LCOV - code coverage report
Current view: top level - muse/framework/dockwindow_v2/qml/Muse/Dock - dockpanelview.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 33.6 % 152 51
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "dockpanelview.h"
      24              : 
      25              : #include "kddockwidgets/src/core/DockWidget.h"
      26              : #include "kddockwidgets/src/core/Group.h"
      27              : #include "kddockwidgets/src/qtquick/views/DockWidget.h"
      28              : #include "kddockwidgets/src/qtquick/views/View.h"
      29              : 
      30              : #include "rcommand/commandtypes.h"
      31              : #include "types/translatablestring.h"
      32              : 
      33              : #include "uicomponents/qml/Muse/UiComponents/abstractmenumodel.h"
      34              : 
      35              : #include "dockcommands.h"
      36              : 
      37              : #include "log.h"
      38              : 
      39              : using namespace muse;
      40              : using namespace muse::dock;
      41              : using namespace muse::ui;
      42              : using namespace muse::uicomponents;
      43              : 
      44              : class DockPanelView::DockPanelMenuModel : public muse::uicomponents::AbstractMenuModel
      45              : {
      46              : public:
      47            3 :     DockPanelMenuModel(DockPanelView* panel)
      48            3 :         : AbstractMenuModel(panel), m_panel(panel)
      49              :     {
      50            3 :         listenFloatingChanged();
      51            3 :     }
      52              : 
      53            3 :     void load() override
      54              :     {
      55            4 :         TRACEFUNC;
      56              : 
      57            3 :         MenuItemList items;
      58              : 
      59            3 :         if (m_customMenuModel && m_customMenuModel->rowCount() > 0) {
      60            0 :             items << m_customMenuModel->items();
      61            0 :             items << makeSeparator();
      62              :         }
      63              : 
      64            3 :         MenuItem* closeDockItem = makeMenuItem(DOCK_SET_OPEN_COMMAND, TranslatableString("appshell/dock", "Close"));
      65           12 :         closeDockItem->setParams({ { "dock_name", Val(m_panel->objectName().toStdString()) }, { "open", Val(false) } });
      66            3 :         items << closeDockItem;
      67              : 
      68            3 :         MenuItem* toggleFloatingItem = makeMenuItem(DOCK_TOGGLE_FLOATING_COMMAND, toggleFloatingActionTitle());
      69            9 :         toggleFloatingItem->setParams({ { "dock_name", Val(m_panel->objectName().toStdString()) } });
      70            3 :         items << toggleFloatingItem;
      71              : 
      72            3 :         setItems(items);
      73           15 :     }
      74              : 
      75            0 :     void handleMenuItem(const QString& itemId) override
      76              :     {
      77              :         // my items
      78            0 :         rcommand::Command cmd(itemId.toStdString());
      79            0 :         if (cmd == DOCK_SET_OPEN_COMMAND || cmd == DOCK_TOGGLE_FLOATING_COMMAND) {
      80            0 :             AbstractMenuModel::handleMenuItem(itemId);
      81            0 :             return;
      82              :         }
      83              : 
      84              :         // forward to custom model
      85            0 :         if (m_customMenuModel) {
      86            0 :             m_customMenuModel->handleMenuItem(itemId);
      87              :         }
      88            0 :     }
      89              : 
      90            0 :     AbstractMenuModel* customMenuModel() const
      91              :     {
      92            0 :         return m_customMenuModel;
      93              :     }
      94              : 
      95            0 :     void setCustomMenuModel(AbstractMenuModel* model)
      96              :     {
      97            0 :         m_customMenuModel = model;
      98              : 
      99            0 :         if (!model) {
     100            0 :             return;
     101              :         }
     102              : 
     103            0 :         connect(model, &AbstractMenuModel::itemsChanged, this, [this]() {
     104            0 :             load();
     105            0 :         });
     106              : 
     107            0 :         connect(model, &AbstractMenuModel::itemChanged, this, [this](MenuItem* item) {
     108            0 :             updateItem(item);
     109            0 :         });
     110              : 
     111            0 :         connect(model, &AbstractMenuModel::destroyed, this, [this]() {
     112            0 :             m_customMenuModel = nullptr;
     113            0 :         });
     114              :     }
     115              : 
     116              : private:
     117              : 
     118            3 :     TranslatableString toggleFloatingActionTitle() const
     119              :     {
     120            3 :         return m_panel->floating() ? TranslatableString("appshell/dock", "Dock") : TranslatableString("appshell/dock", "Undock");
     121              :     }
     122              : 
     123            3 :     void listenFloatingChanged()
     124              :     {
     125            3 :         connect(m_panel, &DockPanelView::floatingChanged, this, [this]() {
     126            0 :             MenuItem& item = findItem(DOCK_TOGGLE_FLOATING_COMMAND);
     127            0 :             item.setTitle(toggleFloatingActionTitle());
     128            0 :         });
     129            3 :     }
     130              : 
     131            0 :     void updateItem(MenuItem* newItem)
     132              :     {
     133            0 :         int index = itemIndex(newItem->id());
     134              : 
     135            0 :         if (index == INVALID_ITEM_INDEX) {
     136            0 :             return;
     137              :         }
     138              : 
     139            0 :         setItem(index, newItem);
     140              :     }
     141              : 
     142              :     AbstractMenuModel* m_customMenuModel = nullptr;
     143              :     DockPanelView* m_panel = nullptr;
     144              : };
     145              : 
     146            3 : DockPanelView::DockPanelView(QQuickItem* parent)
     147            3 :     : DockBase(DockType::Panel, parent), m_menuModel(new DockPanelMenuModel(this))
     148              : {
     149            3 :     setLocation(Location::Left);
     150            3 : }
     151              : 
     152            6 : DockPanelView::~DockPanelView()
     153              : {
     154            6 :     auto* dockWidgetView = qobject_cast<KDDockWidgets::QtQuick::DockWidget*>(
     155            3 :         KDDockWidgets::QtQuick::asQQuickItem(dockWidget()));
     156            3 :     if (!dockWidgetView) {
     157            0 :         return;
     158              :     }
     159              : 
     160            3 :     dockWidgetView->setProperty(DOCK_PANEL_PROPERTY, QVariant::fromValue(nullptr));
     161            3 :     dockWidgetView->setProperty(CONTEXT_MENU_MODEL_PROPERTY, QVariant::fromValue(nullptr));
     162            3 :     dockWidgetView->setProperty(TITLEBAR_PROPERTY, QVariant::fromValue(nullptr));
     163            3 :     dockWidgetView->setProperty(TOOLBAR_COMPONENT_PROPERTY, QVariant::fromValue(nullptr));
     164            6 : }
     165              : 
     166            0 : QString DockPanelView::groupName() const
     167              : {
     168            0 :     return m_groupName;
     169              : }
     170              : 
     171            0 : void DockPanelView::setGroupName(const QString& name)
     172              : {
     173            0 :     if (m_groupName == name) {
     174            0 :         return;
     175              :     }
     176              : 
     177            0 :     m_groupName = name;
     178            0 :     emit groupNameChanged();
     179              : }
     180              : 
     181            3 : void DockPanelView::componentComplete()
     182              : {
     183            3 :     DockBase::componentComplete();
     184              : 
     185            6 :     auto* dockWidgetView = qobject_cast<KDDockWidgets::QtQuick::DockWidget*>(
     186            3 :         KDDockWidgets::QtQuick::asQQuickItem(dockWidget()));
     187            3 :     IF_ASSERT_FAILED(dockWidgetView) {
     188            0 :         return;
     189              :     }
     190              : 
     191            3 :     m_menuModel->load();
     192              : 
     193            3 :     dockWidgetView->setProperty(DOCK_PANEL_PROPERTY, QVariant::fromValue(this));
     194            3 :     dockWidgetView->setProperty(CONTEXT_MENU_MODEL_PROPERTY, QVariant::fromValue(m_menuModel));
     195            3 :     dockWidgetView->setProperty(TITLEBAR_PROPERTY, QVariant::fromValue(m_titleBar));
     196            3 :     dockWidgetView->setProperty(TOOLBAR_COMPONENT_PROPERTY, QVariant::fromValue(m_toolbarComponent));
     197              : 
     198            3 :     connect(m_menuModel, &AbstractMenuModel::itemsChanged, [dockWidgetView, this]() {
     199            0 :         if (dockWidgetView) {
     200            0 :             dockWidgetView->setProperty(CONTEXT_MENU_MODEL_PROPERTY, QVariant::fromValue(m_menuModel));
     201              :         }
     202            0 :     });
     203              : 
     204            3 :     connect(this, &DockPanelView::toolbarComponentChanged, this, [this, dockWidgetView]() {
     205            0 :         if (dockWidgetView) {
     206            0 :             dockWidgetView->setProperty(TOOLBAR_COMPONENT_PROPERTY, QVariant::fromValue(m_toolbarComponent));
     207              :         }
     208            0 :     });
     209              : 
     210            3 :     connect(this, &DockBase::frameCurrentWidgetChanged, this, [this]() {
     211            0 :         auto* ctrl = dockWidget();
     212            0 :         if (!ctrl) {
     213            0 :             return;
     214              :         }
     215            0 :         auto* dockWidgetView = qobject_cast<KDDockWidgets::QtQuick::DockWidget*>(
     216            0 :             KDDockWidgets::QtQuick::asQQuickItem(ctrl));
     217            0 :         auto* group = dockWidgetView ? dockWidgetView->group() : nullptr;
     218            0 :         if (group && group->currentDockWidget() == ctrl) {
     219            0 :             emit panelShown();
     220              :         }
     221              :     });
     222              : }
     223              : 
     224            0 : AbstractMenuModel* DockPanelView::contextMenuModel() const
     225              : {
     226            0 :     return m_menuModel->customMenuModel();
     227              : }
     228              : 
     229            0 : QQmlComponent* DockPanelView::titleBar() const
     230              : {
     231            0 :     return m_titleBar;
     232              : }
     233              : 
     234            0 : QQmlComponent* DockPanelView::toolbarComponent() const
     235              : {
     236            0 :     return m_toolbarComponent;
     237              : }
     238              : 
     239            0 : void DockPanelView::setContextMenuModel(AbstractMenuModel* model)
     240              : {
     241            0 :     if (m_menuModel->customMenuModel() == model) {
     242            0 :         return;
     243              :     }
     244              : 
     245            0 :     m_menuModel->setCustomMenuModel(model);
     246            0 :     m_menuModel->load();
     247            0 :     emit contextMenuModelChanged();
     248              : }
     249              : 
     250            0 : void DockPanelView::setTitleBar(QQmlComponent* titleBar)
     251              : {
     252            0 :     if (m_titleBar == titleBar) {
     253            0 :         return;
     254              :     }
     255              : 
     256            0 :     m_titleBar = titleBar;
     257            0 :     emit titleBarChanged();
     258              : }
     259              : 
     260            0 : void DockPanelView::setToolbarComponent(QQmlComponent* component)
     261              : {
     262            0 :     if (m_toolbarComponent == component) {
     263            0 :         return;
     264              :     }
     265              : 
     266            0 :     m_toolbarComponent = component;
     267            0 :     emit toolbarComponentChanged();
     268              : }
     269              : 
     270            3 : bool DockPanelView::isTabAllowed(const DockPanelView* tab) const
     271              : {
     272            3 :     IF_ASSERT_FAILED(tab) {
     273            0 :         return false;
     274              :     }
     275              : 
     276            3 :     if (tab == this) {
     277            3 :         return false;
     278              :     }
     279              : 
     280            0 :     if (!isOpen()) {
     281            0 :         return false;
     282              :     }
     283              : 
     284            0 :     if (floating()) {
     285            0 :         return false;
     286              :     }
     287              : 
     288            0 :     if (m_groupName.isEmpty() || tab->m_groupName.isEmpty()) {
     289            0 :         return false;
     290              :     }
     291              : 
     292            0 :     return m_groupName == tab->m_groupName;
     293              : }
     294              : 
     295            0 : void DockPanelView::addPanelAsTab(DockPanelView* tab)
     296              : {
     297            0 :     IF_ASSERT_FAILED(tab && dockWidget()) {
     298            0 :         return;
     299              :     }
     300              : 
     301            0 :     if (!isTabAllowed(tab)) {
     302            0 :         return;
     303              :     }
     304              : 
     305            0 :     dockWidget()->addDockWidgetAsTab(tab->dockWidget());
     306            0 :     tab->setVisible(true);
     307              : }
     308              : 
     309            0 : void DockPanelView::setCurrentTabIndex(int index)
     310              : {
     311            0 :     IF_ASSERT_FAILED(dockWidget()) {
     312            0 :         return;
     313              :     }
     314              : 
     315            0 :     auto* dockWidgetView = qobject_cast<KDDockWidgets::QtQuick::DockWidget*>(
     316            0 :         KDDockWidgets::QtQuick::asQQuickItem(dockWidget()));
     317            0 :     auto* group = dockWidgetView ? dockWidgetView->group() : nullptr;
     318            0 :     if (group) {
     319            0 :         group->setCurrentTabIndex(index);
     320              :     }
     321              : }
        

Generated by: LCOV version 2.0-1