Undoing multi-voice paste does not produce multi-voice rest on previously occupied note

• Sep 17, 2011 - 07:27
Type
Functional
Severity
S4 - Minor
Status
closed
Project

MuseScore 1.1 and trunk 4797

  1. Create a measure with a quarter note in voice 1 and a quarter note in voice 2 (or voice 3 or voice 4)
  2. Select and copy those notes and paste them into the 2nd beat of the measure -- all is well so far; the notes will overwrite the rests for that beat
  3. undo the paste and notice that rest for the secondary voice is not restored.

Expected result: voice 2 should be complete after undo.

First reported by mtherieau


Comments

Trying to isolate further--just leaving some notes on how far I got. Have checked out and built the 0-9-6 branch and run in debug mode. The fault here seems to be during the paste operation, when pasteStaff() calls makeGap1() to clear out pre-existing elements in the selection, the elements in voice 2 are not removed. This bit seems to be key as the end result seems to be missing steps when undoing.

Also I'll note that a bit further on in PasteStaff() when inserting the Chord into voice 2, there is a debug complaint from Segment::Add() that "there is already an Rest at..." but it continues with the paste operation by overwriting the existing element. The paste succeeds, but apparently this overwrite is not tracked in the undo-history. Likely this is downstream from the root issue in makeGap1() (or possibly in makeGap()) ... will continue to investigate.

I think the issue does lie within makeGap1(). I see this line where the first ChordRest of the selection is obtained...

cr = static_cast(seg->element(staffIdx * VOICES));

which I believe is the way to retrieve the voice1 ChordRest element...
and these lines that obtain the first ChordRest of a subsequent measure in the selection...

// go to next cr
Measure* m = cr->measure()->nextMeasure();
...
Segment* s = m->firstCRSegment();
int track = cr->track();
cr = static_cast(s->element(track));

where I believe track continues to be voice 1. makeGap1() seems to have no ability to "make a gap" for the secondary voices.

I believe the remediation for this is issue is to add extra logic to "make a gap" for the secondary voices, but am unsure whether that type of loop belongs inside makeGap1() or whether it would be better implemented inside pasteStaff(). If pasteStaff() implements this loop, then I think makeGap1() would then need a track/voice argument to do its work.

Note: I also don't know enough about selections to know whether it's even possible for a selection to contain a subset of the voices or whether a selection always contains all voices. Will study pasteStaff() a little more closely to see if there are hints there.