+ group_info.add_end (el)
+ if not group_info.is_empty ():
+ staves.append (group_info)
+
+ # 2) Now, detect the groups:
+ group_starts = []
+ pos = 0
+ while pos < len (staves):
+ el = staves[pos]
+ if isinstance (el, PartGroupInfo):
+ prev_start = 0
+ if len (group_starts) > 0:
+ prev_start = group_starts[-1]
+ elif len (el.end) > 0: # no group to end here
+ el.end = {}
+ if len (el.end) > 0: # closes an existing group
+ ends = el.end.keys ()
+ prev_started = staves[prev_start].start.keys ()
+ grpid = None
+ intersection = filter(lambda x:x in ends, prev_started)
+ if len (intersection) > 0:
+ grpid = intersection[0]
+ else:
+ # Close the last started group
+ grpid = staves[prev_start].start.keys () [0]
+ # Find the corresponding closing tag and remove it!
+ j = pos + 1
+ foundclosing = False
+ while j < len (staves) and not foundclosing:
+ if isinstance (staves[j], PartGroupInfo) and staves[j].end.has_key (grpid):
+ foundclosing = True
+ del staves[j].end[grpid]
+ if staves[j].is_empty ():
+ del staves[j]
+ j += 1
+ grpobj = staves[prev_start].start[grpid]
+ group = read_score_group (grpobj)
+ # remove the id from both the start and end
+ if el.end.has_key (grpid):
+ del el.end[grpid]
+ del staves[prev_start].start[grpid]
+ if el.is_empty ():
+ del staves[pos]
+ # replace the staves with the whole group
+ for j in staves[(prev_start + 1):pos]:
+ if j.is_group:
+ j.stafftype = "InnerStaffGroup"
+ group.append_staff (j)
+ del staves[(prev_start + 1):pos]
+ staves.insert (prev_start + 1, group)
+ # reset pos so that we continue at the correct position
+ pos = prev_start
+ # remove an empty start group
+ if staves[prev_start].is_empty ():
+ del staves[prev_start]
+ group_starts.remove (prev_start)
+ pos -= 1
+ elif len (el.start) > 0: # starts new part groups
+ group_starts.append (pos)
+ pos += 1
+
+ if len (staves) == 1:
+ return staves[0]
+ for i in staves:
+ layout.append_staff (i)