From fbe040c60882785b527786c705ddb25ff42c98dd Mon Sep 17 00:00:00 2001 From: Calum Matheson Date: Wed, 19 Feb 2025 15:13:19 +0000 Subject: [PATCH 1/4] Percussion panel - add hover/hit states for pad footers --- .../internal/PercussionPanelPadContent.qml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/notation/qml/MuseScore/NotationScene/internal/PercussionPanelPadContent.qml b/src/notation/qml/MuseScore/NotationScene/internal/PercussionPanelPadContent.qml index c07366de460d6..b7126b9e95b83 100644 --- a/src/notation/qml/MuseScore/NotationScene/internal/PercussionPanelPadContent.qml +++ b/src/notation/qml/MuseScore/NotationScene/internal/PercussionPanelPadContent.qml @@ -174,6 +174,7 @@ Column { anchors.fill: parent enabled: root.panelMode !== PanelMode.EDIT_LAYOUT + hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.RightButton @@ -226,5 +227,24 @@ Column { root.padModel.handleMenuItem(itemId) } } + + states: [ + State { + name: "MOUSE_HOVERED" + when: footerMouseArea.containsMouse && !footerMouseArea.pressed + PropertyChanges { + target: footerArea + color: Utils.colorWithAlpha(ui.theme.buttonColor, ui.theme.buttonOpacityHover) + } + }, + State { + name: "MOUSE_HIT" + when: footerMouseArea.pressed + PropertyChanges { + target: footerArea + color: Utils.colorWithAlpha(ui.theme.buttonColor, ui.theme.buttonOpacityHit) + } + } + ] } } From c9daabbc6cb1bdbd758815f6a856d8bd58638b97 Mon Sep 17 00:00:00 2001 From: Calum Matheson Date: Wed, 19 Feb 2025 22:48:03 +0000 Subject: [PATCH 2/4] Percussion panel - add shortcut/view menu item --- src/app/configs/data/shortcuts.xml | 4 +++ src/app/configs/data/shortcuts_azerty.xml | 4 +++ src/app/configs/data/shortcuts_mac.xml | 4 +++ .../internal/applicationuiactions.cpp | 28 +++++++++++-------- src/appshell/internal/applicationuiactions.h | 2 ++ src/appshell/view/appmenumodel.cpp | 2 +- 6 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/app/configs/data/shortcuts.xml b/src/app/configs/data/shortcuts.xml index 468b5626f2b4b..bbd92a0bb82d6 100644 --- a/src/app/configs/data/shortcuts.xml +++ b/src/app/configs/data/shortcuts.xml @@ -898,6 +898,10 @@ toggle-piano-keyboard P + + toggle-percussion-panel + O + next-score 20 diff --git a/src/app/configs/data/shortcuts_azerty.xml b/src/app/configs/data/shortcuts_azerty.xml index 584e89952811d..ceb50391e2d32 100644 --- a/src/app/configs/data/shortcuts_azerty.xml +++ b/src/app/configs/data/shortcuts_azerty.xml @@ -924,6 +924,10 @@ toggle-piano-keyboard P + + toggle-percussion-panel + O + next-score 20 diff --git a/src/app/configs/data/shortcuts_mac.xml b/src/app/configs/data/shortcuts_mac.xml index f532e63b10270..d0d4b28a6fe44 100644 --- a/src/app/configs/data/shortcuts_mac.xml +++ b/src/app/configs/data/shortcuts_mac.xml @@ -899,6 +899,10 @@ toggle-piano-keyboard P + + toggle-percussion-panel + O + next-score 20 diff --git a/src/appshell/internal/applicationuiactions.cpp b/src/appshell/internal/applicationuiactions.cpp index 32ce297765d76..bdfd79693a537 100644 --- a/src/appshell/internal/applicationuiactions.cpp +++ b/src/appshell/internal/applicationuiactions.cpp @@ -39,6 +39,7 @@ using namespace muse::dock; static const ActionCode FULL_SCREEN_CODE("fullscreen"); static const ActionCode TOGGLE_NAVIGATOR_ACTION_CODE("toggle-navigator"); static const ActionCode TOGGLE_BRAILLE_ACTION_CODE("toggle-braille-panel"); +static const ActionCode TOGGLE_PERCUSSION_PANEL_ACTION_CODE("toggle-percussion-panel"); const UiActionList ApplicationUiActions::m_actions = { UiAction("quit", @@ -194,14 +195,13 @@ const UiActionList ApplicationUiActions::m_actions = { TranslatableString("action", "Show/hide piano keyboard"), Checkable::Yes ), - // still in development - // UiAction("toggle-percussion-panel", - // mu::context::UiCtxNotationOpened, - // mu::context::CTX_ANY, - // TranslatableString("action", "Percussion"), - // TranslatableString("action", "Show/hide percussion panel"), - // Checkable::Yes - // ), + UiAction(TOGGLE_PERCUSSION_PANEL_ACTION_CODE, + mu::context::UiCtxProjectOpened, + mu::context::CTX_NOTATION_OPENED, + TranslatableString("action", "Percussion"), + TranslatableString("action", "Show/hide percussion panel"), + Checkable::Yes + ), UiAction("toggle-scorecmp-tool", mu::context::UiCtxProjectOpened, mu::context::CTX_NOTATION_OPENED, @@ -248,6 +248,10 @@ void ApplicationUiActions::init() dockWindowProvider()->windowChanged().onNotify(this, [this]() { listenOpenedDocksChanged(dockWindowProvider()->window()); }); + + notationConfiguration()->useNewPercussionPanelChanged().onNotify(this, [this]() { + m_actionEnabledChanged.send({ TOGGLE_PERCUSSION_PANEL_ACTION_CODE }); + }); } void ApplicationUiActions::listenOpenedDocksChanged(IDockWindow* window) @@ -280,11 +284,11 @@ const muse::ui::UiActionList& ApplicationUiActions::actionsList() const bool ApplicationUiActions::actionEnabled(const UiAction& act) const { - if (!m_controller->canReceiveAction(act.code)) { - return false; + if (act.code == TOGGLE_PERCUSSION_PANEL_ACTION_CODE) { + return notationConfiguration()->useNewPercussionPanel(); } - return true; + return m_controller->canReceiveAction(act.code); } bool ApplicationUiActions::actionChecked(const UiAction& act) const @@ -340,7 +344,7 @@ const QMap& ApplicationUiActions::toggleDockActions() { "toggle-timeline", TIMELINE_PANEL_NAME }, { "toggle-mixer", MIXER_PANEL_NAME }, { "toggle-piano-keyboard", PIANO_KEYBOARD_PANEL_NAME }, - { "toggle-percussion-panel", PERCUSSION_PANEL_NAME }, + { TOGGLE_PERCUSSION_PANEL_ACTION_CODE, PERCUSSION_PANEL_NAME }, { "toggle-statusbar", NOTATION_STATUSBAR_NAME }, }; diff --git a/src/appshell/internal/applicationuiactions.h b/src/appshell/internal/applicationuiactions.h index 396c47638bb5c..2fb747d6aa491 100644 --- a/src/appshell/internal/applicationuiactions.h +++ b/src/appshell/internal/applicationuiactions.h @@ -29,6 +29,7 @@ #include "async/asyncable.h" #include "ui/imainwindow.h" #include "view/preferences/braillepreferencesmodel.h" +#include "notation/inotationconfiguration.h" #include "dockwindow/idockwindowprovider.h" @@ -39,6 +40,7 @@ class ApplicationUiActions : public muse::ui::IUiActionsModule, public muse::Inj muse::Inject dockWindowProvider = { this }; muse::Inject configuration = { this }; muse::Inject brailleConfiguration = { this }; + muse::Inject notationConfiguration = { this }; public: ApplicationUiActions(std::shared_ptr controller, const muse::modularity::ContextPtr& iocCtx); diff --git a/src/appshell/view/appmenumodel.cpp b/src/appshell/view/appmenumodel.cpp index 18e2956043d46..1b13b237edd19 100644 --- a/src/appshell/view/appmenumodel.cpp +++ b/src/appshell/view/appmenumodel.cpp @@ -260,7 +260,7 @@ MenuItem* AppMenuModel::makeViewMenu() makeMenuItem("toggle-timeline"), makeMenuItem("toggle-mixer"), makeMenuItem("toggle-piano-keyboard"), - // makeMenuItem("toggle-percussion-panel"), // still in development + makeMenuItem("toggle-percussion-panel"), makeMenuItem("playback-setup"), //makeMenuItem("toggle-scorecmp-tool"), // not implemented makeSeparator(), From 0587b0a6b01ec2eb87bd8d3537daf9def7d2747f Mon Sep 17 00:00:00 2001 From: Calum Matheson Date: Fri, 21 Feb 2025 14:11:52 +0000 Subject: [PATCH 3/4] Add clear button to shortcut editing dialogs --- .../Shortcuts/EditShortcutDialogContent.qml | 12 ++++++++++++ .../Shortcuts/StandardEditShortcutDialog.qml | 7 ++++++- .../shortcuts/view/editshortcutmodel.cpp | 15 +++++++++++++-- .../shortcuts/view/editshortcutmodel.h | 7 +++++++ .../EditPercussionShortcutDialog.qml | 7 ++++++- src/notation/utilities/percussionutilities.cpp | 8 +++++--- src/notation/utilities/percussionutilities.h | 2 +- .../view/editpercussionshortcutmodel.cpp | 18 +++++++++++++++++- .../view/editpercussionshortcutmodel.h | 7 +++++++ .../percussionpanel/percussionpanelmodel.cpp | 4 +++- .../view/widgets/customizekitdialog.cpp | 4 +++- 11 files changed, 80 insertions(+), 11 deletions(-) diff --git a/src/framework/shortcuts/qml/Muse/Shortcuts/EditShortcutDialogContent.qml b/src/framework/shortcuts/qml/Muse/Shortcuts/EditShortcutDialogContent.qml index b383e77d5ea3e..c50b3dbd77b8d 100644 --- a/src/framework/shortcuts/qml/Muse/Shortcuts/EditShortcutDialogContent.qml +++ b/src/framework/shortcuts/qml/Muse/Shortcuts/EditShortcutDialogContent.qml @@ -44,6 +44,7 @@ Item { signal saveRequested() signal cancelRequested() + signal clearRequested() signal keyPressed(var event) anchors.fill: parent @@ -138,6 +139,17 @@ Item { navigationPanel.section: root.navigationSection navigationPanel.order: 2 + FlatButton { + text: qsTrc("global", "Clear") + buttonRole: ButtonBoxModel.CustomRole + buttonId: ButtonBoxModel.Clear + isLeftSide: true + + onClicked: { + root.clearRequested() + } + } + onStandardButtonClicked: function(buttonId) { if (buttonId === ButtonBoxModel.Cancel) { root.cancelRequested() diff --git a/src/framework/shortcuts/qml/Muse/Shortcuts/StandardEditShortcutDialog.qml b/src/framework/shortcuts/qml/Muse/Shortcuts/StandardEditShortcutDialog.qml index 7505bfbb9a3dc..8941901309d11 100644 --- a/src/framework/shortcuts/qml/Muse/Shortcuts/StandardEditShortcutDialog.qml +++ b/src/framework/shortcuts/qml/Muse/Shortcuts/StandardEditShortcutDialog.qml @@ -63,7 +63,8 @@ StyledDialogView { headerText: qsTrc("shortcuts", "Define keyboard shortcut") - originShortcutText: editShortcutModel.originSequence + //! NOTE: There's no need to actually clear the origin shortcut, we can simply hide it for aesthetic purposes... + originShortcutText: !editShortcutModel.cleared ? editShortcutModel.originSequence : "" newShortcutText: editShortcutModel.newSequence informationText: editShortcutModel.conflictWarning @@ -76,6 +77,10 @@ StyledDialogView { root.reject() } + onClearRequested: { + editShortcutModel.clear() + } + onKeyPressed: function(event) { editShortcutModel.inputKey(event.key, event.modifiers) } diff --git a/src/framework/shortcuts/view/editshortcutmodel.cpp b/src/framework/shortcuts/view/editshortcutmodel.cpp index 2d06428f5fe2b..d803a16f91fd3 100644 --- a/src/framework/shortcuts/view/editshortcutmodel.cpp +++ b/src/framework/shortcuts/view/editshortcutmodel.cpp @@ -63,7 +63,10 @@ void EditShortcutModel::load(const QVariant& originShortcut, const QVariantList& m_originSequence = originShortcutMap.value("sequence").toString(); m_originShortcutTitle = originShortcutMap.value("title").toString(); + m_cleared = false; + emit originSequenceChanged(); + emit clearedChanged(); } void EditShortcutModel::clearNewSequence() @@ -110,6 +113,14 @@ void EditShortcutModel::inputKey(Qt::Key key, Qt::KeyboardModifiers modifiers) emit newSequenceChanged(); } +void EditShortcutModel::clear() +{ + clearNewSequence(); + m_cleared = true; + emit originSequenceChanged(); + emit clearedChanged(); +} + bool EditShortcutModel::isShiftAllowed(Qt::Key key) { if (key >= Qt::Key_A && key <= Qt::Key_Z) { @@ -215,8 +226,8 @@ QString EditShortcutModel::conflictWarning() const void EditShortcutModel::trySave() { QString newSequence = this->newSequence(); - - if (m_originSequence == newSequence) { + const bool alreadyEmpty = originSequenceInNativeFormat().isEmpty() && m_cleared; + if (alreadyEmpty || m_originSequence == newSequence) { return; } diff --git a/src/framework/shortcuts/view/editshortcutmodel.h b/src/framework/shortcuts/view/editshortcutmodel.h index 8ee05fa787117..3040ed03391ac 100644 --- a/src/framework/shortcuts/view/editshortcutmodel.h +++ b/src/framework/shortcuts/view/editshortcutmodel.h @@ -39,6 +39,8 @@ class EditShortcutModel : public QObject, public Injectable Q_PROPERTY(QString newSequence READ newSequenceInNativeFormat NOTIFY newSequenceChanged) Q_PROPERTY(QString conflictWarning READ conflictWarning NOTIFY newSequenceChanged) + Q_PROPERTY(bool cleared READ cleared NOTIFY clearedChanged) + Inject interactive = { this }; public: @@ -47,15 +49,18 @@ class EditShortcutModel : public QObject, public Injectable QString originSequenceInNativeFormat() const; QString newSequenceInNativeFormat() const; QString conflictWarning() const; + bool cleared() const { return m_cleared; } bool isShiftAllowed(Qt::Key key); Q_INVOKABLE void load(const QVariant& shortcut, const QVariantList& allShortcuts); Q_INVOKABLE void inputKey(Qt::Key key, Qt::KeyboardModifiers modifiers); + Q_INVOKABLE void clear(); Q_INVOKABLE void trySave(); signals: void originSequenceChanged(); void newSequenceChanged(); + void clearedChanged(); void applyNewSequenceRequested(const QString& newSequence, int conflictShortcutIndex = -1); @@ -74,6 +79,8 @@ class EditShortcutModel : public QObject, public Injectable QVariantMap m_conflictShortcut; QKeySequence m_newSequence; + + bool m_cleared = false; }; } diff --git a/src/notation/qml/MuseScore/NotationScene/EditPercussionShortcutDialog.qml b/src/notation/qml/MuseScore/NotationScene/EditPercussionShortcutDialog.qml index 0830ebaefbc16..c4c4617fdbc0d 100644 --- a/src/notation/qml/MuseScore/NotationScene/EditPercussionShortcutDialog.qml +++ b/src/notation/qml/MuseScore/NotationScene/EditPercussionShortcutDialog.qml @@ -70,7 +70,8 @@ StyledDialogView { headerText: qsTrc("shortcuts", "Define percussion keyboard shortcut") - originShortcutText: model.originShortcutText + //! NOTE: There's no need to actually clear the origin shortcut, we can simply hide it for aesthetic purposes... + originShortcutText: !model.cleared ? model.originShortcutText : "" newShortcutText: model.newShortcutText informationText: model.informationText @@ -86,6 +87,10 @@ StyledDialogView { root.reject() } + onClearRequested: { + model.clear() + } + onKeyPressed: function(event) { model.inputKey(event.key) } diff --git a/src/notation/utilities/percussionutilities.cpp b/src/notation/utilities/percussionutilities.cpp index ab23df77ef6f0..12ed72e516cf4 100644 --- a/src/notation/utilities/percussionutilities.cpp +++ b/src/notation/utilities/percussionutilities.cpp @@ -105,15 +105,15 @@ std::shared_ptr PercussionUtilities::getDrumNoteForPreview(const Drumset* } /// Opens the percussion shortcut dialog, modifies drumset with user input -void PercussionUtilities::editPercussionShortcut(Drumset& drumset, int originPitch) +bool PercussionUtilities::editPercussionShortcut(Drumset& drumset, int originPitch) { IF_ASSERT_FAILED(drumset.isValid(originPitch)) { - return; + return false; } const muse::RetVal rv = openPercussionShortcutDialog(drumset, originPitch); if (!rv.ret) { - return; + return false; } const QVariantMap vals = rv.val.toQVariant().toMap(); @@ -124,6 +124,8 @@ void PercussionUtilities::editPercussionShortcut(Drumset& drumset, int originPit if (conflictShortcutPitch > -1 && drumset.isValid(conflictShortcutPitch)) { drumset.drum(conflictShortcutPitch).shortcut.clear(); } + + return true; } muse::RetVal PercussionUtilities::openPercussionShortcutDialog(const Drumset& drumset, int originPitch) diff --git a/src/notation/utilities/percussionutilities.h b/src/notation/utilities/percussionutilities.h index bfceb2c06d1af..69c41749844bb 100644 --- a/src/notation/utilities/percussionutilities.h +++ b/src/notation/utilities/percussionutilities.h @@ -48,7 +48,7 @@ class PercussionUtilities public: static void readDrumset(const muse::ByteArray& drumMapping, mu::engraving::Drumset& drumset); static std::shared_ptr getDrumNoteForPreview(const mu::engraving::Drumset* drumset, int pitch); - static void editPercussionShortcut(mu::engraving::Drumset& drumset, int originPitch); + static bool editPercussionShortcut(mu::engraving::Drumset& drumset, int originPitch); private: static muse::RetVal openPercussionShortcutDialog(const mu::engraving::Drumset& drumset, int originPitch); diff --git a/src/notation/view/editpercussionshortcutmodel.cpp b/src/notation/view/editpercussionshortcutmodel.cpp index b884f15fea128..84631cec5a4f7 100644 --- a/src/notation/view/editpercussionshortcutmodel.cpp +++ b/src/notation/view/editpercussionshortcutmodel.cpp @@ -44,7 +44,10 @@ void EditPercussionShortcutModel::load(const QVariant& originDrum, const QVarian m_drumsWithShortcut << drum; } + m_cleared = false; + emit originShortcutTextChanged(); + emit clearedChanged(); } void EditPercussionShortcutModel::inputKey(Qt::Key key) @@ -70,9 +73,22 @@ void EditPercussionShortcutModel::inputKey(Qt::Key key) emit newShortcutTextChanged(); } +void EditPercussionShortcutModel::clear() +{ + m_newShortcut = QKeySequence(); + m_conflictShortcut.clear(); + + m_cleared = true; + + emit newShortcutTextChanged(); + emit clearedChanged(); +} + bool EditPercussionShortcutModel::trySave() { - if (originShortcutText() == m_newShortcut.toString()) { + const QString newShortcut = m_newShortcut.toString(); + const bool alreadyEmpty = originShortcutText().isEmpty() && m_cleared; + if (alreadyEmpty || originShortcutText() == newShortcut) { return false; } diff --git a/src/notation/view/editpercussionshortcutmodel.h b/src/notation/view/editpercussionshortcutmodel.h index f2004264ebc42..28007dd8dd4f8 100644 --- a/src/notation/view/editpercussionshortcutmodel.h +++ b/src/notation/view/editpercussionshortcutmodel.h @@ -37,6 +37,8 @@ class EditPercussionShortcutModel : public QObject, public muse::Injectable Q_PROPERTY(QString newShortcutText READ newShortcutText NOTIFY newShortcutTextChanged) Q_PROPERTY(QString informationText READ informationText NOTIFY newShortcutTextChanged) + Q_PROPERTY(bool cleared READ cleared NOTIFY clearedChanged) + Inject interactive = { this }; public: @@ -44,6 +46,7 @@ class EditPercussionShortcutModel : public QObject, public muse::Injectable Q_INVOKABLE void load(const QVariant& originDrum, const QVariantList& drumsWithShortcut, const QVariantList& applicationShortcuts); Q_INVOKABLE void inputKey(Qt::Key key); + Q_INVOKABLE void clear(); Q_INVOKABLE bool trySave(); Q_INVOKABLE int conflictDrumPitch() const; @@ -52,9 +55,12 @@ class EditPercussionShortcutModel : public QObject, public muse::Injectable QString newShortcutText() const; QString informationText() const; + bool cleared() const { return m_cleared; } + signals: void originShortcutTextChanged(); void newShortcutTextChanged(); + void clearedChanged(); private: bool checkDrumShortcutsForConflict(); @@ -71,5 +77,6 @@ class EditPercussionShortcutModel : public QObject, public muse::Injectable QVariantList m_applicationShortcuts; bool m_conflictInAppShortcuts = false; + bool m_cleared = false; }; } diff --git a/src/notation/view/percussionpanel/percussionpanelmodel.cpp b/src/notation/view/percussionpanel/percussionpanelmodel.cpp index 8dd594e965f7d..0fe0a71ede2df 100644 --- a/src/notation/view/percussionpanel/percussionpanelmodel.cpp +++ b/src/notation/view/percussionpanel/percussionpanelmodel.cpp @@ -448,7 +448,9 @@ void PercussionPanelModel::onDefinePadShortcutRequested(int pitch) } Drumset updatedDrumset = *m_padListModel->drumset(); - PercussionUtilities::editPercussionShortcut(updatedDrumset, pitch); + if (!PercussionUtilities::editPercussionShortcut(updatedDrumset, pitch)) { + return; + } INotationUndoStackPtr undoStack = notation()->undoStack(); diff --git a/src/palette/view/widgets/customizekitdialog.cpp b/src/palette/view/widgets/customizekitdialog.cpp index 5c326cd6a01cd..c93bb0a1e91b2 100644 --- a/src/palette/view/widgets/customizekitdialog.cpp +++ b/src/palette/view/widgets/customizekitdialog.cpp @@ -666,7 +666,9 @@ void CustomizeKitDialog::defineShortcut() } const int originPitch = item->data(Column::PITCH, Qt::UserRole).toInt(); - PercussionUtilities::editPercussionShortcut(m_editedDrumset, originPitch); + if (!PercussionUtilities::editPercussionShortcut(m_editedDrumset, originPitch)) { + return; + } const QString editedShortcutText = m_editedDrumset.shortcut(originPitch); shortcut->setText(!editedShortcutText.isEmpty() ? editedShortcutText : muse::qtrc("shortcuts", "None")); From 3b87493fabd38b6b0723848e8aee968a7f17c808 Mon Sep 17 00:00:00 2001 From: Calum Matheson Date: Fri, 21 Feb 2025 14:45:36 +0000 Subject: [PATCH 4/4] Percussion panel - allow deletion of non-empty rows --- .../NotationScene/PercussionPanel.qml | 15 ++------- .../percussionpanelpadlistmodel.cpp | 33 +++++++------------ .../percussionpanelpadlistmodel.h | 3 -- 3 files changed, 14 insertions(+), 37 deletions(-) diff --git a/src/notation/qml/MuseScore/NotationScene/PercussionPanel.qml b/src/notation/qml/MuseScore/NotationScene/PercussionPanel.qml index c8faac2237ccc..b79fffb0c6579 100644 --- a/src/notation/qml/MuseScore/NotationScene/PercussionPanel.qml +++ b/src/notation/qml/MuseScore/NotationScene/PercussionPanel.qml @@ -166,7 +166,7 @@ Item { onNavigationEvent: { // Use the last known "pad navigation row" and tab to the associated delete button if it exists var padNavigationRow = navigationPrv.currentPadNavigationIndex[0] - if (padGrid.model.rowIsEmpty(padNavigationRow)) { + if (padGrid.numRows > 1) { event.setData("controlIndex", [padNavigationRow, 0]) } } @@ -200,7 +200,7 @@ Item { anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right - visible: padGrid.numRows > 1 && padGrid.model.rowIsEmpty(model.index) + visible: padGrid.numRows > 1 icon: IconCode.DELETE_TANK backgroundRadius: deleteButton.width / 2 @@ -214,17 +214,6 @@ Item { onClicked: { padGrid.model.deleteRow(model.index) } - - Connections { - target: padGrid.model - - function onRowIsEmptyChanged(row, isEmpty) { - if (row !== model.index) { - return - } - deleteButton.visible = padGrid.numRows > 1 && isEmpty - } - } } } } diff --git a/src/notation/view/percussionpanel/percussionpanelpadlistmodel.cpp b/src/notation/view/percussionpanel/percussionpanelpadlistmodel.cpp index 54689f5b575a3..95e08c7541f09 100644 --- a/src/notation/view/percussionpanel/percussionpanelpadlistmodel.cpp +++ b/src/notation/view/percussionpanel/percussionpanelpadlistmodel.cpp @@ -84,7 +84,17 @@ void PercussionPanelPadListModel::addEmptyRow(bool focusFirstInNewRow) void PercussionPanelPadListModel::deleteRow(int row) { + // Update the drumset... + const int startIdx = row * NUM_COLUMNS; + for (int i = startIdx; i < startIdx + NUM_COLUMNS; ++i) { + if (const PercussionPanelPadModel* model = m_padModels.at(i)) { + m_drumset->setDrum(model->pitch(), mu::engraving::DrumInstrument()); + } + } + + // Then remove the row... m_padModels.remove(row * NUM_COLUMNS, NUM_COLUMNS); + emit layoutChanged(); emit numPadsChanged(); } @@ -95,7 +105,8 @@ void PercussionPanelPadListModel::removeEmptyRows() const int lastRowIndex = numPads() / NUM_COLUMNS - 1; for (int i = lastRowIndex; i >= 0; --i) { const int numRows = numPads() / NUM_COLUMNS; - if (rowIsEmpty(i) && numRows > 1) { // never delete the first row + const bool rowIsEmpty = numEmptySlotsAtRow(i) == NUM_COLUMNS; + if (rowIsEmpty && numRows > 1) { // never delete the first row m_padModels.remove(i * NUM_COLUMNS, NUM_COLUMNS); rowsRemoved = true; } @@ -106,11 +117,6 @@ void PercussionPanelPadListModel::removeEmptyRows() } } -bool PercussionPanelPadListModel::rowIsEmpty(int row) const -{ - return numEmptySlotsAtRow(row) == NUM_COLUMNS; -} - void PercussionPanelPadListModel::startPadSwap(int startIndex) { m_padSwapStartIndex = startIndex; @@ -424,23 +430,8 @@ int PercussionPanelPadListModel::getModelIndexForPitch(int pitch) const void PercussionPanelPadListModel::movePad(int fromIndex, int toIndex) { - const int fromRow = fromIndex / NUM_COLUMNS; - const int toRow = toIndex / NUM_COLUMNS; - - // fromRow will become empty if there's only 1 "occupied" slot, toRow will no longer be empty if it was previously... - const bool fromRowEmptyChanged = numEmptySlotsAtRow(fromRow) == NUM_COLUMNS - 1; - const bool toRowEmptyChanged = rowIsEmpty(toRow); - m_padModels.swapItemsAt(fromIndex, toIndex); emit layoutChanged(); - - if (fromRowEmptyChanged) { - emit rowIsEmptyChanged(fromRow, /*isEmpty*/ true); - } - - if (toRowEmptyChanged) { - emit rowIsEmptyChanged(toRow, /*isEmpty*/ false); - } } int PercussionPanelPadListModel::numEmptySlotsAtRow(int row) const diff --git a/src/notation/view/percussionpanel/percussionpanelpadlistmodel.h b/src/notation/view/percussionpanel/percussionpanelpadlistmodel.h index ec049f60bc277..8c9b2b8d4b740 100644 --- a/src/notation/view/percussionpanel/percussionpanelpadlistmodel.h +++ b/src/notation/view/percussionpanel/percussionpanelpadlistmodel.h @@ -61,8 +61,6 @@ class PercussionPanelPadListModel : public QAbstractListModel, public muse::Inje void removeEmptyRows(); - Q_INVOKABLE bool rowIsEmpty(int row) const; - Q_INVOKABLE void startPadSwap(int startIndex); Q_INVOKABLE void endPadSwap(int endIndex); bool swapInProgress() const { return indexIsValid(m_padSwapStartIndex); } @@ -89,7 +87,6 @@ class PercussionPanelPadListModel : public QAbstractListModel, public muse::Inje signals: void numPadsChanged(); - void rowIsEmptyChanged(int row, bool empty); void padFocusRequested(int padIndex); //! NOTE: This won't work if it is called immediately before a layoutChange private: