Skip to content

Commit

Permalink
Merge pull request #3564 from dmitrio95/bugfix/flute_0_crash
Browse files Browse the repository at this point in the history
fix #222031: remove ties and spanners when removing induvidual notes within a chord
  • Loading branch information
anatoly-os committed Jun 2, 2018
2 parents 27d8af4 + 1b8679d commit be5d711
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 25 deletions.
10 changes: 2 additions & 8 deletions libmscore/chord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,10 +444,7 @@ void Chord::add(Element* e)
}
if (!found)
_notes.push_back(note);
if (note->tieFor()) {
if (note->tieFor()->endNote())
note->tieFor()->endNote()->setTieBack(note->tieFor());
}
note->connectTiedNotes();
if (voice() && measure() && note->visible())
measure()->setHasVoices(staffIdx(), true);
}
Expand Down Expand Up @@ -529,10 +526,7 @@ void Chord::remove(Element* e)
auto i = std::find(_notes.begin(), _notes.end(), note);
if (i != _notes.end()) {
_notes.erase(i);
if (note->tieFor()) {
if (note->tieFor()->endNote())
note->tieFor()->endNote()->setTieBack(0);
}
note->disconnectTiedNotes();
for (Spanner* s : note->spannerBack())
note->removeSpannerBack(s);
for (Spanner* s : note->spannerFor())
Expand Down
30 changes: 30 additions & 0 deletions libmscore/note.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3181,6 +3181,36 @@ std::vector<Note*> Note::tiedNotes() const
return notes;
}

//---------------------------------------------------------
// disconnectTiedNotes
//---------------------------------------------------------

void Note::disconnectTiedNotes()
{
if (tieBack() && tieBack()->startNote()) {
tieBack()->startNote()->remove(tieBack());
}
if (tieFor() && tieFor()->endNote()) {
tieFor()->endNote()->setTieBack(0);
}
}

//---------------------------------------------------------
// connectTiedNotes
//---------------------------------------------------------

void Note::connectTiedNotes()
{
if (tieBack()) {
tieBack()->setEndNote(this);
if (tieBack()->startNote())
tieBack()->startNote()->add(tieBack());
}
if (tieFor() && tieFor()->endNote()) {
tieFor()->endNote()->setTieBack(tieFor());
}
}

//---------------------------------------------------------
// accidentalType
//---------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions libmscore/note.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,8 @@ class Note final : public Element {
void setTieBack(Tie* t) { _tieBack = t; }
Note* firstTiedNote() const;
const Note* lastTiedNote() const;
void disconnectTiedNotes();
void connectTiedNotes();

Chord* chord() const { return (Chord*)parent(); }
void setChord(Chord* a) { setParent((Element*)a); }
Expand Down
45 changes: 28 additions & 17 deletions libmscore/undo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,26 @@ const char* AddElement::name() const
return buffer;
}

//---------------------------------------------------------
// removeNote
// Helper function for RemoveElement class
//---------------------------------------------------------

static void removeNote(const Note* note)
{
Score* score = note->score();
if (note->tieFor() && note->tieFor()->endNote())
score->undo(new RemoveElement(note->tieFor()));
if (note->tieBack())
score->undo(new RemoveElement(note->tieBack()));
for (Spanner* s : note->spannerBack()) {
score->undo(new RemoveElement(s));
}
for (Spanner* s : note->spannerFor()) {
score->undo(new RemoveElement(s));

This comment has been minimized.

Copy link
@Ji2z

Ji2z Jun 4, 2018

Is this Dynamic allocation?? (because of 'new')
If it is, why don't you use 'delete'??

This comment has been minimized.

Copy link
@lasconic

lasconic Jun 4, 2018

Contributor

Commands put in the undo stack shouldn't be deleted or they can't be undone ;) They are deleted in the destructor of the undo stack.

}
}

//---------------------------------------------------------
// RemoveElement
//---------------------------------------------------------
Expand All @@ -601,19 +621,15 @@ RemoveElement::RemoveElement(Element* e)
score->undo(new RemoveElement(tremolo));
}
for (const Note* note : chord->notes()) {
if (note->tieFor() && note->tieFor()->endNote())
score->undo(new RemoveElement(note->tieFor()));
if (note->tieBack())
score->undo(new RemoveElement(note->tieBack()));
for (Spanner* s : note->spannerBack()) {
score->undo(new RemoveElement(s));
}
for (Spanner* s : note->spannerFor()) {
score->undo(new RemoveElement(s));
}
removeNote(note);
}
}
}
else if (element->isNote()) {
// Removing an individual note within a chord
const Note* note = toNote(element);
removeNote(note);
}
}

//---------------------------------------------------------
Expand All @@ -640,10 +656,7 @@ void RemoveElement::undo(EditData*)
if (element->isChord()) {
Chord* chord = toChord(element);
for (Note* note : chord->notes()) {
if (note->tieBack())
note->tieBack()->setEndNote(note);
if (note->tieFor() && note->tieFor()->endNote())
note->tieFor()->endNote()->setTieBack(note->tieFor());
note->connectTiedNotes();
}
}
undoAddTuplet(toChordRest(element));
Expand All @@ -667,9 +680,7 @@ void RemoveElement::redo(EditData*)
if (element->isChord()) {
Chord* chord = toChord(element);
for (Note* note : chord->notes()) {
if (note->tieFor() && note->tieFor()->endNote()) {
note->tieFor()->endNote()->setTieBack(0);
}
note->disconnectTiedNotes();
}
}
}
Expand Down

0 comments on commit be5d711

Please sign in to comment.