From 1b736ba3e7d3b4123cb0a1cf724c3874c1bcb63b Mon Sep 17 00:00:00 2001 From: Dmitri Ovodok Date: Tue, 20 Mar 2018 19:34:19 +0300 Subject: [PATCH] fix #222031: remove ties and spanners when removing induvidual notes within a chord (patch backport to 2.3) --- libmscore/chord.cpp | 10 ++-------- libmscore/note.cpp | 30 ++++++++++++++++++++++++++++++ libmscore/note.h | 2 ++ libmscore/undo.cpp | 45 ++++++++++++++++++++++++++++----------------- 4 files changed, 62 insertions(+), 25 deletions(-) diff --git a/libmscore/chord.cpp b/libmscore/chord.cpp index 0e182d1be996..1bb764ef3f99 100644 --- a/libmscore/chord.cpp +++ b/libmscore/chord.cpp @@ -424,10 +424,7 @@ void Chord::add(Element* e) } if (!found) _notes.append(note); - if (note->tieFor()) { - if (note->tieFor()->endNote()) - note->tieFor()->endNote()->setTieBack(note->tieFor()); - } + note->connectTiedNotes(); if (voice() && measure() && note->visible()) measure()->mstaff(staffIdx())->hasVoices = true; } @@ -504,10 +501,7 @@ void Chord::remove(Element* e) { Note* note = static_cast(e); if (_notes.removeOne(note)) { - if (note->tieFor()) { - if (note->tieFor()->endNote()) - note->tieFor()->endNote()->setTieBack(0); - } + note->disconnectTiedNotes(); for (Spanner* s : note->spannerBack()) { note->removeSpannerBack(s); } diff --git a/libmscore/note.cpp b/libmscore/note.cpp index 65f974aa9457..cd148574e6f4 100644 --- a/libmscore/note.cpp +++ b/libmscore/note.cpp @@ -2873,6 +2873,36 @@ QList 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 //--------------------------------------------------------- diff --git a/libmscore/note.h b/libmscore/note.h index efed3cdee6e8..2e0286787956 100644 --- a/libmscore/note.h +++ b/libmscore/note.h @@ -359,6 +359,8 @@ class Note : public Element { Note* firstTiedNote() const; Note* lastTiedNote() const; QList tiedNotes() const; + void disconnectTiedNotes(); + void connectTiedNotes(); Chord* chord() const { return (Chord*)parent(); } void setChord(Chord* a) { setParent((Element*)a); } diff --git a/libmscore/undo.cpp b/libmscore/undo.cpp index f58957afb612..19ea888c6d8b 100644 --- a/libmscore/undo.cpp +++ b/libmscore/undo.cpp @@ -1596,6 +1596,26 @@ const char* AddElement::name() const } #endif +//--------------------------------------------------------- +// 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)); + } + } + //--------------------------------------------------------- // RemoveElement //--------------------------------------------------------- @@ -1647,19 +1667,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 (e->type() == Element::Type::NOTE) { + // Removing an individual note within a chord + const Note* note = static_cast(e); + removeNote(note); + } } //--------------------------------------------------------- @@ -1687,10 +1703,7 @@ void RemoveElement::undo() if (element->type() == Element::Type::CHORD) { Chord* chord = static_cast(element); foreach(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(static_cast(element)); @@ -1710,9 +1723,7 @@ void RemoveElement::redo() if (element->type() == Element::Type::CHORD) { Chord* chord = static_cast(element); foreach(Note* note, chord->notes()) { - if (note->tieFor() && note->tieFor()->endNote()) { - note->tieFor()->endNote()->setTieBack(0); - } + note->disconnectTiedNotes(); } } }