From 8e80dac5dbe8091c1fcbbc9bcdd6cc9641507e6b Mon Sep 17 00:00:00 2001 From: James Mizen Date: Mon, 6 Jan 2025 08:49:03 +0000 Subject: [PATCH 01/11] Further review fixes --- src/engraving/dom/tie.cpp | 48 +++++++++++-------- src/engraving/dom/tie.h | 2 +- .../NotationScene/internal/CapoPopup.qml | 2 +- .../NotationScene/internal/HarpPedalPopup.qml | 2 +- .../internal/PartialTiePopup.qml | 2 +- .../internal/StringTuningsPopup.qml | 2 +- .../qml/MuseScore/Playback/SoundFlagPopup.qml | 2 +- 7 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/engraving/dom/tie.cpp b/src/engraving/dom/tie.cpp index a43809274d19a..b52b7a06ffb93 100644 --- a/src/engraving/dom/tie.cpp +++ b/src/engraving/dom/tie.cpp @@ -217,19 +217,21 @@ Tie::Tie(const ElementType& type, EngravingItem* parent) void Tie::updatePossibleJumpPoints() { - const Note* note = toNote(parentItem()); - const Chord* chord = note->chord(); - const Measure* measure = chord->measure(); if (!tieJumpPoints()) { return; } tieJumpPoints()->clear(); + const Note* note = toNote(parentItem()); + const Chord* chord = note->chord(); + if (!chord->hasFollowingJumpItem()) { return; } + const Measure* measure = chord->measure(); + int jumpPointIdx = 0; Note* nextNote = searchTieNote(note); @@ -276,7 +278,7 @@ void Tie::addTiesToJumpPoints() jumpPoint->undoSetActive(true); continue; } - jumpPoints->addTieToScore(jumpPoint); + jumpPoints->undoAddTieToScore(jumpPoint); } } @@ -482,10 +484,10 @@ const String TieJumpPoint::menuTitle() const { const Measure* measure = m_note->findMeasure(); const int measureNo = measure ? measure->no() + 1 : 0; - const TranslatableString tieTo("engraving", "Tie to "); - const String title = tieTo.str + precedingJumpItemName() + u" " + muse::mtrc("engraving", "(m. %1)").arg(measureNo); + const String measureStr = String::fromStdString(std::to_string(measureNo)); - return title; + //: %1 represents the preceding jump item eg. coda. %2 represents the measure number + return muse::mtrc("engraving", "Tie to %1 (m. %2)").arg(precedingJumpItemName(), measureStr); } String TieJumpPoint::precedingJumpItemName() const @@ -495,7 +497,8 @@ String TieJumpPoint::precedingJumpItemName() const const Measure* measure = seg->measure(); if (seg->score()->firstSegment(SegmentType::ChordRest) == seg) { - return muse::mtrc("engraving", "start of score"); + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "start of score", "partial tie menu"); } // Markers @@ -510,9 +513,11 @@ String TieJumpPoint::precedingJumpItemName() const } if (marker->markerType() == MarkerType::CODA || marker->markerType() == MarkerType::VARCODA) { - return muse::mtrc("engraving", "coda"); + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "coda", "partial tie menu"); } else { - return muse::mtrc("engraving", "segno"); + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "segno", "partial tie menu"); } } @@ -525,12 +530,14 @@ String TieJumpPoint::precedingJumpItemName() const Volta* volta = toVolta(spanner.value); - return muse::mtrc("engraving", "“%1” volta").arg(volta->beginText()); + //: Used at %1 in the string "Tie to %1 (m. %2)". %1 in this string represents the volta's text set by the user + return muse::mtrc("engraving", "“%1” volta", "partial tie menu").arg(volta->beginText()); } // Repeat barlines if (measure->repeatStart()) { - return muse::mtrc("engraving", "start repeat"); + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "start repeat", "partial tie menu"); } for (Segment* prevSeg = seg->prev(SegmentType::BarLineType); prevSeg && prevSeg->tick() == seg->tick(); @@ -542,15 +549,18 @@ String TieJumpPoint::precedingJumpItemName() const BarLine* bl = toBarLine(el); if (bl->barLineType() & (BarLineType::START_REPEAT | BarLineType::END_START_REPEAT)) { - return muse::mtrc("engraving", "start repeat"); + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "start repeat", "partial tie menu"); } } if (m_note->tieBack() && m_note->tieBack()->startNote()) { - return muse::mtrc("engraving", "next note"); + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "next note", "partial tie menu"); } - return muse::mtrc("engraving", "invalid"); + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "invalid", "partial tie menu"); } //--------------------------------------------------------- @@ -613,12 +623,12 @@ void TieJumpPointList::toggleJumpPoint(const String& id) if (checked) { undoRemoveTieFromScore(end); } else { - addTieToScore(end); + undoAddTieToScore(end); } score->endCmd(); } -void TieJumpPointList::addTieToScore(TieJumpPoint* jumpPoint) +void TieJumpPointList::undoAddTieToScore(TieJumpPoint* jumpPoint) { Note* note = jumpPoint->note(); Score* score = note ? note->score() : nullptr; @@ -697,8 +707,8 @@ Tie* Tie::changeTieType(Tie* oldTie, Note* endNote) return nullptr; } - TranslatableString undoCmd = addPartialTie ? TranslatableString("engraving", "Replace full tie with partial tie") : TranslatableString( - "engraving", "Replace partial tie with full tie"); + TranslatableString undoCmd = addPartialTie ? TranslatableString("engraving", "Replace full tie with partial tie") + : TranslatableString("engraving", "Replace partial tie with full tie"); Tie* newTie = addPartialTie ? Factory::createPartialTie(score->dummy()->note()) : Factory::createTie(score->dummy()->note()); score->undoRemoveElement(oldTie); diff --git a/src/engraving/dom/tie.h b/src/engraving/dom/tie.h index d2ca9e4c3c81c..729d8398b4e4f 100644 --- a/src/engraving/dom/tie.h +++ b/src/engraving/dom/tie.h @@ -70,7 +70,7 @@ class TieJumpPointList TieJumpPoint* findJumpPoint(const String& id); void toggleJumpPoint(const String& id); - void addTieToScore(TieJumpPoint* jumpPoint); + void undoAddTieToScore(TieJumpPoint* jumpPoint); void undoRemoveTieFromScore(TieJumpPoint* jumpPoint); std::vector::iterator begin() { return m_jumpPoints.begin(); } diff --git a/src/notation/qml/MuseScore/NotationScene/internal/CapoPopup.qml b/src/notation/qml/MuseScore/NotationScene/internal/CapoPopup.qml index b8bcea7a0b52e..0b88bb4e1d317 100644 --- a/src/notation/qml/MuseScore/NotationScene/internal/CapoPopup.qml +++ b/src/notation/qml/MuseScore/NotationScene/internal/CapoPopup.qml @@ -33,7 +33,7 @@ StyledPopupView { property alias navigationOrderStart: capoSettingsNavPanel.order readonly property alias navigationOrderEnd: capoSettingsNavPanel.order - property QtObject model: capoModel + readonly property alias model: capoModel contentWidth: content.width diff --git a/src/notation/qml/MuseScore/NotationScene/internal/HarpPedalPopup.qml b/src/notation/qml/MuseScore/NotationScene/internal/HarpPedalPopup.qml index dd8d398606fa7..56569e859c5e8 100644 --- a/src/notation/qml/MuseScore/NotationScene/internal/HarpPedalPopup.qml +++ b/src/notation/qml/MuseScore/NotationScene/internal/HarpPedalPopup.qml @@ -30,7 +30,7 @@ import MuseScore.NotationScene 1.0 StyledPopupView { id: root - property QtObject model: harpModel + readonly property alias model: harpModel property variant pedalState: harpModel.pedalState diff --git a/src/notation/qml/MuseScore/NotationScene/internal/PartialTiePopup.qml b/src/notation/qml/MuseScore/NotationScene/internal/PartialTiePopup.qml index bc9dc8944e6bd..d17f1fe34e0fa 100644 --- a/src/notation/qml/MuseScore/NotationScene/internal/PartialTiePopup.qml +++ b/src/notation/qml/MuseScore/NotationScene/internal/PartialTiePopup.qml @@ -36,7 +36,7 @@ StyledPopupView { property alias navigationOrderStart: partialTieNavPanel.order readonly property alias navigationOrderEnd: partialTieNavPanel.order - property QtObject model: partialTiePopupModel + readonly property alias model: partialTiePopupModel showArrow: false diff --git a/src/notation/qml/MuseScore/NotationScene/internal/StringTuningsPopup.qml b/src/notation/qml/MuseScore/NotationScene/internal/StringTuningsPopup.qml index eb7689150d103..dadd85897ef7c 100644 --- a/src/notation/qml/MuseScore/NotationScene/internal/StringTuningsPopup.qml +++ b/src/notation/qml/MuseScore/NotationScene/internal/StringTuningsPopup.qml @@ -33,7 +33,7 @@ StyledPopupView { property alias navigationOrderStart: navPanel.order readonly property alias navigationOrderEnd: navPanel.order - property QtObject model: stringTuningsModel + readonly property alias model: stringTuningsModel contentWidth: content.width diff --git a/src/playback/qml/MuseScore/Playback/SoundFlagPopup.qml b/src/playback/qml/MuseScore/Playback/SoundFlagPopup.qml index 6fee516b39f90..20266afe0977a 100644 --- a/src/playback/qml/MuseScore/Playback/SoundFlagPopup.qml +++ b/src/playback/qml/MuseScore/Playback/SoundFlagPopup.qml @@ -36,7 +36,7 @@ StyledPopupView { property alias navigationOrderStart: navPanel.order readonly property alias navigationOrderEnd: museSoundsParams.navigationPanelOrderEnd - property QtObject model: soundFlagModel + readonly property alias model: soundFlagModel contentWidth: content.width contentHeight: content.childrenRect.height From dad08f43e51e59ac4613f40cf8b3e3704391abad Mon Sep 17 00:00:00 2001 From: James Mizen Date: Tue, 7 Jan 2025 12:03:01 +0000 Subject: [PATCH 02/11] Move TieJumpPoint code to its own file --- src/engraving/dom/dom.cmake | 2 + src/engraving/dom/note.h | 1 + src/engraving/dom/tie.cpp | 257 ++---------------------- src/engraving/dom/tie.h | 62 +----- src/engraving/dom/tiejumppointlist.cpp | 260 +++++++++++++++++++++++++ src/engraving/dom/tiejumppointlist.h | 70 +++++++ 6 files changed, 347 insertions(+), 305 deletions(-) create mode 100644 src/engraving/dom/tiejumppointlist.cpp create mode 100644 src/engraving/dom/tiejumppointlist.h diff --git a/src/engraving/dom/dom.cmake b/src/engraving/dom/dom.cmake index 2b0e6475c06b7..a1ecb4c5572d3 100644 --- a/src/engraving/dom/dom.cmake +++ b/src/engraving/dom/dom.cmake @@ -343,6 +343,8 @@ set(DOM_SRC ${CMAKE_CURRENT_LIST_DIR}/textlinebase.h ${CMAKE_CURRENT_LIST_DIR}/tie.cpp ${CMAKE_CURRENT_LIST_DIR}/tie.h + ${CMAKE_CURRENT_LIST_DIR}/tiejumppointlist.cpp + ${CMAKE_CURRENT_LIST_DIR}/tiejumppointlist.h ${CMAKE_CURRENT_LIST_DIR}/tiemap.h ${CMAKE_CURRENT_LIST_DIR}/timesig.cpp ${CMAKE_CURRENT_LIST_DIR}/timesig.h diff --git a/src/engraving/dom/note.h b/src/engraving/dom/note.h index dd105f1656d60..41cae8eae3f6b 100644 --- a/src/engraving/dom/note.h +++ b/src/engraving/dom/note.h @@ -36,6 +36,7 @@ #include "pitchspelling.h" #include "symbol.h" #include "tie.h" +#include "tiejumppointlist.h" #include "types.h" namespace mu::engraving { diff --git a/src/engraving/dom/tie.cpp b/src/engraving/dom/tie.cpp index b52b7a06ffb93..9cf7a4518ff2a 100644 --- a/src/engraving/dom/tie.cpp +++ b/src/engraving/dom/tie.cpp @@ -31,7 +31,6 @@ #include "factory.h" #include "hook.h" #include "ledgerline.h" -#include "marker.h" #include "masterscore.h" #include "measure.h" #include "mscoreview.h" @@ -45,7 +44,7 @@ #include "stafftype.h" #include "stem.h" #include "system.h" -#include "types/typesconv.h" +#include "tiejumppointlist.h" #include "undo.h" #include "utils.h" #include "volta.h" @@ -215,6 +214,11 @@ Tie::Tie(const ElementType& type, EngravingItem* parent) setAnchor(Anchor::NOTE); } +TieJumpPointList* Tie::startTieJumpPoints() const +{ + return m_jumpPoint ? m_jumpPoint->jumpPointList() : nullptr; +} + void Tie::updatePossibleJumpPoints() { if (!tieJumpPoints()) { @@ -453,250 +457,6 @@ bool Tie::isCrossStaff() const || (endChord && (endChord->staffMove() != 0 || endChord->vStaffIdx() != staff)); } -//--------------------------------------------------------- -// PartialTieJumpPoint -//--------------------------------------------------------- - -TieJumpPoint::TieJumpPoint(Note* note, bool active, int idx, bool followingNote) - : m_note(note), m_active(active), m_followingNote(followingNote) -{ - m_id = u"jumpPoint" + String::fromStdString(std::to_string(idx)); - if (active && endTie()) { - endTie()->setJumpPoint(this); - } -} - -Tie* TieJumpPoint::endTie() const -{ - return m_note ? m_note->tieBack() : nullptr; -} - -void TieJumpPoint::undoSetActive(bool v) -{ - Score* score = m_note ? m_note->score() : nullptr; - if (!score || m_active == v) { - return; - } - score->undo(new ChangeTieJumpPointActive(m_jumpPointList, m_id, v)); -} - -const String TieJumpPoint::menuTitle() const -{ - const Measure* measure = m_note->findMeasure(); - const int measureNo = measure ? measure->no() + 1 : 0; - const String measureStr = String::fromStdString(std::to_string(measureNo)); - - //: %1 represents the preceding jump item eg. coda. %2 represents the measure number - return muse::mtrc("engraving", "Tie to %1 (m. %2)").arg(precedingJumpItemName(), measureStr); -} - -String TieJumpPoint::precedingJumpItemName() const -{ - const Chord* startChord = m_note->chord(); - const Segment* seg = startChord->segment(); - const Measure* measure = seg->measure(); - - if (seg->score()->firstSegment(SegmentType::ChordRest) == seg) { - //: Used at %1 in the string "Tie to %1 (m. %2)" - return muse::mtrc("engraving", "start of score", "partial tie menu"); - } - - // Markers - for (const EngravingItem* e : measure->el()) { - if (!e->isMarker()) { - continue; - } - - const Marker* marker = toMarker(e); - if (muse::contains(Marker::RIGHT_MARKERS, marker->markerType())) { - continue; - } - - if (marker->markerType() == MarkerType::CODA || marker->markerType() == MarkerType::VARCODA) { - //: Used at %1 in the string "Tie to %1 (m. %2)" - return muse::mtrc("engraving", "coda", "partial tie menu"); - } else { - //: Used at %1 in the string "Tie to %1 (m. %2)" - return muse::mtrc("engraving", "segno", "partial tie menu"); - } - } - - // Voltas - auto spanners = m_note->score()->spannerMap().findOverlapping(measure->tick().ticks(), measure->tick().ticks()); - for (auto& spanner : spanners) { - if (!spanner.value->isVolta() || Fraction::fromTicks(spanner.start) != startChord->tick()) { - continue; - } - - Volta* volta = toVolta(spanner.value); - - //: Used at %1 in the string "Tie to %1 (m. %2)". %1 in this string represents the volta's text set by the user - return muse::mtrc("engraving", "“%1” volta", "partial tie menu").arg(volta->beginText()); - } - - // Repeat barlines - if (measure->repeatStart()) { - //: Used at %1 in the string "Tie to %1 (m. %2)" - return muse::mtrc("engraving", "start repeat", "partial tie menu"); - } - - for (Segment* prevSeg = seg->prev(SegmentType::BarLineType); prevSeg && prevSeg->tick() == seg->tick(); - prevSeg = prevSeg->prev(SegmentType::BarLineType)) { - EngravingItem* el = prevSeg->element(startChord->track()); - if (!el || !el->isBarLine()) { - continue; - } - - BarLine* bl = toBarLine(el); - if (bl->barLineType() & (BarLineType::START_REPEAT | BarLineType::END_START_REPEAT)) { - //: Used at %1 in the string "Tie to %1 (m. %2)" - return muse::mtrc("engraving", "start repeat", "partial tie menu"); - } - } - - if (m_note->tieBack() && m_note->tieBack()->startNote()) { - //: Used at %1 in the string "Tie to %1 (m. %2)" - return muse::mtrc("engraving", "next note", "partial tie menu"); - } - - //: Used at %1 in the string "Tie to %1 (m. %2)" - return muse::mtrc("engraving", "invalid", "partial tie menu"); -} - -//--------------------------------------------------------- -// PartialTieJumpPointList -//--------------------------------------------------------- - -TieJumpPointList::~TieJumpPointList() -{ - muse::DeleteAll(m_jumpPoints); - m_jumpPoints.clear(); -} - -void TieJumpPointList::add(TieJumpPoint* item) -{ - item->setJumpPointList(this); - m_jumpPoints.push_back(item); -} - -void TieJumpPointList::clear() -{ - for (const TieJumpPoint* jumpPoint : m_jumpPoints) { - Tie* endTie = jumpPoint->endTie(); - if (!endTie) { - continue; - } - endTie->setJumpPoint(nullptr); - } - muse::DeleteAll(m_jumpPoints); - m_jumpPoints.clear(); -} - -TieJumpPoint* TieJumpPointList::findJumpPoint(const String& id) -{ - for (TieJumpPoint* jumpPoint : m_jumpPoints) { - if (jumpPoint->id() != id) { - continue; - } - - return jumpPoint; - } - return nullptr; -} - -void TieJumpPointList::toggleJumpPoint(const String& id) -{ - TieJumpPoint* end = findJumpPoint(id); - - if (!end) { - LOGE() << "No partial tie end point found with id: " << id; - return; - } - - Score* score = end->note() ? end->note()->score() : nullptr; - if (!score) { - return; - } - - score->startCmd(TranslatableString("engraving", "Toggle partial tie")); - const bool checked = end->active(); - if (checked) { - undoRemoveTieFromScore(end); - } else { - undoAddTieToScore(end); - } - score->endCmd(); -} - -void TieJumpPointList::undoAddTieToScore(TieJumpPoint* jumpPoint) -{ - Note* note = jumpPoint->note(); - Score* score = note ? note->score() : nullptr; - if (!m_startTie || !score) { - return; - } - - if (jumpPoint->followingNote()) { - // Remove partial tie and add full tie - if (!m_startTie->isPartialTie() || !toPartialTie(m_startTie)->isOutgoing()) { - return; - } - jumpPoint->undoSetActive(true); - m_startTie = Tie::changeTieType(m_startTie, note); - return; - } - - jumpPoint->undoSetActive(true); - - // Check if there is already a tie. If so, add partial tie info to it - Tie* tieBack = note->tieBack(); - if (tieBack && !tieBack->isPartialTie()) { - tieBack->setJumpPoint(jumpPoint); - return; - } - // Otherwise create incoming partial tie on note - PartialTie* pt = Factory::createPartialTie(note); - pt->setParent(note); - pt->setEndNote(note); - pt->setJumpPoint(jumpPoint); - score->undoAddElement(pt); -} - -void TieJumpPointList::undoRemoveTieFromScore(TieJumpPoint* jumpPoint) -{ - Note* note = jumpPoint->note(); - Score* score = note ? note->score() : nullptr; - if (!m_startTie || !score) { - return; - } - - if (jumpPoint->followingNote()) { - // Remove full tie and add partial tie - if (m_startTie->isPartialTie()) { - return; - } - jumpPoint->undoSetActive(false); - - m_startTie = Tie::changeTieType(m_startTie); - return; - } - - jumpPoint->undoSetActive(false); - - // Check if there is a full tie. If so, remove partial tie info from it - Tie* tieBack = note->tieBack(); - if (tieBack && !tieBack->isPartialTie()) { - tieBack->setJumpPoint(nullptr); - return; - } - // Otherwise remove incoming partial tie on note - PartialTie* pt = note->incomingPartialTie(); - if (!pt) { - return; - } - score->undoRemoveElement(pt); -} - Tie* Tie::changeTieType(Tie* oldTie, Note* endNote) { // Replaces oldTie with an outgoing partial tie if no endNote is specified. Otherwise replaces oldTie with a regular tie @@ -749,4 +509,9 @@ void Tie::updateStartTieOnRemoval() score()->undoRemoveElement(_startTie); } } + +Tie* Tie::startTie() const +{ + return startTieJumpPoints() ? startTieJumpPoints()->startTie() : nullptr; +} } diff --git a/src/engraving/dom/tie.h b/src/engraving/dom/tie.h index 729d8398b4e4f..3bd577c8131aa 100644 --- a/src/engraving/dom/tie.h +++ b/src/engraving/dom/tie.h @@ -26,63 +26,7 @@ namespace mu::engraving { class TieJumpPointList; -class TieJumpPoint -{ -public: - TieJumpPoint(Note* note, bool active, int idx, bool followingNote); - TieJumpPoint() {} - - Note* note() const { return m_note; } - Tie* endTie() const; - bool followingNote() const { return m_followingNote; } - const String& id() const { return m_id; } - bool active() const { return m_active; } - void setActive(bool v) { m_active = v; } - void undoSetActive(bool v); - void setJumpPointList(TieJumpPointList* jumpPointList) { m_jumpPointList = jumpPointList; } - TieJumpPointList* jumpPointList() { return m_jumpPointList; } - - const String menuTitle() const; - -private: - String precedingJumpItemName() const; - Note* m_note = nullptr; - bool m_active = false; - String m_id; - TieJumpPointList* m_jumpPointList = nullptr; - bool m_followingNote = false; -}; - -class TieJumpPointList -{ -public: - TieJumpPointList() = default; - ~TieJumpPointList(); - - void add(TieJumpPoint* item); - void clear(); - size_t size() const { return m_jumpPoints.size(); } - bool empty() const { return m_jumpPoints.empty(); } - - void setStartTie(Tie* startTie) { m_startTie = startTie; } - Tie* startTie() const { return m_startTie; } - - TieJumpPoint* findJumpPoint(const String& id); - void toggleJumpPoint(const String& id); - - void undoAddTieToScore(TieJumpPoint* jumpPoint); - void undoRemoveTieFromScore(TieJumpPoint* jumpPoint); - - std::vector::iterator begin() { return m_jumpPoints.begin(); } - std::vector::const_iterator begin() const { return m_jumpPoints.begin(); } - std::vector::iterator end() { return m_jumpPoints.end(); } - std::vector::const_iterator end() const { return m_jumpPoints.end(); } - -private: - std::vector m_jumpPoints; - Tie* m_startTie = nullptr; -}; - +class TieJumpPoint; //--------------------------------------------------------- // @@ TieSegment /// a single segment of a tie @@ -189,7 +133,7 @@ class Tie : public SlurTie void setJumpPoint(TieJumpPoint* jumpPoint) { m_jumpPoint = jumpPoint; } void updateStartTieOnRemoval(); TieJumpPoint* jumpPoint() const { return m_jumpPoint; } - Tie* startTie() const { return startTieJumpPoints() ? startTieJumpPoints()->startTie() : nullptr; } + Tie* startTie() const; static Tie* changeTieType(Tie* oldTie, Note* endNote = nullptr); @@ -201,6 +145,6 @@ class Tie : public SlurTie // Jump point information for incoming ties after repeats TieJumpPoint* m_jumpPoint = nullptr; - TieJumpPointList* startTieJumpPoints() const { return m_jumpPoint ? m_jumpPoint->jumpPointList() : nullptr; } + TieJumpPointList* startTieJumpPoints() const; }; } // namespace mu::engraving diff --git a/src/engraving/dom/tiejumppointlist.cpp b/src/engraving/dom/tiejumppointlist.cpp new file mode 100644 index 0000000000000..e35ef90c44de3 --- /dev/null +++ b/src/engraving/dom/tiejumppointlist.cpp @@ -0,0 +1,260 @@ +#include "tiejumppointlist.h" + +#include "barline.h" +#include "chord.h" +#include "factory.h" +#include "marker.h" +#include "measure.h" +#include "note.h" +#include "partialtie.h" +#include "score.h" +#include "segment.h" +#include "tie.h" +#include "undo.h" +#include "volta.h" + +using namespace mu::engraving; + +//--------------------------------------------------------- +// TieJumpPoint +//--------------------------------------------------------- + +TieJumpPoint::TieJumpPoint(Note* note, bool active, int idx, bool followingNote) + : m_note(note), m_active(active), m_followingNote(followingNote) +{ + m_id = u"jumpPoint" + String::fromStdString(std::to_string(idx)); + if (active && endTie()) { + endTie()->setJumpPoint(this); + } +} + +Tie* TieJumpPoint::endTie() const +{ + return m_note ? m_note->tieBack() : nullptr; +} + +void TieJumpPoint::undoSetActive(bool v) +{ + Score* score = m_note ? m_note->score() : nullptr; + if (!score || m_active == v) { + return; + } + score->undo(new ChangeTieJumpPointActive(m_jumpPointList, m_id, v)); +} + +const String TieJumpPoint::menuTitle() const +{ + const Measure* measure = m_note->findMeasure(); + const int measureNo = measure ? measure->no() + 1 : 0; + const String measureStr = String::fromStdString(std::to_string(measureNo)); + + //: %1 represents the preceding jump item eg. coda. %2 represents the measure number + return muse::mtrc("engraving", "Tie to %1 (m. %2)").arg(precedingJumpItemName(), measureStr); +} + +String TieJumpPoint::precedingJumpItemName() const +{ + const Chord* startChord = m_note->chord(); + const Segment* seg = startChord->segment(); + const Measure* measure = seg->measure(); + + if (seg->score()->firstSegment(SegmentType::ChordRest) == seg) { + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "start of score", "partial tie menu"); + } + + // Markers + for (const EngravingItem* e : measure->el()) { + if (!e->isMarker()) { + continue; + } + + const Marker* marker = toMarker(e); + if (muse::contains(Marker::RIGHT_MARKERS, marker->markerType())) { + continue; + } + + if (marker->markerType() == MarkerType::CODA || marker->markerType() == MarkerType::VARCODA) { + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "coda", "partial tie menu"); + } else { + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "segno", "partial tie menu"); + } + } + + // Voltas + auto spanners = m_note->score()->spannerMap().findOverlapping(measure->tick().ticks(), measure->tick().ticks()); + for (auto& spanner : spanners) { + if (!spanner.value->isVolta() || Fraction::fromTicks(spanner.start) != startChord->tick()) { + continue; + } + + Volta* volta = toVolta(spanner.value); + + //: Used at %1 in the string "Tie to %1 (m. %2)". %1 in this string represents the volta's text set by the user + return muse::mtrc("engraving", "“%1” volta", "partial tie menu").arg(volta->beginText()); + } + + // Repeat barlines + if (measure->repeatStart()) { + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "start repeat", "partial tie menu"); + } + + for (Segment* prevSeg = seg->prev(SegmentType::BarLineType); prevSeg && prevSeg->tick() == seg->tick(); + prevSeg = prevSeg->prev(SegmentType::BarLineType)) { + EngravingItem* el = prevSeg->element(startChord->track()); + if (!el || !el->isBarLine()) { + continue; + } + + BarLine* bl = toBarLine(el); + if (bl->barLineType() & (BarLineType::START_REPEAT | BarLineType::END_START_REPEAT)) { + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "start repeat", "partial tie menu"); + } + } + + if (m_note->tieBack() && m_note->tieBack()->startNote()) { + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "next note", "partial tie menu"); + } + + //: Used at %1 in the string "Tie to %1 (m. %2)" + return muse::mtrc("engraving", "invalid", "partial tie menu"); +} + +//--------------------------------------------------------- +// TieJumpPointList +//--------------------------------------------------------- + +TieJumpPointList::~TieJumpPointList() +{ + muse::DeleteAll(m_jumpPoints); + m_jumpPoints.clear(); +} + +void TieJumpPointList::add(TieJumpPoint* item) +{ + item->setJumpPointList(this); + m_jumpPoints.push_back(item); +} + +void TieJumpPointList::clear() +{ + for (const TieJumpPoint* jumpPoint : m_jumpPoints) { + Tie* endTie = jumpPoint->endTie(); + if (!endTie) { + continue; + } + endTie->setJumpPoint(nullptr); + } + muse::DeleteAll(m_jumpPoints); + m_jumpPoints.clear(); +} + +TieJumpPoint* TieJumpPointList::findJumpPoint(const String& id) +{ + for (TieJumpPoint* jumpPoint : m_jumpPoints) { + if (jumpPoint->id() != id) { + continue; + } + + return jumpPoint; + } + return nullptr; +} + +void TieJumpPointList::toggleJumpPoint(const String& id) +{ + TieJumpPoint* end = findJumpPoint(id); + + if (!end) { + LOGE() << "No partial tie end point found with id: " << id; + return; + } + + Score* score = end->note() ? end->note()->score() : nullptr; + if (!score) { + return; + } + + score->startCmd(TranslatableString("engraving", "Toggle partial tie")); + const bool checked = end->active(); + if (checked) { + undoRemoveTieFromScore(end); + } else { + undoAddTieToScore(end); + } + score->endCmd(); +} + +void TieJumpPointList::undoAddTieToScore(TieJumpPoint* jumpPoint) +{ + Note* note = jumpPoint->note(); + Score* score = note ? note->score() : nullptr; + if (!m_startTie || !score) { + return; + } + + if (jumpPoint->followingNote()) { + // Remove partial tie and add full tie + if (!m_startTie->isPartialTie() || !toPartialTie(m_startTie)->isOutgoing()) { + return; + } + jumpPoint->undoSetActive(true); + m_startTie = Tie::changeTieType(m_startTie, note); + return; + } + + jumpPoint->undoSetActive(true); + + // Check if there is already a tie. If so, add partial tie info to it + Tie* tieBack = note->tieBack(); + if (tieBack && !tieBack->isPartialTie()) { + tieBack->setJumpPoint(jumpPoint); + return; + } + // Otherwise create incoming partial tie on note + PartialTie* pt = Factory::createPartialTie(note); + pt->setParent(note); + pt->setEndNote(note); + pt->setJumpPoint(jumpPoint); + score->undoAddElement(pt); +} + +void TieJumpPointList::undoRemoveTieFromScore(TieJumpPoint* jumpPoint) +{ + Note* note = jumpPoint->note(); + Score* score = note ? note->score() : nullptr; + if (!m_startTie || !score) { + return; + } + + if (jumpPoint->followingNote()) { + // Remove full tie and add partial tie + if (m_startTie->isPartialTie()) { + return; + } + jumpPoint->undoSetActive(false); + + m_startTie = Tie::changeTieType(m_startTie); + return; + } + + jumpPoint->undoSetActive(false); + + // Check if there is a full tie. If so, remove partial tie info from it + Tie* tieBack = note->tieBack(); + if (tieBack && !tieBack->isPartialTie()) { + tieBack->setJumpPoint(nullptr); + return; + } + // Otherwise remove incoming partial tie on note + PartialTie* pt = note->incomingPartialTie(); + if (!pt) { + return; + } + score->undoRemoveElement(pt); +} diff --git a/src/engraving/dom/tiejumppointlist.h b/src/engraving/dom/tiejumppointlist.h new file mode 100644 index 0000000000000..44deb895dff83 --- /dev/null +++ b/src/engraving/dom/tiejumppointlist.h @@ -0,0 +1,70 @@ +#pragma once +#include "global/types/string.h" + +using muse::String; +namespace mu::engraving { +class Note; +class Tie; +class TieJumpPointList; + +// Items of TieJumpPointList +// Stores information about an endpoint +class TieJumpPoint +{ +public: + TieJumpPoint(Note* note, bool active, int idx, bool followingNote); + TieJumpPoint() {} + + Note* note() const { return m_note; } + Tie* endTie() const; + bool followingNote() const { return m_followingNote; } + const String& id() const { return m_id; } + bool active() const { return m_active; } + void setActive(bool v) { m_active = v; } + void undoSetActive(bool v); + void setJumpPointList(TieJumpPointList* jumpPointList) { m_jumpPointList = jumpPointList; } + TieJumpPointList* jumpPointList() { return m_jumpPointList; } + + const String menuTitle() const; + +private: + String precedingJumpItemName() const; + Note* m_note = nullptr; + bool m_active = false; + String m_id; + TieJumpPointList* m_jumpPointList = nullptr; + bool m_followingNote = false; +}; + +// Created & deleted by Note +// Manages adding and removing ties from endpoints +class TieJumpPointList +{ +public: + TieJumpPointList() = default; + ~TieJumpPointList(); + + void add(TieJumpPoint* item); + void clear(); + size_t size() const { return m_jumpPoints.size(); } + bool empty() const { return m_jumpPoints.empty(); } + + void setStartTie(Tie* startTie) { m_startTie = startTie; } + Tie* startTie() const { return m_startTie; } + + TieJumpPoint* findJumpPoint(const String& id); + void toggleJumpPoint(const String& id); + + void undoAddTieToScore(TieJumpPoint* jumpPoint); + void undoRemoveTieFromScore(TieJumpPoint* jumpPoint); + + std::vector::iterator begin() { return m_jumpPoints.begin(); } + std::vector::const_iterator begin() const { return m_jumpPoints.begin(); } + std::vector::iterator end() { return m_jumpPoints.end(); } + std::vector::const_iterator end() const { return m_jumpPoints.end(); } + +private: + std::vector m_jumpPoints; + Tie* m_startTie = nullptr; +}; +} From 1cee2dde18dd8cb67676d4c45b54e4d73227c103 Mon Sep 17 00:00:00 2001 From: James Mizen Date: Tue, 7 Jan 2025 16:31:02 +0000 Subject: [PATCH 03/11] Store pointer to note instead of start tie in TieJumpPointList --- src/engraving/dom/note.cpp | 5 ++-- src/engraving/dom/tie.cpp | 6 ++-- src/engraving/dom/tie.h | 2 +- src/engraving/dom/tiejumppointlist.cpp | 41 ++++++++++++++++++++++---- src/engraving/dom/tiejumppointlist.h | 32 +++++++++++++++++--- 5 files changed, 68 insertions(+), 18 deletions(-) diff --git a/src/engraving/dom/note.cpp b/src/engraving/dom/note.cpp index ba0fefdc9ed23..50dff8e43e5e5 100644 --- a/src/engraving/dom/note.cpp +++ b/src/engraving/dom/note.cpp @@ -549,7 +549,7 @@ NoteHeadGroup NoteHead::headGroup() const //--------------------------------------------------------- Note::Note(Chord* ch) - : EngravingItem(ElementType::NOTE, ch, ElementFlag::MOVABLE) + : EngravingItem(ElementType::NOTE, ch, ElementFlag::MOVABLE), m_jumpPoints(this) { m_playEvents.push_back(NoteEvent()); // add default play event } @@ -599,7 +599,7 @@ std::vector Note::compoundNotes() const } Note::Note(const Note& n, bool link) - : EngravingItem(n) + : EngravingItem(n), m_jumpPoints(this) { if (link) { score()->undo(new Link(this, const_cast(&n))); @@ -2509,7 +2509,6 @@ PartialTie* Note::outgoingPartialTie() const void Note::setTieFor(Tie* t) { m_tieFor = t; - m_jumpPoints.setStartTie(m_tieFor); } void Note::setTieBack(Tie* t) diff --git a/src/engraving/dom/tie.cpp b/src/engraving/dom/tie.cpp index 9cf7a4518ff2a..e829f5baa3e4c 100644 --- a/src/engraving/dom/tie.cpp +++ b/src/engraving/dom/tie.cpp @@ -457,14 +457,14 @@ bool Tie::isCrossStaff() const || (endChord && (endChord->staffMove() != 0 || endChord->vStaffIdx() != staff)); } -Tie* Tie::changeTieType(Tie* oldTie, Note* endNote) +void Tie::changeTieType(Tie* oldTie, Note* endNote) { // Replaces oldTie with an outgoing partial tie if no endNote is specified. Otherwise replaces oldTie with a regular tie Note* startNote = oldTie->startNote(); bool addPartialTie = !endNote; Score* score = startNote ? startNote->score() : nullptr; if (!score) { - return nullptr; + return; } TranslatableString undoCmd = addPartialTie ? TranslatableString("engraving", "Replace full tie with partial tie") @@ -494,8 +494,6 @@ Tie* Tie::changeTieType(Tie* oldTie, Note* endNote) score->undoAddElement(newTie); score->endCmd(); - - return newTie; } void Tie::updateStartTieOnRemoval() diff --git a/src/engraving/dom/tie.h b/src/engraving/dom/tie.h index 3bd577c8131aa..b4c8c60b0eb24 100644 --- a/src/engraving/dom/tie.h +++ b/src/engraving/dom/tie.h @@ -135,7 +135,7 @@ class Tie : public SlurTie TieJumpPoint* jumpPoint() const { return m_jumpPoint; } Tie* startTie() const; - static Tie* changeTieType(Tie* oldTie, Note* endNote = nullptr); + static void changeTieType(Tie* oldTie, Note* endNote = nullptr); protected: Tie(const ElementType& type, EngravingItem* parent = nullptr); diff --git a/src/engraving/dom/tiejumppointlist.cpp b/src/engraving/dom/tiejumppointlist.cpp index e35ef90c44de3..47dbdf957d767 100644 --- a/src/engraving/dom/tiejumppointlist.cpp +++ b/src/engraving/dom/tiejumppointlist.cpp @@ -1,3 +1,25 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "tiejumppointlist.h" #include "barline.h" @@ -154,6 +176,11 @@ void TieJumpPointList::clear() m_jumpPoints.clear(); } +Tie* TieJumpPointList::startTie() const +{ + return m_note ? m_note->tieFor() : nullptr; +} + TieJumpPoint* TieJumpPointList::findJumpPoint(const String& id) { for (TieJumpPoint* jumpPoint : m_jumpPoints) { @@ -194,17 +221,18 @@ void TieJumpPointList::undoAddTieToScore(TieJumpPoint* jumpPoint) { Note* note = jumpPoint->note(); Score* score = note ? note->score() : nullptr; - if (!m_startTie || !score) { + Tie* tie = startTie(); + if (!tie || !score) { return; } if (jumpPoint->followingNote()) { // Remove partial tie and add full tie - if (!m_startTie->isPartialTie() || !toPartialTie(m_startTie)->isOutgoing()) { + if (!tie->isPartialTie() || !toPartialTie(tie)->isOutgoing()) { return; } jumpPoint->undoSetActive(true); - m_startTie = Tie::changeTieType(m_startTie, note); + Tie::changeTieType(tie, note); return; } @@ -228,18 +256,19 @@ void TieJumpPointList::undoRemoveTieFromScore(TieJumpPoint* jumpPoint) { Note* note = jumpPoint->note(); Score* score = note ? note->score() : nullptr; - if (!m_startTie || !score) { + Tie* tie = startTie(); + if (!tie || !score) { return; } if (jumpPoint->followingNote()) { // Remove full tie and add partial tie - if (m_startTie->isPartialTie()) { + if (tie->isPartialTie()) { return; } jumpPoint->undoSetActive(false); - m_startTie = Tie::changeTieType(m_startTie); + Tie::changeTieType(tie); return; } diff --git a/src/engraving/dom/tiejumppointlist.h b/src/engraving/dom/tiejumppointlist.h index 44deb895dff83..152d32b1f733e 100644 --- a/src/engraving/dom/tiejumppointlist.h +++ b/src/engraving/dom/tiejumppointlist.h @@ -1,3 +1,25 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-Studio-CLA-applies + * + * MuseScore Studio + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore Limited + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #pragma once #include "global/types/string.h" @@ -22,6 +44,8 @@ class TieJumpPoint bool active() const { return m_active; } void setActive(bool v) { m_active = v; } void undoSetActive(bool v); + + // Stores the list that this end point belongs to. This is needed to find the start tie from an endpoint void setJumpPointList(TieJumpPointList* jumpPointList) { m_jumpPointList = jumpPointList; } TieJumpPointList* jumpPointList() { return m_jumpPointList; } @@ -41,7 +65,8 @@ class TieJumpPoint class TieJumpPointList { public: - TieJumpPointList() = default; + TieJumpPointList(Note* note) + : m_note(note) {} ~TieJumpPointList(); void add(TieJumpPoint* item); @@ -49,8 +74,7 @@ class TieJumpPointList size_t size() const { return m_jumpPoints.size(); } bool empty() const { return m_jumpPoints.empty(); } - void setStartTie(Tie* startTie) { m_startTie = startTie; } - Tie* startTie() const { return m_startTie; } + Tie* startTie() const; TieJumpPoint* findJumpPoint(const String& id); void toggleJumpPoint(const String& id); @@ -65,6 +89,6 @@ class TieJumpPointList private: std::vector m_jumpPoints; - Tie* m_startTie = nullptr; + Note* m_note = nullptr; }; } From aac9f3d858d1718e647d05f30474264533ee9a99 Mon Sep 17 00:00:00 2001 From: James Mizen Date: Wed, 8 Jan 2025 14:55:58 +0000 Subject: [PATCH 04/11] Update min hanging tie length --- src/engraving/style/styledef.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engraving/style/styledef.cpp b/src/engraving/style/styledef.cpp index 317ff8929d198..933fc5607fe07 100644 --- a/src/engraving/style/styledef.cpp +++ b/src/engraving/style/styledef.cpp @@ -538,7 +538,7 @@ const std::array StyleDef::styleValue styleDef(tieMidWidth, Spatium(.21)), styleDef(tieDottedWidth, Spatium(.10)), styleDef(minTieLength, Spatium(1.0)), - styleDef(minHangingTieLength, Spatium(1.0)), + styleDef(minHangingTieLength, Spatium(1.5)), styleDef(minStraightGlissandoLength, Spatium(1.2)), styleDef(minWigglyGlissandoLength, Spatium(2.0)), styleDef(slurMinDistance, Spatium(0.5)), From d183027c85aa22b3fa19e06a08b43d4f17531cd9 Mon Sep 17 00:00:00 2001 From: James Mizen Date: Thu, 9 Jan 2025 11:16:15 +0000 Subject: [PATCH 05/11] Fix crash --- src/engraving/dom/edit.cpp | 3 +++ src/engraving/dom/note.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/src/engraving/dom/edit.cpp b/src/engraving/dom/edit.cpp index 6519e366eb54a..ce23219f5d88e 100644 --- a/src/engraving/dom/edit.cpp +++ b/src/engraving/dom/edit.cpp @@ -1900,6 +1900,9 @@ static Tie* createAndAddTie(Note* startNote, Note* endNote) tie->setTrack(startNote->track()); tie->setTick(startNote->chord()->segment()->tick()); if (endNote) { + if (endNote->tieBack()) { + score->undoRemoveElement(endNote->tieBack()); + } tie->setEndNote(endNote); tie->setTicks(endNote->chord()->segment()->tick() - startNote->chord()->segment()->tick()); } diff --git a/src/engraving/dom/note.cpp b/src/engraving/dom/note.cpp index 50dff8e43e5e5..d6246733fdb9c 100644 --- a/src/engraving/dom/note.cpp +++ b/src/engraving/dom/note.cpp @@ -2515,6 +2515,7 @@ void Note::setTieBack(Tie* t) { if (m_tieBack && t && m_tieBack->jumpPoint()) { t->setJumpPoint(m_tieBack->jumpPoint()); + m_tieBack->setJumpPoint(nullptr); } m_tieBack = t; } From 32eda781b4474cd4c0ad77aacd71d296c8b683a2 Mon Sep 17 00:00:00 2001 From: James Mizen Date: Thu, 9 Jan 2025 11:21:33 +0000 Subject: [PATCH 06/11] Fix next note without tie being named "invalid" --- src/engraving/dom/tiejumppointlist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engraving/dom/tiejumppointlist.cpp b/src/engraving/dom/tiejumppointlist.cpp index 47dbdf957d767..2447c6c343680 100644 --- a/src/engraving/dom/tiejumppointlist.cpp +++ b/src/engraving/dom/tiejumppointlist.cpp @@ -138,7 +138,7 @@ String TieJumpPoint::precedingJumpItemName() const } } - if (m_note->tieBack() && m_note->tieBack()->startNote()) { + if (m_followingNote) { //: Used at %1 in the string "Tie to %1 (m. %2)" return muse::mtrc("engraving", "next note", "partial tie menu"); } From 2784610ade7e1e1edcfc2cb347a5a4263d5812d9 Mon Sep 17 00:00:00 2001 From: James Mizen Date: Thu, 9 Jan 2025 10:37:06 +0000 Subject: [PATCH 07/11] Refactor partial tie popup menu --- .../Muse/UiComponents/ContextMenuLoader.qml | 18 ----- .../Muse/UiComponents/StyledMenuLoader.qml | 18 +---- .../Muse/UiComponents/internal/StyledMenu.qml | 7 +- src/notation/notationscene.qrc | 1 + .../internal/PartialTieMenuRowItem.qml | 75 +++++++++++++++++ .../internal/PartialTiePopup.qml | 81 ++++++++++++------- 6 files changed, 132 insertions(+), 68 deletions(-) create mode 100644 src/notation/qml/MuseScore/NotationScene/internal/PartialTieMenuRowItem.qml diff --git a/src/framework/uicomponents/qml/Muse/UiComponents/ContextMenuLoader.qml b/src/framework/uicomponents/qml/Muse/UiComponents/ContextMenuLoader.qml index d5a9b891abfd6..6633c1b116c60 100644 --- a/src/framework/uicomponents/qml/Muse/UiComponents/ContextMenuLoader.qml +++ b/src/framework/uicomponents/qml/Muse/UiComponents/ContextMenuLoader.qml @@ -21,23 +21,12 @@ */ import QtQuick 2.15 -import Muse.Ui 1.0 - Item { id: container // Useful for static context menus property var items: [] - - property NavigationSection notationViewNavigationSection: null - property int navigationOrderStart: 0 - - property alias closeMenuOnSelection: contextMenuLoader.closeMenuOnSelection - property alias opensUpward: contextMenuLoader.opensUpward - property alias focusOnOpened: contextMenuLoader.focusOnOpened - property alias item: contextMenuLoader.item - signal handleMenuItem(string itemId) signal opened() signal closed() @@ -47,13 +36,6 @@ Item { width: 0 height: 0 - onNotationViewNavigationSectionChanged: function() { - contextMenuLoader.item.navigationSectionOverride = container.notationViewNavigationSection - } - onNavigationOrderStartChanged: function() { - contextMenuLoader.item.navigationOrderStart = container.navigationOrderStart - } - function show(position: point, items) { if (!items) { items = container.items diff --git a/src/framework/uicomponents/qml/Muse/UiComponents/StyledMenuLoader.qml b/src/framework/uicomponents/qml/Muse/UiComponents/StyledMenuLoader.qml index 2b0d0fcf8ee20..1622e320e80bf 100644 --- a/src/framework/uicomponents/qml/Muse/UiComponents/StyledMenuLoader.qml +++ b/src/framework/uicomponents/qml/Muse/UiComponents/StyledMenuLoader.qml @@ -21,7 +21,6 @@ */ import QtQuick 2.15 -import Muse.Ui 1.0 import Muse.UiComponents 1.0 import "internal" @@ -38,13 +37,6 @@ Loader { property StyledMenu menu: loader.item as StyledMenu property Item menuAnchorItem: null property bool hasSiblingMenus: false - property bool closeMenuOnSelection: true - property bool focusOnOpened: true - - property NavigationSection notationViewNavigationSection: null - property int navigationOrderStart: 0 - - property bool opensUpward: false property alias isMenuOpened: loader.active @@ -73,9 +65,7 @@ Loader { accessibleName: loader.accessibleName onHandleMenuItem: function(itemId) { - if (loader.closeMenuOnSelection) { - itemMenu.close() - } + itemMenu.close() Qt.callLater(loader.handleMenuItem, itemId) } @@ -92,9 +82,7 @@ Loader { } onOpened: { - if (focusOnOpened) { - focusOnOpenedMenuTimer.start() - } + focusOnOpenedMenuTimer.start() } } @@ -145,8 +133,6 @@ Loader { menu.closeSubMenu() - menu.setOpensUpward(loader.opensUpward) - if (x !== -1) { menu.x = x } diff --git a/src/framework/uicomponents/qml/Muse/UiComponents/internal/StyledMenu.qml b/src/framework/uicomponents/qml/Muse/UiComponents/internal/StyledMenu.qml index cb2b4c8fb5bdc..6262704ad7365 100644 --- a/src/framework/uicomponents/qml/Muse/UiComponents/internal/StyledMenu.qml +++ b/src/framework/uicomponents/qml/Muse/UiComponents/internal/StyledMenu.qml @@ -32,9 +32,6 @@ MenuView { property alias model: view.model - property NavigationSection navigationSectionOverride: null - property int navigationOrderStart: 0 - property int preferredAlign: Qt.AlignRight // Left, HCenter, Right property bool hasSiblingMenus: loader.hasSiblingMenus @@ -137,9 +134,9 @@ MenuView { property NavigationPanel navigationPanel: NavigationPanel { name: "StyledMenu" + section: content.navigationSection direction: NavigationPanel.Vertical - section: root.navigationSectionOverride ?? content.navigationSection - order: root.navigationOrderStart + order: 1 accessible.name: root.accessibleName diff --git a/src/notation/notationscene.qrc b/src/notation/notationscene.qrc index cf0e035766a58..4f7b108f17775 100644 --- a/src/notation/notationscene.qrc +++ b/src/notation/notationscene.qrc @@ -76,5 +76,6 @@ qml/MuseScore/NotationScene/internal/EditStyle/timeSigImages/timesig-on_all_staves.png qml/MuseScore/NotationScene/internal/EditStyle/timeSigImages/timesig-courtesy-create_space.png qml/MuseScore/NotationScene/internal/EditStyle/StyledImage.qml + qml/MuseScore/NotationScene/internal/PartialTieMenuRowItem.qml diff --git a/src/notation/qml/MuseScore/NotationScene/internal/PartialTieMenuRowItem.qml b/src/notation/qml/MuseScore/NotationScene/internal/PartialTieMenuRowItem.qml new file mode 100644 index 0000000000000..8d6d897f70af8 --- /dev/null +++ b/src/notation/qml/MuseScore/NotationScene/internal/PartialTieMenuRowItem.qml @@ -0,0 +1,75 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-CLA-applies + * + * MuseScore + * Music Composition & Notation + * + * Copyright (C) 2025 MuseScore BVBA and others + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 + +import Muse.Ui 1.0 +import Muse.UiComponents 1.0 +import MuseScore.NotationScene 1.0 + +ListItemBlank { + function calculateWidth() { + let result = 0 + + result += rowLayout.anchors.leftMargin + + result += Math.ceil(checkIcon.Layout.preferredWidth) + result += rowLayout.spacing + + result += Math.ceil(titleLabel.implicitWidth) + result += rowLayout.spacing + result += rowLayout.anchors.rightMargin + + return result + } + + RowLayout { + id: rowLayout + + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 12 + anchors.right: parent.right + anchors.rightMargin: 12 + + spacing: 12 + + StyledIconLabel { + id: checkIcon + Layout.alignment: Qt.AlignLeft + Layout.preferredWidth: 16 + iconCode: modelData.checked ? IconCode.TICK_RIGHT_ANGLE : IconCode.NONE + } + + StyledTextLabel { + id: titleLabel + Layout.fillWidth: true + horizontalAlignment: Text.AlignLeft + + text: modelData.title + + textFormat: Text.RichText + } + } +} diff --git a/src/notation/qml/MuseScore/NotationScene/internal/PartialTiePopup.qml b/src/notation/qml/MuseScore/NotationScene/internal/PartialTiePopup.qml index d17f1fe34e0fa..63a8546b116b5 100644 --- a/src/notation/qml/MuseScore/NotationScene/internal/PartialTiePopup.qml +++ b/src/notation/qml/MuseScore/NotationScene/internal/PartialTiePopup.qml @@ -5,7 +5,7 @@ * MuseScore * Music Composition & Notation * - * Copyright (C) 2022 MuseScore BVBA and others + * Copyright (C) 2025 MuseScore BVBA and others * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -32,6 +32,9 @@ StyledPopupView { id: root margins: 0 + contentWidth: content.width + contentHeight: content.height + property alias notationViewNavigationSection: partialTieNavPanel.section property alias navigationOrderStart: partialTieNavPanel.order readonly property alias navigationOrderEnd: partialTieNavPanel.order @@ -40,12 +43,7 @@ StyledPopupView { showArrow: false - onOpened: { - tieMenuLoader.show(Qt.point(0, 0)) - } - onClosed: { - tieMenuLoader.close() partialTiePopupModel.onClosed() } @@ -53,26 +51,23 @@ StyledPopupView { function updatePosition() { const opensUp = partialTiePopupModel.tieDirection - const popupHeight = tieMenuLoader.item.height + root.margins * 2 + root.padding * 2 + const popupHeight = content.height + root.margins * 2 + root.padding * 2 root.x = partialTiePopupModel.dialogPosition.x - root.parent.x root.y = partialTiePopupModel.dialogPosition.y - root.parent.y - (opensUp ? popupHeight : 0) root.setOpensUpward(opensUp) - } - - contentWidth: tieMenuLoader.width - contentHeight: tieMenuLoader.childrenRect.height - ContextMenuLoader { - id: tieMenuLoader - closeMenuOnSelection: false - focusOnOpened: false - opensUpward: root.opensUpward + tieMenuList.calculateWidth() + } - items: partialTiePopupModel.items + Component.onCompleted: { + partialTiePopupModel.init() + } - onHandleMenuItem: function(itemId) { - partialTiePopupModel.toggleItemChecked(itemId) - } + Column { + id: content + width: tieMenuList.width + height: tieMenuList.height + spacing: 0 PartialTiePopupModel { id: partialTiePopupModel @@ -82,26 +77,54 @@ StyledPopupView { } onItemsChanged: function() { - tieMenuLoader.show(Qt.point(0, 0)) + tieMenuList.model = partialTiePopupModel.items } } - Component.onCompleted: { - partialTiePopupModel.init() - } - NavigationPanel { id: partialTieNavPanel name: "PartialTieMenu" direction: NavigationPanel.Vertical accessible.name: qsTrc("notation", "Partial tie menu items") + } + + StyledListView { + id: tieMenuList + + property int itemHeight: 32 + + implicitWidth: contentItem.childrenRect.width + height: itemHeight * count + + spacing: 0 + arrowControlsAvailable: false - onSectionChanged: function() { - tieMenuLoader.notationViewNavigationSection = section + model: partialTiePopupModel.items + + visible: true + + function calculateWidth() { + var result = 0 + for (var item in tieMenuList.contentItem.children) { + var row = tieMenuList.contentItem.children[item]; + if (!(row instanceof ListItemBlank)) { + continue + } + result = Math.max(result, tieMenuList.contentItem.children[item].calculateWidth()) + } + + tieMenuList.width = result } - onOrderChanged: function() { - tieMenuLoader.navigationOrderStart = order + delegate: PartialTieMenuRowItem { + implicitHeight: tieMenuList.itemHeight + hoverHitColor: ui.theme.accentColor + anchors.left: parent ? parent.left : undefined + anchors.right: parent ? parent.right : undefined + + onClicked: { + partialTiePopupModel.toggleItemChecked(modelData.id) + } } } } From 4eac7d70f635ef4b0fb9115d6fbc3d61697b835f Mon Sep 17 00:00:00 2001 From: James Mizen Date: Fri, 10 Jan 2025 16:51:38 +0000 Subject: [PATCH 08/11] Fix build --- src/engraving/dom/tie.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/engraving/dom/tie.cpp b/src/engraving/dom/tie.cpp index e829f5baa3e4c..db58fb76205ec 100644 --- a/src/engraving/dom/tie.cpp +++ b/src/engraving/dom/tie.cpp @@ -229,13 +229,12 @@ void Tie::updatePossibleJumpPoints() const Note* note = toNote(parentItem()); const Chord* chord = note->chord(); + const Measure* measure = chord->measure(); if (!chord->hasFollowingJumpItem()) { return; } - const Measure* measure = chord->measure(); - int jumpPointIdx = 0; Note* nextNote = searchTieNote(note); From dcb4e6414510004033f38c6f8e5c5ce7ca4adcff Mon Sep 17 00:00:00 2001 From: James Mizen Date: Mon, 13 Jan 2025 09:31:30 +0000 Subject: [PATCH 09/11] Review fixes --- src/engraving/dom/tiejumppointlist.cpp | 3 +-- src/engraving/dom/tiejumppointlist.h | 13 ++++++------ .../internal/PartialTieMenuRowItem.qml | 9 ++++++-- .../internal/PartialTiePopup.qml | 21 ++++++++----------- .../qml/MuseScore/Playback/SoundFlagPopup.qml | 2 -- 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/engraving/dom/tiejumppointlist.cpp b/src/engraving/dom/tiejumppointlist.cpp index 2447c6c343680..7ee4372d00cae 100644 --- a/src/engraving/dom/tiejumppointlist.cpp +++ b/src/engraving/dom/tiejumppointlist.cpp @@ -68,10 +68,9 @@ const String TieJumpPoint::menuTitle() const { const Measure* measure = m_note->findMeasure(); const int measureNo = measure ? measure->no() + 1 : 0; - const String measureStr = String::fromStdString(std::to_string(measureNo)); //: %1 represents the preceding jump item eg. coda. %2 represents the measure number - return muse::mtrc("engraving", "Tie to %1 (m. %2)").arg(precedingJumpItemName(), measureStr); + return muse::mtrc("engraving", "Tie to %1 (m. %2)").arg(precedingJumpItemName(), String::number(measureNo)); } String TieJumpPoint::precedingJumpItemName() const diff --git a/src/engraving/dom/tiejumppointlist.h b/src/engraving/dom/tiejumppointlist.h index 152d32b1f733e..8b6147674f789 100644 --- a/src/engraving/dom/tiejumppointlist.h +++ b/src/engraving/dom/tiejumppointlist.h @@ -23,7 +23,6 @@ #pragma once #include "global/types/string.h" -using muse::String; namespace mu::engraving { class Note; class Tie; @@ -40,7 +39,7 @@ class TieJumpPoint Note* note() const { return m_note; } Tie* endTie() const; bool followingNote() const { return m_followingNote; } - const String& id() const { return m_id; } + const muse::String& id() const { return m_id; } bool active() const { return m_active; } void setActive(bool v) { m_active = v; } void undoSetActive(bool v); @@ -49,13 +48,13 @@ class TieJumpPoint void setJumpPointList(TieJumpPointList* jumpPointList) { m_jumpPointList = jumpPointList; } TieJumpPointList* jumpPointList() { return m_jumpPointList; } - const String menuTitle() const; + const muse::String menuTitle() const; private: - String precedingJumpItemName() const; + muse::String precedingJumpItemName() const; Note* m_note = nullptr; bool m_active = false; - String m_id; + muse::String m_id; TieJumpPointList* m_jumpPointList = nullptr; bool m_followingNote = false; }; @@ -76,8 +75,8 @@ class TieJumpPointList Tie* startTie() const; - TieJumpPoint* findJumpPoint(const String& id); - void toggleJumpPoint(const String& id); + TieJumpPoint* findJumpPoint(const muse::String& id); + void toggleJumpPoint(const muse::String& id); void undoAddTieToScore(TieJumpPoint* jumpPoint); void undoRemoveTieFromScore(TieJumpPoint* jumpPoint); diff --git a/src/notation/qml/MuseScore/NotationScene/internal/PartialTieMenuRowItem.qml b/src/notation/qml/MuseScore/NotationScene/internal/PartialTieMenuRowItem.qml index 8d6d897f70af8..fd92b3044a7cb 100644 --- a/src/notation/qml/MuseScore/NotationScene/internal/PartialTieMenuRowItem.qml +++ b/src/notation/qml/MuseScore/NotationScene/internal/PartialTieMenuRowItem.qml @@ -44,6 +44,11 @@ ListItemBlank { return result } + id: rowDelegate + + required property var modelData + required property var model + RowLayout { id: rowLayout @@ -59,7 +64,7 @@ ListItemBlank { id: checkIcon Layout.alignment: Qt.AlignLeft Layout.preferredWidth: 16 - iconCode: modelData.checked ? IconCode.TICK_RIGHT_ANGLE : IconCode.NONE + iconCode: rowDelegate.modelData.checked ? IconCode.TICK_RIGHT_ANGLE : IconCode.NONE } StyledTextLabel { @@ -67,7 +72,7 @@ ListItemBlank { Layout.fillWidth: true horizontalAlignment: Text.AlignLeft - text: modelData.title + text: rowDelegate.modelData.title textFormat: Text.RichText } diff --git a/src/notation/qml/MuseScore/NotationScene/internal/PartialTiePopup.qml b/src/notation/qml/MuseScore/NotationScene/internal/PartialTiePopup.qml index 63a8546b116b5..23623f2cade40 100644 --- a/src/notation/qml/MuseScore/NotationScene/internal/PartialTiePopup.qml +++ b/src/notation/qml/MuseScore/NotationScene/internal/PartialTiePopup.qml @@ -35,11 +35,9 @@ StyledPopupView { contentWidth: content.width contentHeight: content.height - property alias notationViewNavigationSection: partialTieNavPanel.section - property alias navigationOrderStart: partialTieNavPanel.order - readonly property alias navigationOrderEnd: partialTieNavPanel.order - - readonly property alias model: partialTiePopupModel + property NavigationSection notationViewNavigationSection: null + property int navigationOrderStart: 0 + property int navigationOrderEnd: tieMenuList.navigation.order showArrow: false @@ -81,13 +79,6 @@ StyledPopupView { } } - NavigationPanel { - id: partialTieNavPanel - name: "PartialTieMenu" - direction: NavigationPanel.Vertical - accessible.name: qsTrc("notation", "Partial tie menu items") - } - StyledListView { id: tieMenuList @@ -101,6 +92,9 @@ StyledPopupView { model: partialTiePopupModel.items + navigation.section: notationViewNavigationSection + navigation.order: navigationOrderStart + visible: true function calculateWidth() { @@ -122,6 +116,9 @@ StyledPopupView { anchors.left: parent ? parent.left : undefined anchors.right: parent ? parent.right : undefined + navigation.panel: tieMenuList.navigation + navigation.row: model.index + onClicked: { partialTiePopupModel.toggleItemChecked(modelData.id) } diff --git a/src/playback/qml/MuseScore/Playback/SoundFlagPopup.qml b/src/playback/qml/MuseScore/Playback/SoundFlagPopup.qml index 20266afe0977a..502edeb8b175c 100644 --- a/src/playback/qml/MuseScore/Playback/SoundFlagPopup.qml +++ b/src/playback/qml/MuseScore/Playback/SoundFlagPopup.qml @@ -36,8 +36,6 @@ StyledPopupView { property alias navigationOrderStart: navPanel.order readonly property alias navigationOrderEnd: museSoundsParams.navigationPanelOrderEnd - readonly property alias model: soundFlagModel - contentWidth: content.width contentHeight: content.childrenRect.height onContentHeightChanged: { From 217d6da1493a5bfbbc5395706df6f74133ef48ac Mon Sep 17 00:00:00 2001 From: James Mizen Date: Mon, 13 Jan 2025 11:27:05 +0000 Subject: [PATCH 10/11] Only apply minHangingTieWidth to longest ties --- .../rendering/score/horizontalspacing.cpp | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/engraving/rendering/score/horizontalspacing.cpp b/src/engraving/rendering/score/horizontalspacing.cpp index a8337935a7db6..c61ee9eeae588 100644 --- a/src/engraving/rendering/score/horizontalspacing.cpp +++ b/src/engraving/rendering/score/horizontalspacing.cpp @@ -1507,6 +1507,8 @@ void HorizontalSpacing::computeHangingLineWidth(const Segment* firstSeg, const S const Measure* crMeasure = crSeg->measure(); const size_t ntracks = crSeg->score()->ntracks(); + std::vector tieLengths; + for (track_idx_t track = 0; track < ntracks; track++) { // Hanging lines only occur at start or end of a measure const ChordRest* cr = incoming ? crMeasure->firstChordRest(track) : crMeasure->lastChordRest(track); @@ -1542,9 +1544,7 @@ void HorizontalSpacing::computeHangingLineWidth(const Segment* firstSeg, const S } double minLength = 0.0; - if (attachedLine->isTie()) { - minLength = style.styleMM(Sid::minHangingTieLength); - } else if (attachedLine->isGlissando()) { + if (attachedLine->isGlissando()) { bool straight = toGlissando(attachedLine)->glissandoType() == GlissandoType::STRAIGHT; minLength = straight ? style.styleMM(Sid::minStraightGlissandoLength) : style.styleMM(Sid::minWigglyGlissandoLength); @@ -1561,10 +1561,32 @@ void HorizontalSpacing::computeHangingLineWidth(const Segment* firstSeg, const S const double lineEndPointX = incoming ? lineNoteEndPos : lineSegEndPos; const double lineLength = lineEndPointX - lineStartPointX; + if (attachedLine->isTie()) { + tieLengths.push_back(lineLength); + continue; + } + if (lineLength < minLength) { width += minLength - lineLength; } } } } + + if (tieLengths.empty()) { + return; + } + + const double maxLength = *std::max_element(tieLengths.begin(), tieLengths.end()); + const double oldWidth = width; + for (double& tieLength : tieLengths) { + // Adjust for new width + tieLength += width - oldWidth; + const double minLength = muse::RealIsEqual(tieLength, maxLength) ? style.styleMM(Sid::minHangingTieLength) : style.styleMM( + Sid::minTieLength); + + if (tieLength < minLength) { + width += minLength - tieLength; + } + } } From 1277d3705aac4a823138365db9b6ffb3f2e6fede Mon Sep 17 00:00:00 2001 From: James Mizen Date: Thu, 16 Jan 2025 10:18:33 +0000 Subject: [PATCH 11/11] Final review fixes --- src/engraving/dom/note.cpp | 4 ++-- src/engraving/dom/note.h | 2 +- .../MuseScore/NotationScene/internal/CapoPopup.qml | 2 -- .../NotationScene/internal/HarpPedalPopup.qml | 11 ++++------- .../NotationScene/internal/StringTuningsPopup.qml | 3 --- 5 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/engraving/dom/note.cpp b/src/engraving/dom/note.cpp index d6246733fdb9c..cbe605adac293 100644 --- a/src/engraving/dom/note.cpp +++ b/src/engraving/dom/note.cpp @@ -549,7 +549,7 @@ NoteHeadGroup NoteHead::headGroup() const //--------------------------------------------------------- Note::Note(Chord* ch) - : EngravingItem(ElementType::NOTE, ch, ElementFlag::MOVABLE), m_jumpPoints(this) + : EngravingItem(ElementType::NOTE, ch, ElementFlag::MOVABLE) { m_playEvents.push_back(NoteEvent()); // add default play event } @@ -599,7 +599,7 @@ std::vector Note::compoundNotes() const } Note::Note(const Note& n, bool link) - : EngravingItem(n), m_jumpPoints(this) + : EngravingItem(n) { if (link) { score()->undo(new Link(this, const_cast(&n))); diff --git a/src/engraving/dom/note.h b/src/engraving/dom/note.h index 41cae8eae3f6b..6ee51d9424356 100644 --- a/src/engraving/dom/note.h +++ b/src/engraving/dom/note.h @@ -575,6 +575,6 @@ class Note final : public EngravingItem String m_fretString; std::vector m_lineAttachPoints; - TieJumpPointList m_jumpPoints; + TieJumpPointList m_jumpPoints { this }; }; } // namespace mu::engraving diff --git a/src/notation/qml/MuseScore/NotationScene/internal/CapoPopup.qml b/src/notation/qml/MuseScore/NotationScene/internal/CapoPopup.qml index 0b88bb4e1d317..ee9d27f11fdfc 100644 --- a/src/notation/qml/MuseScore/NotationScene/internal/CapoPopup.qml +++ b/src/notation/qml/MuseScore/NotationScene/internal/CapoPopup.qml @@ -33,8 +33,6 @@ StyledPopupView { property alias navigationOrderStart: capoSettingsNavPanel.order readonly property alias navigationOrderEnd: capoSettingsNavPanel.order - readonly property alias model: capoModel - contentWidth: content.width contentHeight: content.height diff --git a/src/notation/qml/MuseScore/NotationScene/internal/HarpPedalPopup.qml b/src/notation/qml/MuseScore/NotationScene/internal/HarpPedalPopup.qml index 56569e859c5e8..1660a59fa69fe 100644 --- a/src/notation/qml/MuseScore/NotationScene/internal/HarpPedalPopup.qml +++ b/src/notation/qml/MuseScore/NotationScene/internal/HarpPedalPopup.qml @@ -29,9 +29,6 @@ import MuseScore.NotationScene 1.0 StyledPopupView { id: root - - readonly property alias model: harpModel - property variant pedalState: harpModel.pedalState property alias notationViewNavigationSection: pedalSettingsNavPanel.section @@ -279,7 +276,7 @@ StyledPopupView { Layout.leftMargin: 30 Layout.fillWidth: true - checked: model.isDiagram + checked: harpModel.isDiagram text: qsTrc("notation", "Diagram") navigation.name: "diagramButton" @@ -288,7 +285,7 @@ StyledPopupView { navigation.accessible.name: qsTrc("notation", "Diagram") onToggled: { - model.setIsDiagram(true) + harpModel.setIsDiagram(true) } } @@ -302,7 +299,7 @@ StyledPopupView { Layout.bottomMargin: 15 Layout.fillWidth: true - checked: !model.isDiagram + checked: !harpModel.isDiagram text: qsTrc("notation", "Text") navigation.name: "textButton" @@ -311,7 +308,7 @@ StyledPopupView { navigation.accessible.name: qsTrc("notation", "Text") onToggled: { - model.setIsDiagram(false) + harpModel.setIsDiagram(false) } } } diff --git a/src/notation/qml/MuseScore/NotationScene/internal/StringTuningsPopup.qml b/src/notation/qml/MuseScore/NotationScene/internal/StringTuningsPopup.qml index dadd85897ef7c..f04b2b30eefeb 100644 --- a/src/notation/qml/MuseScore/NotationScene/internal/StringTuningsPopup.qml +++ b/src/notation/qml/MuseScore/NotationScene/internal/StringTuningsPopup.qml @@ -33,9 +33,6 @@ StyledPopupView { property alias navigationOrderStart: navPanel.order readonly property alias navigationOrderEnd: navPanel.order - readonly property alias model: stringTuningsModel - - contentWidth: content.width contentHeight: content.height