diff --git a/src/appshell/qml/NotationPage/NotationPage.qml b/src/appshell/qml/NotationPage/NotationPage.qml index 5b1c5a3041c56..e3b6b515b7421 100644 --- a/src/appshell/qml/NotationPage/NotationPage.qml +++ b/src/appshell/qml/NotationPage/NotationPage.qml @@ -336,6 +336,7 @@ DockPage { Component.onCompleted: { mixerPanel.contextMenuModel = contextMenuModel + mixerPanel.toolbarComponent = toolbarComponent } onResizeRequested: function(newWidth, newHeight) { diff --git a/src/appshell/qml/dockwindow/DockFrame.qml b/src/appshell/qml/dockwindow/DockFrame.qml index d75f999926933..10f8bcf5157e8 100644 --- a/src/appshell/qml/dockwindow/DockFrame.qml +++ b/src/appshell/qml/dockwindow/DockFrame.qml @@ -112,6 +112,8 @@ Rectangle { tabsModel: frameModel.tabs currentIndex: Boolean(root.frameCpp) && root.frameCpp.currentIndex >= 0 ? root.frameCpp.currentIndex : 0 + currentToolbarComponent: frameModel.currentDockToolbarComponent + navigationPanel: navPanel function setCurrentDockWidget(index: int) { diff --git a/src/appshell/qml/dockwindow/DockTabBar.qml b/src/appshell/qml/dockwindow/DockTabBar.qml index b90c16e3e1bd9..673198e3db92f 100644 --- a/src/appshell/qml/dockwindow/DockTabBar.qml +++ b/src/appshell/qml/dockwindow/DockTabBar.qml @@ -41,6 +41,8 @@ Rectangle { property NavigationPanel navigationPanel: null readonly property string currentItemNavigationName: tabs.currentItem && tabs.currentItem.navigation ? tabs.currentItem.navigation.name : "" + property alias currentToolbarComponent: toolbarLoader.sourceComponent + signal tabClicked(int index) signal handleContextMenuItemRequested(string itemId) @@ -130,7 +132,18 @@ Rectangle { cursorShape: Qt.SizeAllCursor } + Loader { + id: toolbarLoader + + anchors.top: parent.top + anchors.left: tabs.right + anchors.right: parent.right + anchors.bottom: bottomSeparatorContainer.top + } + Item { + id: bottomSeparatorContainer + anchors.left: tabs.right anchors.right: parent.right anchors.bottom: parent.bottom diff --git a/src/appshell/view/dockwindow/dockpanelview.cpp b/src/appshell/view/dockwindow/dockpanelview.cpp index bb905ab3bdc1e..43d74795f5cab 100644 --- a/src/appshell/view/dockwindow/dockpanelview.cpp +++ b/src/appshell/view/dockwindow/dockpanelview.cpp @@ -163,6 +163,7 @@ DockPanelView::~DockPanelView() dockWidget->setProperty(DOCK_PANEL_PROPERTY, QVariant::fromValue(nullptr)); dockWidget->setProperty(CONTEXT_MENU_MODEL_PROPERTY, QVariant::fromValue(nullptr)); + dockWidget->setProperty(TOOLBAR_COMPONENT_PROPERTY, QVariant::fromValue(nullptr)); } QString DockPanelView::groupName() const @@ -193,12 +194,19 @@ void DockPanelView::componentComplete() dockWidget->setProperty(DOCK_PANEL_PROPERTY, QVariant::fromValue(this)); dockWidget->setProperty(CONTEXT_MENU_MODEL_PROPERTY, QVariant::fromValue(m_menuModel)); + dockWidget->setProperty(TOOLBAR_COMPONENT_PROPERTY, QVariant::fromValue(m_toolbarComponent)); connect(m_menuModel, &AbstractMenuModel::itemsChanged, [dockWidget, this]() { if (dockWidget) { dockWidget->setProperty(CONTEXT_MENU_MODEL_PROPERTY, QVariant::fromValue(m_menuModel)); } }); + + connect(this, &DockPanelView::toolbarComponentChanged, this, [this, dockWidget]() { + if (dockWidget) { + dockWidget->setProperty(TOOLBAR_COMPONENT_PROPERTY, QVariant::fromValue(m_toolbarComponent)); + } + }); } QObject* DockPanelView::navigationSection() const @@ -221,6 +229,11 @@ AbstractMenuModel* DockPanelView::contextMenuModel() const return m_menuModel->customMenuModel(); } +QQmlComponent* DockPanelView::toolbarComponent() const +{ + return m_toolbarComponent; +} + void DockPanelView::setContextMenuModel(AbstractMenuModel* model) { if (m_menuModel->customMenuModel() == model) { @@ -232,6 +245,16 @@ void DockPanelView::setContextMenuModel(AbstractMenuModel* model) emit contextMenuModelChanged(); } +void DockPanelView::setToolbarComponent(QQmlComponent* component) +{ + if (m_toolbarComponent == component) { + return; + } + + m_toolbarComponent = component; + emit toolbarComponentChanged(); +} + bool DockPanelView::isTabAllowed(const DockPanelView* tab) const { IF_ASSERT_FAILED(tab) { diff --git a/src/appshell/view/dockwindow/dockpanelview.h b/src/appshell/view/dockwindow/dockpanelview.h index b14aa66769d7e..ad9715abd4983 100644 --- a/src/appshell/view/dockwindow/dockpanelview.h +++ b/src/appshell/view/dockwindow/dockpanelview.h @@ -25,10 +25,10 @@ #include "internal/dockbase.h" -#include "framework/uicomponents/view/qmllistproperty.h" - #include "uicomponents/view/abstractmenumodel.h" +class QQmlComponent; + namespace mu::uicomponents { class AbstractMenuModel; } @@ -43,6 +43,7 @@ class DockPanelView : public DockBase Q_PROPERTY( mu::uicomponents::AbstractMenuModel * contextMenuModel READ contextMenuModel WRITE setContextMenuModel NOTIFY contextMenuModelChanged) + Q_PROPERTY(QQmlComponent * toolbarComponent READ toolbarComponent WRITE setToolbarComponent NOTIFY toolbarComponentChanged) public: explicit DockPanelView(QQuickItem* parent = nullptr); @@ -51,6 +52,7 @@ class DockPanelView : public DockBase QString groupName() const; QObject* navigationSection() const; uicomponents::AbstractMenuModel* contextMenuModel() const; + QQmlComponent* toolbarComponent() const; bool isTabAllowed(const DockPanelView* tab) const; void addPanelAsTab(DockPanelView* tab); @@ -60,11 +62,13 @@ public slots: void setGroupName(const QString& name); void setNavigationSection(QObject* newNavigation); void setContextMenuModel(uicomponents::AbstractMenuModel* model); + void setToolbarComponent(QQmlComponent* component); signals: void groupNameChanged(); void navigationSectionChanged(); void contextMenuModelChanged(); + void toolbarComponentChanged(); private: void componentComplete() override; @@ -74,6 +78,8 @@ public slots: class DockPanelMenuModel; DockPanelMenuModel* m_menuModel = nullptr; + + QQmlComponent* m_toolbarComponent = nullptr; }; } diff --git a/src/appshell/view/dockwindow/docktypes.h b/src/appshell/view/dockwindow/docktypes.h index 85d347a0e42f5..e0a663841b359 100644 --- a/src/appshell/view/dockwindow/docktypes.h +++ b/src/appshell/view/dockwindow/docktypes.h @@ -29,6 +29,7 @@ namespace mu::dock { inline const char* CONTEXT_MENU_MODEL_PROPERTY("contextMenuModel"); inline const char* DOCK_PANEL_PROPERTY("dockPanel"); +inline const char* TOOLBAR_COMPONENT_PROPERTY("toolbarComponent"); //! NOTE: need to be synchronized with Window shadow(see DockFloatingWindow margins) inline constexpr int DOCK_WINDOW_SHADOW(8); diff --git a/src/appshell/view/dockwindow/internal/dockframemodel.cpp b/src/appshell/view/dockwindow/internal/dockframemodel.cpp index c0c92e86d55c5..1a3e68d2c047f 100644 --- a/src/appshell/view/dockwindow/internal/dockframemodel.cpp +++ b/src/appshell/view/dockwindow/internal/dockframemodel.cpp @@ -55,7 +55,8 @@ bool DockFrameModel::eventFilter(QObject* watched, QEvent* event) return QObject::eventFilter(watched, event); } - if (propertyChangeEvent->propertyName() == CONTEXT_MENU_MODEL_PROPERTY) { + if (propertyChangeEvent->propertyName() == CONTEXT_MENU_MODEL_PROPERTY + || propertyChangeEvent->propertyName() == TOOLBAR_COMPONENT_PROPERTY) { emit tabsChanged(); if (watched == currentDockWidget()) { @@ -87,6 +88,7 @@ QVariantList DockFrameModel::tabs() const QVariantMap tab; tab["title"] = dock->title(); tab[CONTEXT_MENU_MODEL_PROPERTY] = dock->property(CONTEXT_MENU_MODEL_PROPERTY); + tab[TOOLBAR_COMPONENT_PROPERTY] = dock->property(TOOLBAR_COMPONENT_PROPERTY); result << tab; } @@ -204,6 +206,11 @@ QVariant DockFrameModel::currentDockContextMenuModel() const return currentDockProperty(CONTEXT_MENU_MODEL_PROPERTY); } +QVariant DockFrameModel::currentDockToolbarComponent() const +{ + return currentDockProperty(TOOLBAR_COMPONENT_PROPERTY); +} + bool DockFrameModel::highlightingVisible() const { return highlightingRect().isValid(); diff --git a/src/appshell/view/dockwindow/internal/dockframemodel.h b/src/appshell/view/dockwindow/internal/dockframemodel.h index e4aa6a5673aad..3427913b96296 100644 --- a/src/appshell/view/dockwindow/internal/dockframemodel.h +++ b/src/appshell/view/dockwindow/internal/dockframemodel.h @@ -48,6 +48,7 @@ class DockFrameModel : public QObject Q_PROPERTY(QObject * navigationSection READ navigationSection NOTIFY navigationSectionChanged) Q_PROPERTY(QString currentDockUniqueName READ currentDockUniqueName NOTIFY currentDockChanged) Q_PROPERTY(QVariant currentDockContextMenuModel READ currentDockContextMenuModel NOTIFY currentDockChanged) + Q_PROPERTY(QVariant currentDockToolbarComponent READ currentDockToolbarComponent NOTIFY currentDockChanged) Q_PROPERTY(bool highlightingVisible READ highlightingVisible NOTIFY highlightingVisibleChanged) Q_PROPERTY(QRect highlightingRect READ highlightingRect NOTIFY highlightingVisibleChanged) @@ -63,6 +64,7 @@ class DockFrameModel : public QObject QObject* navigationSection() const; QString currentDockUniqueName() const; QVariant currentDockContextMenuModel() const; + QVariant currentDockToolbarComponent() const; bool highlightingVisible() const; QRect highlightingRect() const; diff --git a/src/playback/playback.qrc b/src/playback/playback.qrc index 206c1bcf355bf..34af2d57adbf4 100644 --- a/src/playback/playback.qrc +++ b/src/playback/playback.qrc @@ -5,6 +5,7 @@ qml/MuseScore/Playback/internal/MeasureAndBeatFields.qml qml/MuseScore/Playback/internal/TempoSlider.qml qml/MuseScore/Playback/MixerPanel.qml + qml/MuseScore/Playback/internal/MixerPanelToolbar.qml qml/MuseScore/Playback/internal/MixerPanelSection.qml qml/MuseScore/Playback/internal/MixerBalanceSection.qml qml/MuseScore/Playback/internal/MixerVolumeSection.qml diff --git a/src/playback/qml/MuseScore/Playback/MixerPanel.qml b/src/playback/qml/MuseScore/Playback/MixerPanel.qml index 8660d4b5885ff..31972520d593f 100644 --- a/src/playback/qml/MuseScore/Playback/MixerPanel.qml +++ b/src/playback/qml/MuseScore/Playback/MixerPanel.qml @@ -34,6 +34,10 @@ ColumnLayout { id: root property alias contextMenuModel: contextMenuModel + property Component toolbarComponent: MixerPanelToolbar { + navigation.section: root.navigationSection + navigation.order: 1 + } property NavigationSection navigationSection: null property NavigationPanel navigationPanel: mixerPanelModel.count > 0 ? mixerPanelModel.get(0).channelItem.panel : null // first panel diff --git a/src/playback/qml/MuseScore/Playback/internal/MixerPanelToolbar.qml b/src/playback/qml/MuseScore/Playback/internal/MixerPanelToolbar.qml new file mode 100644 index 0000000000000..cd421aa752e04 --- /dev/null +++ b/src/playback/qml/MuseScore/Playback/internal/MixerPanelToolbar.qml @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-CLA-applies + * + * MuseScore + * Music Composition & Notation + * + * Copyright (C) 2023 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 MuseScore.Ui 1.0 +import MuseScore.UiComponents 1.0 + +Item { + id: root + + property alias navigation: navPanel + + anchors.fill: parent + + NavigationPanel { + id: navPanel + name: "MixerPanelToolbarPanel" + enabled: root.enabled && root.visible + } + + FlatButton { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 2 + + icon: IconCode.SETTINGS_COG + text: qsTrc("playback", "Customize mixer") + orientation: Qt.Horizontal + + navigation.panel: navPanel + navigation.row: 0 + } +}