From 36489eeb62941e1836f05d7051d29825867bda2b Mon Sep 17 00:00:00 2001 From: Roman Pudashkin Date: Fri, 29 Oct 2021 11:03:53 +0200 Subject: [PATCH] refactored the docking behaviour --- src/appshell/appshell.qrc | 1 + src/appshell/qml/DevTools/DevToolsPage.qml | 2 +- src/appshell/qml/HomePage/HomePage.qml | 2 +- .../qml/NotationPage/NotationPage.qml | 56 ++- src/appshell/qml/WindowContent.qml | 4 +- src/appshell/qml/dockwindow/DockFrame.qml | 18 + src/appshell/qml/dockwindow/DockPage.qml | 58 ++- .../dockwindow/DockingHolder.qml} | 19 +- .../view/dockwindow/dockcentralview.cpp | 2 +- ...oolbarholder.cpp => dockingholderview.cpp} | 28 +- ...ocktoolbarholder.h => dockingholderview.h} | 12 +- src/appshell/view/dockwindow/dockpageview.cpp | 69 +-- src/appshell/view/dockwindow/dockpageview.h | 23 +- .../view/dockwindow/dockpanelview.cpp | 2 +- src/appshell/view/dockwindow/docksetup.cpp | 11 +- .../view/dockwindow/dockstatusbarview.cpp | 2 - .../view/dockwindow/docktoolbarview.cpp | 11 +- src/appshell/view/dockwindow/docktypes.h | 39 +- src/appshell/view/dockwindow/dockwindow.cmake | 8 +- src/appshell/view/dockwindow/dockwindow.cpp | 462 +++++++++++------- src/appshell/view/dockwindow/dockwindow.h | 46 +- src/appshell/view/dockwindow/idockwindow.h | 14 +- .../view/dockwindow/internal/dockbase.cpp | 145 ++++-- .../view/dockwindow/internal/dockbase.h | 76 ++- .../dockwindow/internal/dockframemodel.cpp | 55 ++- .../view/dockwindow/internal/dockframemodel.h | 11 +- .../dockwindow/internal/dragcontroller.cpp | 101 ++++ .../dragcontroller.h} | 24 +- .../dockwindow/internal/dropindicators.cpp | 72 +-- 29 files changed, 877 insertions(+), 496 deletions(-) rename src/appshell/{view/dockwindow/dockpanelholder.cpp => qml/dockwindow/DockingHolder.qml} (73%) rename src/appshell/view/dockwindow/{docktoolbarholder.cpp => dockingholderview.cpp} (63%) rename src/appshell/view/dockwindow/{docktoolbarholder.h => dockingholderview.h} (78%) create mode 100644 src/appshell/view/dockwindow/internal/dragcontroller.cpp rename src/appshell/view/dockwindow/{dockpanelholder.h => internal/dragcontroller.h} (55%) diff --git a/src/appshell/appshell.qrc b/src/appshell/appshell.qrc index c9054e65e1..ff754b40b5 100644 --- a/src/appshell/appshell.qrc +++ b/src/appshell/appshell.qrc @@ -69,6 +69,7 @@ qml/dockwindow/DockPanel.qml qml/dockwindow/DropIndicators.qml qml/dockwindow/DropIndicator.qml + qml/dockwindow/DockingHolder.qml qml/AppWindow.qml qml/WindowContent.qml qml/platform/linux/Main.qml diff --git a/src/appshell/qml/DevTools/DevToolsPage.qml b/src/appshell/qml/DevTools/DevToolsPage.qml index a1fe16f81e..5c3738f3a8 100644 --- a/src/appshell/qml/DevTools/DevToolsPage.qml +++ b/src/appshell/qml/DevTools/DevToolsPage.qml @@ -71,7 +71,7 @@ DockPage { minimumWidth: 200 maximumWidth: 280 - allowedAreas: Qt.NoDockWidgetArea + persistent: true Rectangle { anchors.fill: parent diff --git a/src/appshell/qml/HomePage/HomePage.qml b/src/appshell/qml/HomePage/HomePage.qml index 4e91250785..dd1363a48f 100644 --- a/src/appshell/qml/HomePage/HomePage.qml +++ b/src/appshell/qml/HomePage/HomePage.qml @@ -71,7 +71,7 @@ DockPage { minimumWidth: 76 maximumWidth: 280 - allowedAreas: Qt.NoDockWidgetArea + persistent: true HomeMenu { currentPageName: root.section diff --git a/src/appshell/qml/NotationPage/NotationPage.qml b/src/appshell/qml/NotationPage/NotationPage.qml index 7232385138..d9f2278ad2 100644 --- a/src/appshell/qml/NotationPage/NotationPage.qml +++ b/src/appshell/qml/NotationPage/NotationPage.qml @@ -127,6 +127,10 @@ DockPage { alignment: DockToolBarAlignment.Right contentBottomPadding: 2 + dropDestinations: [ + { "dock": notationToolBar, "dropLocation": DropLocation.Right } + ] + PlaybackToolBar { navigation.section: root.topToolKeyNavSec navigation.order: 3 @@ -161,11 +165,16 @@ DockPage { objectName: pageModel.noteInputBarName() title: qsTrc("appshell", "Note input") - allowedAreas: { Qt.AllDockWidgetAreas } - minimumWidth: floating && orientation === Qt.Horizontal ? 720 : 76 minimumHeight: floating && orientation === Qt.Vertical ? 720 : 40 + dropDestinations: [ + root.toolBarTopDropDestination, + root.toolBarBottomDropDestination, + root.toolBarLeftDropDestination, + root.toolBarRightDropDestination + ] + NoteInputBar { orientation: noteInputBar.orientation floating: noteInputBar.floating @@ -196,6 +205,11 @@ DockPage { location: DockBase.Left + dropDestinations: [ + root.panelLeftDropDestination, + root.panelRightDropDestination + ] + PalettesPanel { navigationSection: palettesPanel.navigationSection } @@ -217,6 +231,11 @@ DockPage { location: DockBase.Left + dropDestinations: [ + root.panelLeftDropDestination, + root.panelRightDropDestination + ] + InstrumentsPanel { navigationSection: instrumentsPanel.navigationSection @@ -242,6 +261,11 @@ DockPage { location: DockBase.Left + dropDestinations: [ + root.panelLeftDropDestination, + root.panelRightDropDestination + ] + InspectorForm { navigationSection: inspectorPanel.navigationSection } @@ -264,6 +288,11 @@ DockPage { location: DockBase.Left + dropDestinations: [ + root.panelLeftDropDestination, + root.panelRightDropDestination + ] + SelectionFilterPanel { navigationSection: selectionFilterPanel.navigationSection } @@ -279,8 +308,6 @@ DockPage { objectName: pageModel.mixerPanelName() title: qsTrc("appshell", "Mixer") - allowedAreas: Qt.TopDockWidgetArea | Qt.BottomDockWidgetArea - height: minimumHeight minimumHeight: 260 maximumHeight: 520 @@ -292,6 +319,11 @@ DockPage { location: DockBase.Bottom + dropDestinations: [ + root.panelTopDropDestination, + root.panelBottomDropDestination + ] + navigationSection: root.navigationPanelSec(mixerPanel.location) MixerPanel { @@ -309,8 +341,6 @@ DockPage { objectName: pageModel.pianoPanelName() title: qsTrc("appshell", "Piano Roll") - allowedAreas: Qt.TopDockWidgetArea | Qt.BottomDockWidgetArea - height: 200 minimumHeight: 100 maximumHeight: 300 @@ -322,6 +352,11 @@ DockPage { location: DockBase.Bottom + dropDestinations: [ + root.panelTopDropDestination, + root.panelBottomDropDestination + ] + Rectangle { anchors.fill: parent color: ui.theme.backgroundPrimaryColor @@ -339,8 +374,6 @@ DockPage { objectName: pageModel.timelinePanelName() title: qsTrc("appshell", "Timeline") - allowedAreas: Qt.TopDockWidgetArea | Qt.BottomDockWidgetArea - height: 200 minimumHeight: 100 maximumHeight: 300 @@ -350,6 +383,11 @@ DockPage { location: DockBase.Bottom + dropDestinations: [ + root.panelTopDropDestination, + root.panelBottomDropDestination + ] + Timeline {} }, @@ -359,8 +397,6 @@ DockPage { objectName: pageModel.drumsetPanelName() title: qsTrc("appshell", "Drumset Tools") - allowedAreas: Qt.TopDockWidgetArea | Qt.BottomDockWidgetArea - minimumHeight: 30 maximumHeight: 30 diff --git a/src/appshell/qml/WindowContent.qml b/src/appshell/qml/WindowContent.qml index 630e3b1e55..5184248cf1 100644 --- a/src/appshell/qml/WindowContent.qml +++ b/src/appshell/qml/WindowContent.qml @@ -80,11 +80,9 @@ DockWindow { } ] - mainToolBarDockingHolder: DockToolBarHolder { + mainToolBarDockingHolder: DockingHolder { objectName: root.objectName + "_mainToolBarDockingHolderTop" location: DockBase.Top - - Rectangle { color: ui.theme.backgroundPrimaryColor } } pages: [ diff --git a/src/appshell/qml/dockwindow/DockFrame.qml b/src/appshell/qml/dockwindow/DockFrame.qml index 073e8e38ce..223b73ba8b 100644 --- a/src/appshell/qml/dockwindow/DockFrame.qml +++ b/src/appshell/qml/dockwindow/DockFrame.qml @@ -207,4 +207,22 @@ Rectangle { return 0 } } + + Rectangle { + anchors.fill: parent + + visible: frameModel.selectionVisible + + color: "transparent" + + border.width: 1 + border.color: ui.theme.accentColor + + Rectangle { + anchors.fill: parent + + color: ui.theme.accentColor + opacity: 0.3 + } + } } diff --git a/src/appshell/qml/dockwindow/DockPage.qml b/src/appshell/qml/dockwindow/DockPage.qml index 89f4f167be..19e7ab2265 100644 --- a/src/appshell/qml/dockwindow/DockPage.qml +++ b/src/appshell/qml/dockwindow/DockPage.qml @@ -28,6 +28,16 @@ DockPageView { property alias central: central.sourceComponent + property var toolBarLeftDropDestination: { "dock": toolBarLeftDockingHolder, "dropLocation": DropLocation.Top } + property var toolBarRightDropDestination: { "dock": toolBarRightDockingHolder, "dropLocation": DropLocation.Top } + property var toolBarTopDropDestination: { "dock": toolBarTopDockingHolder, "dropLocation": DropLocation.Left } + property var toolBarBottomDropDestination: { "dock": toolBarBottomDockingHolder, "dropLocation": DropLocation.Left } + + property var panelLeftDropDestination: { "dock": panelLeftDockingHolder, "dropLocation": DropLocation.Top } + property var panelRightDropDestination: { "dock": panelRightDockingHolder, "dropLocation": DropLocation.Top } + property var panelTopDropDestination: { "dock": panelTopDockingHolder, "dropLocation": DropLocation.Left } + property var panelBottomDropDestination: { "dock": panelBottomDockingHolder, "dropLocation": DropLocation.Left } + centralDock: DockCentralView { objectName: root.objectName + "_central" @@ -39,56 +49,56 @@ DockPageView { } toolBarsDockingHolders: [ - DockToolBarHolder { + DockingHolder { + id: toolBarLeftDockingHolder + objectName: root.objectName + "_toolBarsDockingHolderLeft" location: DockBase.Left - - Rectangle { color: ui.theme.backgroundPrimaryColor } }, - DockToolBarHolder { + DockingHolder { + id: toolBarRightDockingHolder + objectName: root.objectName + "_toolBarsDockingHolderRight" location: DockBase.Right - - Rectangle { color: ui.theme.backgroundPrimaryColor } }, - DockToolBarHolder { + DockingHolder { + id: toolBarTopDockingHolder + objectName: root.objectName + "_toolBarsDockingHolderTop" location: DockBase.Top - - Rectangle { color: ui.theme.backgroundPrimaryColor } }, - DockToolBarHolder { + DockingHolder { + id: toolBarBottomDockingHolder + objectName: root.objectName + "_toolBarsDockingHolderBottom" location: DockBase.Bottom - - Rectangle { color: ui.theme.backgroundPrimaryColor } } ] panelsDockingHolders: [ - DockPanelHolder { + DockingHolder { + id: panelLeftDockingHolder + objectName: root.objectName + "_panelsDockingHolderLeft" location: DockBase.Left - - Rectangle { color: ui.theme.backgroundPrimaryColor } }, - DockPanelHolder { + DockingHolder { + id: panelRightDockingHolder + objectName: root.objectName + "_panelsDockingHolderRight" location: DockBase.Right - - Rectangle { color: ui.theme.backgroundPrimaryColor } }, - DockPanelHolder { + DockingHolder { + id: panelTopDockingHolder + objectName: root.objectName + "_panelsDockingHolderTop" location: DockBase.Top - - Rectangle { color: ui.theme.backgroundPrimaryColor } }, - DockPanelHolder { + DockingHolder { + id: panelBottomDockingHolder + objectName: root.objectName + "_panelsDockingHolderBottom" location: DockBase.Bottom - - Rectangle { color: ui.theme.backgroundPrimaryColor } } ] } diff --git a/src/appshell/view/dockwindow/dockpanelholder.cpp b/src/appshell/qml/dockwindow/DockingHolder.qml similarity index 73% rename from src/appshell/view/dockwindow/dockpanelholder.cpp rename to src/appshell/qml/dockwindow/DockingHolder.qml index 19f5d8b3eb..79e331eabe 100644 --- a/src/appshell/view/dockwindow/dockpanelholder.cpp +++ b/src/appshell/qml/dockwindow/DockingHolder.qml @@ -20,18 +20,13 @@ * along with this program. If not, see . */ -#include "dockpanelholder.h" +import QtQuick 2.15 -using namespace mu::dock; +import MuseScore.Ui 1.0 +import MuseScore.Dock 1.0 -DockPanelHolder::DockPanelHolder(QQuickItem* parent) - : DockPanelView(parent) -{ - setVisible(false); - //setMovable(false); -} - -DockType DockPanelHolder::type() const -{ - return DockType::PanelDockingHolder; +DockingHolderView { + Rectangle { + color: ui.theme.backgroundPrimaryColor + } } diff --git a/src/appshell/view/dockwindow/dockcentralview.cpp b/src/appshell/view/dockwindow/dockcentralview.cpp index b106c3d5ef..2e7383adb0 100644 --- a/src/appshell/view/dockwindow/dockcentralview.cpp +++ b/src/appshell/view/dockwindow/dockcentralview.cpp @@ -26,7 +26,7 @@ using namespace mu::dock; DockCentralView::DockCentralView(QQuickItem* parent) : DockBase(parent) { - setAllowedAreas(Qt::NoDockWidgetArea); + setPersistent(true); } DockType DockCentralView::type() const diff --git a/src/appshell/view/dockwindow/docktoolbarholder.cpp b/src/appshell/view/dockwindow/dockingholderview.cpp similarity index 63% rename from src/appshell/view/dockwindow/docktoolbarholder.cpp rename to src/appshell/view/dockwindow/dockingholderview.cpp index a6851302e0..96e6cf728f 100644 --- a/src/appshell/view/dockwindow/docktoolbarholder.cpp +++ b/src/appshell/view/dockwindow/dockingholderview.cpp @@ -20,42 +20,40 @@ * along with this program. If not, see . */ -#include "docktoolbarholder.h" +#include "dockingholderview.h" using namespace mu::dock; -constexpr int DOCK_TOOLBAR_HOLDER_SIZE = 36; +constexpr int MIN_LENGTH = 36; -DockToolBarHolder::DockToolBarHolder(QQuickItem* parent) - : DockToolBarView(parent) +DockingHolderView::DockingHolderView(QQuickItem* parent) + : DockBase(parent) { setVisible(false); } -void DockToolBarHolder::componentComplete() +void DockingHolderView::componentComplete() { - DockToolBarView::componentComplete(); - switch (location()) { case DockLocation::Left: case DockLocation::Right: - setWidth(DOCK_TOOLBAR_HOLDER_SIZE); - setMinimumWidth(DOCK_TOOLBAR_HOLDER_SIZE); - setMaximumWidth(DOCK_TOOLBAR_HOLDER_SIZE * 2); + setMinimumWidth(MIN_LENGTH); + setWidth(MIN_LENGTH); break; case DockLocation::Top: case DockLocation::Bottom: - setHeight(DOCK_TOOLBAR_HOLDER_SIZE); - setMinimumHeight(DOCK_TOOLBAR_HOLDER_SIZE); - setMaximumHeight(DOCK_TOOLBAR_HOLDER_SIZE); + setMinimumHeight(MIN_LENGTH); + setHeight(MIN_LENGTH); break; case DockLocation::Center: case DockLocation::Undefined: break; } + + DockBase::componentComplete(); } -DockType DockToolBarHolder::type() const +DockType DockingHolderView::type() const { - return DockType::ToolBarDockingHolder; + return DockType::DockingHolder; } diff --git a/src/appshell/view/dockwindow/docktoolbarholder.h b/src/appshell/view/dockwindow/dockingholderview.h similarity index 78% rename from src/appshell/view/dockwindow/docktoolbarholder.h rename to src/appshell/view/dockwindow/dockingholderview.h index 85e23bc7fb..59d93262cf 100644 --- a/src/appshell/view/dockwindow/docktoolbarholder.h +++ b/src/appshell/view/dockwindow/dockingholderview.h @@ -20,18 +20,18 @@ * along with this program. If not, see . */ -#ifndef MU_DOCK_DOCKTOOLBARHOLDER_H -#define MU_DOCK_DOCKTOOLBARHOLDER_H +#ifndef MU_DOCK_DOCKINGHOLDERVIEW_H +#define MU_DOCK_DOCKINGHOLDERVIEW_H -#include "docktoolbarview.h" +#include "internal/dockbase.h" namespace mu::dock { -class DockToolBarHolder : public DockToolBarView +class DockingHolderView : public DockBase { Q_OBJECT public: - explicit DockToolBarHolder(QQuickItem* parent = nullptr); + explicit DockingHolderView(QQuickItem* parent = nullptr); private: void componentComplete() override; @@ -40,4 +40,4 @@ private: }; } -#endif // MU_DOCK_DOCKTOOLBARHOLDER_H +#endif // MU_DOCK_DOCKINGHOLDERVIEW_H diff --git a/src/appshell/view/dockwindow/dockpageview.cpp b/src/appshell/view/dockwindow/dockpageview.cpp index 07f65fcbfa..f69d23ab34 100644 --- a/src/appshell/view/dockwindow/dockpageview.cpp +++ b/src/appshell/view/dockwindow/dockpageview.cpp @@ -23,10 +23,9 @@ #include "dockpageview.h" #include "docktoolbarview.h" -#include "docktoolbarholder.h" +#include "dockingholderview.h" #include "dockcentralview.h" #include "dockpanelview.h" -#include "dockpanelholder.h" #include "dockstatusbarview.h" #include "log.h" @@ -72,12 +71,12 @@ QQmlListProperty DockPageView::panelsProperty() return m_panels.property(); } -QQmlListProperty DockPageView::toolBarsDockingHoldersProperty() +QQmlListProperty DockPageView::toolBarsDockingHoldersProperty() { return m_toolBarsDockingHolders.property(); } -QQmlListProperty DockPageView::panelsDockingHoldersProperty() +QQmlListProperty DockPageView::panelsDockingHoldersProperty() { return m_panelsDockingHolders.property(); } @@ -89,33 +88,10 @@ QList DockPageView::mainToolBars() const QList DockPageView::toolBars() const { - //! NOTE: Order is important for correct drawing - auto list = m_toolBars.list(); - - DockToolBarHolder* leftHolder = toolBarHolderByLocation(DockBase::DockLocation::Left); - if (leftHolder) { - list.prepend(leftHolder); - } - - DockToolBarHolder* rightHolder = toolBarHolderByLocation(DockBase::DockLocation::Right); - if (rightHolder) { - list.append(rightHolder); - } - - DockToolBarHolder* bottomHolder = toolBarHolderByLocation(DockBase::DockLocation::Bottom); - if (bottomHolder) { - list.prepend(bottomHolder); - } - - DockToolBarHolder* topHolder = toolBarHolderByLocation(DockBase::DockLocation::Top); - if (topHolder) { - list.append(topHolder); - } - - return list; + return m_toolBars.list(); } -QList DockPageView::toolBarsHolders() const +QList DockPageView::toolBarsHolders() const { return m_toolBarsDockingHolders.list(); } @@ -132,33 +108,10 @@ DockStatusBarView* DockPageView::statusBar() const QList DockPageView::panels() const { - //! NOTE: Order is important for correct drawing - auto list = m_panels.list(); - - DockPanelHolder* leftHolder = panelHolderByLocation(DockBase::DockLocation::Left); - if (leftHolder) { - list.prepend(leftHolder); - } - - DockPanelHolder* rightHolder = panelHolderByLocation(DockBase::DockLocation::Right); - if (rightHolder) { - list.append(rightHolder); - } - - DockPanelHolder* bottomHolder = panelHolderByLocation(DockBase::DockLocation::Bottom); - if (bottomHolder) { - list.prepend(bottomHolder); - } - - DockPanelHolder* topHolder = panelHolderByLocation(DockBase::DockLocation::Top); - if (topHolder) { - list.append(topHolder); - } - - return list; + return m_panels.list(); } -QList DockPageView::panelsHolders() const +QList DockPageView::panelsHolders() const { return m_panelsDockingHolders.list(); } @@ -174,9 +127,9 @@ DockBase* DockPageView::dockByName(const QString& dockName) const return nullptr; } -DockToolBarHolder* DockPageView::toolBarHolderByLocation(DockBase::DockLocation location) const +DockingHolderView* DockPageView::toolBarHolderByLocation(DockBase::DockLocation location) const { - for (DockToolBarHolder* holder : m_toolBarsDockingHolders.list()) { + for (DockingHolderView* holder : m_toolBarsDockingHolders.list()) { if (holder->location() == location) { return holder; } @@ -185,9 +138,9 @@ DockToolBarHolder* DockPageView::toolBarHolderByLocation(DockBase::DockLocation return nullptr; } -DockPanelHolder* DockPageView::panelHolderByLocation(DockBase::DockLocation location) const +DockingHolderView* DockPageView::panelHolderByLocation(DockBase::DockLocation location) const { - for (DockPanelHolder* holder : m_panelsDockingHolders.list()) { + for (DockingHolderView* holder : m_panelsDockingHolders.list()) { if (holder->location() == location) { return holder; } diff --git a/src/appshell/view/dockwindow/dockpageview.h b/src/appshell/view/dockwindow/dockpageview.h index cd0939c570..e6562587b9 100644 --- a/src/appshell/view/dockwindow/dockpageview.h +++ b/src/appshell/view/dockwindow/dockpageview.h @@ -35,8 +35,7 @@ class DockToolBarView; class DockPanelView; class DockCentralView; class DockStatusBarView; -class DockToolBarHolder; -class DockPanelHolder; +class DockingHolderView; class DockPageView : public QQuickItem { Q_OBJECT @@ -44,9 +43,9 @@ class DockPageView : public QQuickItem Q_PROPERTY(QString uri READ uri WRITE setUri NOTIFY uriChanged) Q_PROPERTY(QQmlListProperty mainToolBars READ mainToolBarsProperty) Q_PROPERTY(QQmlListProperty toolBars READ toolBarsProperty) - Q_PROPERTY(QQmlListProperty toolBarsDockingHolders READ toolBarsDockingHoldersProperty) + Q_PROPERTY(QQmlListProperty toolBarsDockingHolders READ toolBarsDockingHoldersProperty) Q_PROPERTY(QQmlListProperty panels READ panelsProperty) - Q_PROPERTY(QQmlListProperty panelsDockingHolders READ panelsDockingHoldersProperty) + Q_PROPERTY(QQmlListProperty panelsDockingHolders READ panelsDockingHoldersProperty) Q_PROPERTY(mu::dock::DockCentralView * centralDock READ centralDock WRITE setCentralDock NOTIFY centralDockChanged) Q_PROPERTY(mu::dock::DockStatusBarView * statusBar READ statusBar WRITE setStatusBar NOTIFY statusBarChanged) @@ -59,22 +58,22 @@ public: QQmlListProperty mainToolBarsProperty(); QQmlListProperty toolBarsProperty(); - QQmlListProperty toolBarsDockingHoldersProperty(); + QQmlListProperty toolBarsDockingHoldersProperty(); QQmlListProperty panelsProperty(); - QQmlListProperty panelsDockingHoldersProperty(); + QQmlListProperty panelsDockingHoldersProperty(); QList mainToolBars() const; QList toolBars() const; - QList toolBarsHolders() const; + QList toolBarsHolders() const; DockCentralView* centralDock() const; DockStatusBarView* statusBar() const; QList panels() const; - QList panelsHolders() const; + QList panelsHolders() const; QList allDocks() const; DockBase* dockByName(const QString& dockName) const; - DockToolBarHolder* toolBarHolderByLocation(DockBase::DockLocation location) const; - DockPanelHolder* panelHolderByLocation(DockBase::DockLocation location) const; + DockingHolderView* toolBarHolderByLocation(DockBase::DockLocation location) const; + DockingHolderView* panelHolderByLocation(DockBase::DockLocation location) const; bool isDockOpen(const QString& dockName) const; void toggleDock(const QString& dockName); @@ -102,9 +101,9 @@ private: QString m_uri; uicomponents::QmlListProperty m_mainToolBars; uicomponents::QmlListProperty m_toolBars; - uicomponents::QmlListProperty m_toolBarsDockingHolders; + uicomponents::QmlListProperty m_toolBarsDockingHolders; uicomponents::QmlListProperty m_panels; - uicomponents::QmlListProperty m_panelsDockingHolders; + uicomponents::QmlListProperty m_panelsDockingHolders; DockCentralView* m_central = nullptr; DockStatusBarView* m_statusBar = nullptr; }; diff --git a/src/appshell/view/dockwindow/dockpanelview.cpp b/src/appshell/view/dockwindow/dockpanelview.cpp index 18487fd53a..4b0d9f697f 100644 --- a/src/appshell/view/dockwindow/dockpanelview.cpp +++ b/src/appshell/view/dockwindow/dockpanelview.cpp @@ -147,7 +147,7 @@ private: DockPanelView::DockPanelView(QQuickItem* parent) : DockBase(parent), m_menuModel(new DockPanelMenuModel(this)) { - setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + setLocation(DockLocation::Left); } DockPanelView::~DockPanelView() diff --git a/src/appshell/view/dockwindow/docksetup.cpp b/src/appshell/view/dockwindow/docksetup.cpp index dbb13ca75e..c3dcea09d3 100644 --- a/src/appshell/view/dockwindow/docksetup.cpp +++ b/src/appshell/view/dockwindow/docksetup.cpp @@ -23,6 +23,7 @@ #include "docksetup.h" #include "internal/dropindicators.h" +#include "internal/dragcontroller.h" #include "internal/dockseparator.h" #include "internal/dockframemodel.h" #include "internal/dockwindowactionscontroller.h" @@ -30,9 +31,9 @@ #include "dockwindow.h" #include "dockpanelview.h" -#include "dockpanelholder.h" +#include "docktoolbarview.h" #include "dockstatusbarview.h" -#include "docktoolbarholder.h" +#include "dockingholderview.h" #include "dockcentralview.h" #include "dockpageview.h" @@ -51,7 +52,7 @@ class DockWidgetFactory : public KDDockWidgets::DefaultWidgetFactory public: KDDockWidgets::DropIndicatorOverlayInterface* createDropIndicatorOverlay(KDDockWidgets::DropArea* dropArea) const override { - return new DropIndicators(dropArea); + return new DragController(dropArea); } Layouting::Separator* createSeparator(Layouting::Widget* parent = nullptr) const override @@ -85,10 +86,9 @@ void DockSetup::registerQmlTypes() { qmlRegisterType("MuseScore.Dock", 1, 0, "DockWindow"); qmlRegisterType("MuseScore.Dock", 1, 0, "DockPanelView"); - qmlRegisterType("MuseScore.Dock", 1, 0, "DockPanelHolder"); qmlRegisterType("MuseScore.Dock", 1, 0, "DockStatusBar"); qmlRegisterType("MuseScore.Dock", 1, 0, "DockToolBarView"); - qmlRegisterType("MuseScore.Dock", 1, 0, "DockToolBarHolder"); + qmlRegisterType("MuseScore.Dock", 1, 0, "DockingHolderView"); qmlRegisterType("MuseScore.Dock", 1, 0, "DockCentralView"); qmlRegisterType("MuseScore.Dock", 1, 0, "DockPageView"); qmlRegisterType("MuseScore.Dock", 1, 0, "DockFrameModel"); @@ -97,6 +97,7 @@ void DockSetup::registerQmlTypes() qRegisterMetaType(); qmlRegisterUncreatableType("MuseScore.Dock", 1, 0, "DockToolBarAlignment", "Not creatable from QML"); + qmlRegisterUncreatableType("MuseScore.Dock", 1, 0, "DropLocation", "Not creatable from QML"); } void DockSetup::registerExports() diff --git a/src/appshell/view/dockwindow/dockstatusbarview.cpp b/src/appshell/view/dockwindow/dockstatusbarview.cpp index e2a71c6255..6363b90ecb 100644 --- a/src/appshell/view/dockwindow/dockstatusbarview.cpp +++ b/src/appshell/view/dockwindow/dockstatusbarview.cpp @@ -26,8 +26,6 @@ using namespace mu::dock; DockStatusBarView::DockStatusBarView(QQuickItem* parent) : DockBase(parent) { - setAllowedAreas(Qt::BottomDockWidgetArea); - constexpr int STATUS_BAR_HEIGHT = 32; setMinimumHeight(STATUS_BAR_HEIGHT); diff --git a/src/appshell/view/dockwindow/docktoolbarview.cpp b/src/appshell/view/dockwindow/docktoolbarview.cpp index 87586d233b..b685c9d629 100644 --- a/src/appshell/view/dockwindow/docktoolbarview.cpp +++ b/src/appshell/view/dockwindow/docktoolbarview.cpp @@ -109,7 +109,6 @@ DockToolBarView::DockToolBarView(QQuickItem* parent) //! NOTE: parent (MouseArea) will be set later m_draggableArea(new DraggableArea()) { - setAllowedAreas(Qt::TopDockWidgetArea); setLocation(DockLocation::Top); } @@ -125,9 +124,7 @@ int DockToolBarView::alignment() const void DockToolBarView::setOrientation(Qt::Orientation orientation) { - bool isChangingAllowed = isOrientationChangingAllowed(); - - if (orientation == m_orientation || !isChangingAllowed) { + if (orientation == m_orientation) { return; } @@ -166,9 +163,3 @@ DockType DockToolBarView::type() const { return DockType::ToolBar; } - -bool DockToolBarView::isOrientationChangingAllowed() const -{ - return allowedAreas().testFlag(Qt::LeftDockWidgetArea) - || allowedAreas().testFlag(Qt::RightDockWidgetArea); -} diff --git a/src/appshell/view/dockwindow/docktypes.h b/src/appshell/view/dockwindow/docktypes.h index 8227edc665..49fa349d44 100644 --- a/src/appshell/view/dockwindow/docktypes.h +++ b/src/appshell/view/dockwindow/docktypes.h @@ -33,18 +33,35 @@ inline const char* DOCK_PANEL_PROPERY("dockPanel"); enum class DockType { Undefined = -1, Panel, - PanelDockingHolder, ToolBar, - ToolBarDockingHolder, + DockingHolder, StatusBar, Central }; +class DropLocation +{ + Q_GADGET + +public: + enum Location { + None, + Left, + Right, + Center, + Top, + Bottom + }; + + Q_ENUM(Location) +}; + struct DockProperties { DockType type = DockType::Undefined; - Qt::DockWidgetAreas allowedAreas = Qt::NoDockWidgetArea; + bool persistent = false; bool separatorsVisible = false; + bool selected = false; bool isValid() const { @@ -54,11 +71,16 @@ struct DockProperties inline void writePropertiesToObject(const DockProperties& properties, QObject& obj) { - QObject* propertiesObj = new QObject(&obj); - propertiesObj->setObjectName("properties"); - propertiesObj->setProperty("dockType", QVariant::fromValue(static_cast(properties.type))); - propertiesObj->setProperty("allowedAreas", QVariant::fromValue(static_cast(properties.allowedAreas))); + QObject* propertiesObj = obj.findChild("properties"); + if (!propertiesObj) { + propertiesObj = new QObject(&obj); + propertiesObj->setObjectName("properties"); + } + + propertiesObj->setProperty("dockType", static_cast(properties.type)); + propertiesObj->setProperty("persistent", properties.persistent); propertiesObj->setProperty("separatorsVisible", properties.separatorsVisible); + propertiesObj->setProperty("selected", properties.selected); } inline DockProperties readPropertiesFromObject(const QObject* obj) @@ -74,8 +96,9 @@ inline DockProperties readPropertiesFromObject(const QObject* obj) DockProperties result; result.type = static_cast(properties->property("dockType").toInt()); - result.allowedAreas = static_cast(properties->property("allowedAreas").toInt()); + result.persistent = properties->property("persistent").toBool(); result.separatorsVisible = properties->property("separatorsVisible").toBool(); + result.selected = properties->property("selected").toBool(); return result; } diff --git a/src/appshell/view/dockwindow/dockwindow.cmake b/src/appshell/view/dockwindow/dockwindow.cmake index 6718c9b1e1..21f53c3d4c 100644 --- a/src/appshell/view/dockwindow/dockwindow.cmake +++ b/src/appshell/view/dockwindow/dockwindow.cmake @@ -34,20 +34,20 @@ set (DOCKWINDOW_SRC ${CMAKE_CURRENT_LIST_DIR}/dockpageview.h ${CMAKE_CURRENT_LIST_DIR}/dockpanelview.cpp ${CMAKE_CURRENT_LIST_DIR}/dockpanelview.h - ${CMAKE_CURRENT_LIST_DIR}/dockpanelholder.cpp - ${CMAKE_CURRENT_LIST_DIR}/dockpanelholder.h ${CMAKE_CURRENT_LIST_DIR}/dockstatusbarview.cpp ${CMAKE_CURRENT_LIST_DIR}/dockstatusbarview.h ${CMAKE_CURRENT_LIST_DIR}/docktoolbarview.cpp ${CMAKE_CURRENT_LIST_DIR}/docktoolbarview.h - ${CMAKE_CURRENT_LIST_DIR}/docktoolbarholder.cpp - ${CMAKE_CURRENT_LIST_DIR}/docktoolbarholder.h + ${CMAKE_CURRENT_LIST_DIR}/dockingholderview.cpp + ${CMAKE_CURRENT_LIST_DIR}/dockingholderview.h ${CMAKE_CURRENT_LIST_DIR}/dockcentralview.cpp ${CMAKE_CURRENT_LIST_DIR}/dockcentralview.h ${CMAKE_CURRENT_LIST_DIR}/internal/dockbase.cpp ${CMAKE_CURRENT_LIST_DIR}/internal/dockbase.h ${CMAKE_CURRENT_LIST_DIR}/internal/dropindicators.cpp ${CMAKE_CURRENT_LIST_DIR}/internal/dropindicators.h + ${CMAKE_CURRENT_LIST_DIR}/internal/dragcontroller.cpp + ${CMAKE_CURRENT_LIST_DIR}/internal/dragcontroller.h ${CMAKE_CURRENT_LIST_DIR}/internal/dropindicatorswindow.cpp ${CMAKE_CURRENT_LIST_DIR}/internal/dropindicatorswindow.h ${CMAKE_CURRENT_LIST_DIR}/internal/dockseparator.cpp diff --git a/src/appshell/view/dockwindow/dockwindow.cpp b/src/appshell/view/dockwindow/dockwindow.cpp index 5e11b7e3c5..2334a219db 100644 --- a/src/appshell/view/dockwindow/dockwindow.cpp +++ b/src/appshell/view/dockwindow/dockwindow.cpp @@ -30,10 +30,9 @@ #include "dockcentralview.h" #include "dockpageview.h" #include "dockpanelview.h" -#include "dockpanelholder.h" #include "dockstatusbarview.h" #include "docktoolbarview.h" -#include "docktoolbarholder.h" +#include "dockingholderview.h" #include "dockwindow.h" #include "log.h" @@ -41,7 +40,7 @@ using namespace mu::dock; using namespace mu::async; -static constexpr double MAX_DISTANCE_TO_HOLDER = 25; +static constexpr double MAX_DISTANCE_TO_HOLDER = 50; DockWindow::DockWindow(QQuickItem* parent) : QQuickItem(parent), @@ -170,34 +169,6 @@ void DockWindow::loadPage(const QString& uri) m_docksOpenStatusChanged.send(allDockNames); } -void DockWindow::setToolBarOrientation(const QString& toolBarName, framework::Orientation orientation) -{ - const DockPageView* page = currentPage(); - DockToolBarView* toolBar = page ? dynamic_cast(page->dockByName(toolBarName)) : nullptr; - - if (toolBar) { - toolBar->setOrientation(static_cast(orientation)); - } -} - -void DockWindow::showDockingHolder(const QPoint& globalPos, DockingHolderType type) -{ - switch (type) { - case ToolBar: - showToolBarDockingHolder(globalPos); - break; - case Panel: - showPanelDockingHolder(globalPos); - break; - } -} - -void DockWindow::hideAllDockingHolders() -{ - hideCurrentToolBarDockingHolder(); - hideCurrentPanelDockingHolder(); -} - bool DockWindow::isDockOpen(const QString& dockName) const { const DockPageView* currPage = currentPage(); @@ -241,12 +212,57 @@ void DockWindow::toggleDockFloating(const QString& dockName) } } -DockToolBarHolder* DockWindow::mainToolBarDockingHolder() const +DropLocation::Location DockWindow::hover(const QString& draggedDockName, const QPoint& globalPos) +{ + DockBase* draggedDock = dockByName(draggedDockName); + if (!draggedDock) { + return DropLocation::None; + } + + QPoint hoveredLocalPos = m_mainWindow->mapFromGlobal(globalPos); + + if (isMouseOverDock(hoveredLocalPos, m_currentDropDestination.dock)) { + return m_currentDropDestination.dropLocation; + } + + DropDestination dropDestination = resolveDropDestination(draggedDock, hoveredLocalPos); + + if (auto toolBar = dynamic_cast(draggedDock)) { + updateToolBarOrientation(toolBar, dropDestination); + } + + setCurrentDropDestination(draggedDock, dropDestination); + + return m_currentDropDestination.dropLocation; +} + +void DockWindow::endHover() +{ + if (!m_currentDropDestination.isValid()) { + return; + } + + m_currentDropDestination.dock->setSelected(false); + + if (m_currentDropDestination.dock->type() == DockType::DockingHolder) { + m_currentDropDestination.dock->close(); + } + + m_currentDropDestination.clear(); +} + +DockBase* DockWindow::dockByName(const QString& dockName) const +{ + const DockPageView* page = currentPage(); + return page ? page->dockByName(dockName) : nullptr; +} + +DockingHolderView* DockWindow::mainToolBarDockingHolder() const { return m_mainToolBarDockingHolder; } -void DockWindow::setMainToolBarDockingHolder(DockToolBarHolder* mainToolBarDockingHolder) +void DockWindow::setMainToolBarDockingHolder(DockingHolderView* mainToolBarDockingHolder) { if (m_mainToolBarDockingHolder == mainToolBarDockingHolder) { return; @@ -300,13 +316,29 @@ void DockWindow::unitePanelsToTabs(const DockPageView* page) void DockWindow::loadPageToolbars(const DockPageView* page) { - QList leftSideToolbars; - QList rightSideToolbars; - QList topSideToolbars; - QList bottomSideToolbars; + QList leftSideToolbars; + if (auto leftHolder = page->toolBarHolderByLocation(DockBase::DockLocation::Left)) { + leftSideToolbars << leftHolder; + } + + QList rightSideToolbars; + if (auto rightHolder = page->toolBarHolderByLocation(DockBase::DockLocation::Right)) { + rightSideToolbars << rightHolder; + } + + QList topSideToolbars; + if (auto topHolder = page->toolBarHolderByLocation(DockBase::DockLocation::Top)) { + topSideToolbars << topHolder; + } + + QList bottomSideToolbars; + if (auto bottomHolder = page->toolBarHolderByLocation(DockBase::DockLocation::Bottom)) { + bottomSideToolbars << bottomHolder; + } QList pageToolBars = page->toolBars(); - for (DockToolBarView* toolBar : pageToolBars) { + + for (DockBase* toolBar : pageToolBars) { switch (toolBar->location()) { case DockBase::DockLocation::Left: leftSideToolbars << toolBar; @@ -346,10 +378,25 @@ void DockWindow::loadPageToolbars(const DockPageView* page) void DockWindow::loadPagePanels(const DockPageView* page) { - QList leftSidePanels; - QList rightSidePanels; - QList topSidePanels; - QList bottomSidePanels; + QList leftSidePanels; + if (auto leftHolder = page->panelHolderByLocation(DockBase::DockLocation::Left)) { + leftSidePanels << leftHolder; + } + + QList rightSidePanels; + if (auto rightHolder = page->panelHolderByLocation(DockBase::DockLocation::Right)) { + rightSidePanels << rightHolder; + } + + QList topSidePanels; + if (auto topHolder = page->panelHolderByLocation(DockBase::DockLocation::Top)) { + topSidePanels << topHolder; + } + + QList bottomSidePanels; + if (auto bottomHolder = page->panelHolderByLocation(DockBase::DockLocation::Bottom)) { + bottomSidePanels << bottomHolder; + } QList pagePanels = page->panels(); for (DockPanelView* panel : pagePanels) { @@ -366,12 +413,8 @@ void DockWindow::loadPagePanels(const DockPageView* page) case DockBase::DockLocation::Bottom: bottomSidePanels << panel; break; - default: - if (panel->allowedAreas() & Qt::BottomDockWidgetArea) { - bottomSidePanels << panel; - } else { - leftSidePanels << panel; - } + case DockBase::DockLocation::Center: + case DockBase::DockLocation::Undefined: break; } } @@ -581,7 +624,138 @@ QList DockWindow::topLevelToolBars(const DockPageView* page) c return toolBars; } -DockToolBarHolder* DockWindow::resolveToolbarDockingHolder(const QPoint& localPos) const +bool DockWindow::isMouseOverDock(const QPoint& mouseLocalPos, const DockBase* dock) const +{ + if (!dock || !dock->isVisible() || !m_mainWindow) { + return false; + } + + const KDDockWidgets::DockWidgetBase* dockWidget = dock->dockWidget(); + if (!dockWidget) { + return false; + } + + QRect frameGeometry = dockWidget->frameGeometry(); + frameGeometry.setTopLeft(m_mainWindow->mapFromGlobal(dockWidget->mapToGlobal({ dockWidget->x(), dockWidget->y() }))); + + return frameGeometry.contains(mouseLocalPos); +} + +void DockWindow::updateToolBarOrientation(DockToolBarView* draggedToolBar, const DropDestination& dropDestination) +{ + IF_ASSERT_FAILED(draggedToolBar) { + return; + } + + framework::Orientation orientation = framework::Orientation::Horizontal; + + if (!dropDestination.isValid()) { + draggedToolBar->setOrientation(static_cast(orientation)); + return; + } + + switch (dropDestination.dock->location()) { + case DockBase::DockLocation::Left: + case DockBase::DockLocation::Right: + orientation = framework::Orientation::Vertical; + break; + case DockBase::DockLocation::Top: + case DockBase::DockLocation::Bottom: + orientation = framework::Orientation::Horizontal; + break; + case DockBase::DockLocation::Center: + case DockBase::DockLocation::Undefined: + break; + } + + draggedToolBar->setOrientation(static_cast(orientation)); +} + +void DockWindow::setCurrentDropDestination(const DockBase* draggedDock, const DropDestination& dropDestination) +{ + if (m_currentDropDestination == dropDestination) { + return; + } + + endHover(); + + m_currentDropDestination = dropDestination; + + if (!m_currentDropDestination.isValid()) { + return; + } + + if (m_currentDropDestination.dock->type() != DockType::DockingHolder) { + m_currentDropDestination.dock->setSelected(true); + return; + } + + switch (m_currentDropDestination.dock->location()) { + case DockBase::DockLocation::Left: + case DockBase::DockLocation::Right: + m_currentDropDestination.dock->setMinimumWidth(draggedDock->minimumWidth()); + break; + case DockBase::DockLocation::Top: + case DockBase::DockLocation::Bottom: + m_currentDropDestination.dock->setMinimumHeight(draggedDock->minimumHeight()); + break; + case DockBase::DockLocation::Center: + case DockBase::DockLocation::Undefined: + break; + } + + m_currentDropDestination.dock->open(); + m_currentDropDestination.dock->setSelected(true); + m_currentDropDestination.dock->init(); +} + +DropDestination DockWindow::resolveDropDestination(const DockBase* draggedDock, const QPoint& localPos) const +{ + const DockBase* holder = resolveDockingHolder(draggedDock->type(), localPos); + QList destinations = draggedDock->dropDestinations(); + + for (const DropDestination& destination : destinations) { + if (holder == destination.dock) { + return destination; + } + + if (isMouseOverDock(localPos, destination.dock)) { + return destination; + } + } + + if (holder) { + return DropDestination(); + } + + DropDestination destination; + + if (auto panel = dynamic_cast(draggedDock)) { + destination.dock = findTabifyPanel(panel, localPos); + destination.dropLocation = destination.dock ? DropLocation::Center : DropLocation::None; + } + + return destination; +} + +DockingHolderView* DockWindow::resolveDockingHolder(DockType draggedDockType, const QPoint& localPos) const +{ + switch (draggedDockType) { + case DockType::ToolBar: + return resolveToolbarDockingHolder(localPos); + case DockType::Panel: + return resolvePanelDockingHolder(localPos); + case DockType::Central: + case DockType::StatusBar: + case DockType::DockingHolder: + case DockType::Undefined: + break; + } + + return nullptr; +} + +DockingHolderView* DockWindow::resolveToolbarDockingHolder(const QPoint& localPos) const { const DockPageView* page = currentPage(); if (!page) { @@ -597,29 +771,32 @@ DockToolBarHolder* DockWindow::resolveToolbarDockingHolder(const QPoint& localPo centralFrameGeometry.moveTopLeft(m_mainWindow->mapFromGlobal(centralDock->mapToGlobal({ centralDock->x(), centralDock->y() }))); QRect mainFrameGeometry = m_mainWindow->rect(); - DockToolBarHolder* newHolder = nullptr; - - if (localPos.y() < MAX_DISTANCE_TO_HOLDER) { // main toolbar holder - newHolder = m_mainToolBarDockingHolder; + if (!mainFrameGeometry.contains(localPos)) { + return nullptr; } + // TODO: Need to take any panels docked at top into account - else if (localPos.y() > centralFrameGeometry.top() - && localPos.y() < centralFrameGeometry.top() + MAX_DISTANCE_TO_HOLDER) { // page top toolbar holder - newHolder = page->toolBarHolderByLocation(DockBase::DockLocation::Top); - } else if (localPos.y() < centralFrameGeometry.bottom()) { // page left toolbar holder - if (localPos.x() < MAX_DISTANCE_TO_HOLDER) { - newHolder = page->toolBarHolderByLocation(DockBase::DockLocation::Left); - } else if (localPos.x() > mainFrameGeometry.right() - MAX_DISTANCE_TO_HOLDER) { // page right toolbar holder - newHolder = page->toolBarHolderByLocation(DockBase::DockLocation::Right); + if (localPos.y() >= centralFrameGeometry.top() - MAX_DISTANCE_TO_HOLDER + && localPos.y() <= centralFrameGeometry.top() + MAX_DISTANCE_TO_HOLDER) { + return page->toolBarHolderByLocation(DockBase::DockLocation::Top); } - } else if (localPos.y() < mainFrameGeometry.bottom()) { // page bottom toolbar holder - newHolder = page->toolBarHolderByLocation(DockBase::DockLocation::Bottom); + + if (localPos.y() >= centralFrameGeometry.bottom() - MAX_DISTANCE_TO_HOLDER) { + return page->toolBarHolderByLocation(DockBase::DockLocation::Bottom); } - return newHolder; + if (localPos.x() <= MAX_DISTANCE_TO_HOLDER) { + return page->toolBarHolderByLocation(DockBase::DockLocation::Left); + } + + if (localPos.x() >= mainFrameGeometry.right() - MAX_DISTANCE_TO_HOLDER) { + return page->toolBarHolderByLocation(DockBase::DockLocation::Right); + } + + return nullptr; } -DockPanelHolder* DockWindow::resolvePanelDockingHolder(const QPoint& localPos) const +DockingHolderView* DockWindow::resolvePanelDockingHolder(const QPoint& localPos) const { const DockPageView* page = currentPage(); if (!page) { @@ -631,127 +808,74 @@ DockPanelHolder* DockWindow::resolvePanelDockingHolder(const QPoint& localPos) c return nullptr; } + if (!m_mainWindow->contains(localPos)) { + return nullptr; + } + QRect centralFrameGeometry = centralDock->frameGeometry(); centralFrameGeometry.moveTopLeft(m_mainWindow->mapFromGlobal(centralDock->mapToGlobal({ centralDock->x(), centralDock->y() }))); - DockPanelHolder* newHolder = nullptr; - if (localPos.y() > centralFrameGeometry.top() - && localPos.y() < centralFrameGeometry.top() + MAX_DISTANCE_TO_HOLDER) { // page top panel holder - newHolder = page->panelHolderByLocation(DockBase::DockLocation::Top); - } else if (localPos.y() < centralFrameGeometry.bottom()) { // page left panel holder - if (localPos.x() < MAX_DISTANCE_TO_HOLDER) { - newHolder = page->panelHolderByLocation(DockBase::DockLocation::Left); - } else if (localPos.x() > centralFrameGeometry.right() - MAX_DISTANCE_TO_HOLDER) { // page right panel holder - newHolder = page->panelHolderByLocation(DockBase::DockLocation::Right); + if (localPos.y() >= centralFrameGeometry.top() - MAX_DISTANCE_TO_HOLDER + && localPos.y() <= centralFrameGeometry.top() + MAX_DISTANCE_TO_HOLDER) { + return page->panelHolderByLocation(DockBase::DockLocation::Top); } - } else if (localPos.y() < centralFrameGeometry.bottom()) { // page bottom panel holder - newHolder = page->panelHolderByLocation(DockBase::DockLocation::Bottom); + + if (localPos.y() >= centralFrameGeometry.bottom() - MAX_DISTANCE_TO_HOLDER) { + return page->panelHolderByLocation(DockBase::DockLocation::Bottom); } - return newHolder; + if (localPos.x() <= MAX_DISTANCE_TO_HOLDER) { + return page->panelHolderByLocation(DockBase::DockLocation::Left); + } + + if (localPos.x() >= centralFrameGeometry.right() - MAX_DISTANCE_TO_HOLDER) { + return page->panelHolderByLocation(DockBase::DockLocation::Right); + } + + return nullptr; } -void DockWindow::showToolBarDockingHolder(const QPoint& globalPos) +DockPanelView* DockWindow::findTabifyPanel(const DockPanelView* panel, const QPoint& localPos) const { - QPoint localPos = m_mainWindow->mapFromGlobal(globalPos); - QRect mainFrameGeometry = m_mainWindow->rect(); + auto hoverOverPanel = [localPos, panel, this](const DockPanelView* p) { + if (p == panel || p->floating()) { + return false; + } - if (!mainFrameGeometry.contains(localPos)) { - return; + return isMouseOverDock(localPos, p); + }; + + DockPanelView* rootPanel = findRootPanel(panel); + if (hoverOverPanel(rootPanel)) { + return rootPanel; } - if (isMouseOverCurrentToolBarDockingHolder(localPos)) { - return; + DockPanelView* nextPanel = rootPanel ? rootPanel->tabifyPanel() : nullptr; + + while (nextPanel) { + if (hoverOverPanel(nextPanel)) { + return nextPanel; + } + + nextPanel = nextPanel->tabifyPanel(); } - DockToolBarHolder* holder = resolveToolbarDockingHolder(localPos); + return nullptr; +} - if (holder != m_currentToolBarDockingHolder) { - hideCurrentToolBarDockingHolder(); +DockPanelView* DockWindow::findRootPanel(const DockPanelView* panel) const +{ + for (DockPanelView* panel_ : currentPage()->panels()) { + DockPanelView* tabifyPanel = panel_->tabifyPanel(); - if (holder) { - holder->open(); + while (tabifyPanel) { + if (tabifyPanel == panel) { + return panel_; + } + + tabifyPanel = tabifyPanel->tabifyPanel(); } } - m_currentToolBarDockingHolder = holder; -} - -void DockWindow::hideCurrentToolBarDockingHolder() -{ - if (!m_currentToolBarDockingHolder) { - return; - } - - m_currentToolBarDockingHolder->close(); - m_currentToolBarDockingHolder = nullptr; -} - -void DockWindow::showPanelDockingHolder(const QPoint& globalPos) -{ - QPoint localPos = m_mainWindow->mapFromGlobal(globalPos); - QRect mainFrameGeometry = m_mainWindow->rect(); - - if (!mainFrameGeometry.contains(localPos)) { - return; - } - - if (isMouseOverCurrentPanelDockingHolder(localPos)) { - return; - } - - DockPanelHolder* holder = resolvePanelDockingHolder(localPos); - - if (holder != m_currentPanelDockingHolder) { - hideCurrentPanelDockingHolder(); - - if (holder) { - qDebug() << holder->location(); - holder->open(); - } - } - - m_currentPanelDockingHolder = holder; -} - -void DockWindow::hideCurrentPanelDockingHolder() -{ - if (!m_currentPanelDockingHolder) { - return; - } - - m_currentPanelDockingHolder->close(); - m_currentPanelDockingHolder = nullptr; -} - -bool DockWindow::isMouseOverCurrentToolBarDockingHolder(const QPoint& mouseLocalPos) const -{ - if (!m_currentToolBarDockingHolder || !m_mainWindow) { - return false; - } - - const KDDockWidgets::DockWidgetBase* holderDock = m_currentToolBarDockingHolder->dockWidget(); - if (!holderDock) { - return false; - } - - QRect holderFrameGeometry = holderDock->frameGeometry(); - holderFrameGeometry.setTopLeft(m_mainWindow->mapFromGlobal(holderDock->mapToGlobal({ holderDock->x(), holderDock->y() }))); - return holderFrameGeometry.contains(mouseLocalPos); -} - -bool DockWindow::isMouseOverCurrentPanelDockingHolder(const QPoint& mouseLocalPos) const -{ - if (!m_currentPanelDockingHolder || !m_mainWindow) { - return false; - } - - const KDDockWidgets::DockWidgetBase* holderDock = m_currentPanelDockingHolder->dockWidget(); - if (!holderDock) { - return false; - } - - QRect holderFrameGeometry = holderDock->frameGeometry(); - holderFrameGeometry.setTopLeft(m_mainWindow->mapFromGlobal(holderDock->mapToGlobal({ holderDock->x(), holderDock->y() }))); - return holderFrameGeometry.contains(mouseLocalPos); + return const_cast(panel); } diff --git a/src/appshell/view/dockwindow/dockwindow.h b/src/appshell/view/dockwindow/dockwindow.h index 08b4f8e510..3dadd66844 100644 --- a/src/appshell/view/dockwindow/dockwindow.h +++ b/src/appshell/view/dockwindow/dockwindow.h @@ -36,6 +36,7 @@ #include "internal/istartupscenario.h" #include "idockwindow.h" #include "idockwindowprovider.h" +#include "internal/dockbase.h" namespace KDDockWidgets { class MainWindowBase; @@ -44,10 +45,9 @@ class LayoutSaver; namespace mu::dock { class DockToolBarView; -class DockToolBarHolder; -class DockPanelHolder; +class DockingHolderView; class DockPageView; -class DockBase; +class DockPanelView; class DockWindow : public QQuickItem, public IDockWindow, public async::Asyncable { Q_OBJECT @@ -56,7 +56,7 @@ class DockWindow : public QQuickItem, public IDockWindow, public async::Asyncabl Q_PROPERTY(QQmlListProperty toolBars READ toolBarsProperty) Q_PROPERTY( - mu::dock::DockToolBarHolder + mu::dock::DockingHolderView * mainToolBarDockingHolder READ mainToolBarDockingHolder WRITE setMainToolBarDockingHolder NOTIFY mainToolBarDockingHolderChanged) Q_PROPERTY(QQmlListProperty pages READ pagesProperty) @@ -72,15 +72,11 @@ public: QQmlListProperty toolBarsProperty(); QQmlListProperty pagesProperty(); - DockToolBarHolder* mainToolBarDockingHolder() const; + DockingHolderView* mainToolBarDockingHolder() const; Q_INVOKABLE void loadPage(const QString& uri); //! IDockWindow - void setToolBarOrientation(const QString& toolBarName, framework::Orientation orientation) override; - void showDockingHolder(const QPoint& globalPos, DockingHolderType type) override; - void hideAllDockingHolders() override; - bool isDockOpen(const QString& dockName) const override; void toggleDock(const QString& dockName) override; void setDockOpen(const QString& dockName, bool open) override; @@ -90,13 +86,16 @@ public: bool isDockFloating(const QString& dockName) const override; void toggleDockFloating(const QString& dockName) override; + DropLocation::Location hover(const QString& draggedDockName, const QPoint& globalPos) override; + void endHover() override; + public slots: - void setMainToolBarDockingHolder(DockToolBarHolder* mainToolBarDockingHolder); + void setMainToolBarDockingHolder(DockingHolderView* mainToolBarDockingHolder); signals: void currentPageUriChanged(const QString& uri); - void mainToolBarDockingHolderChanged(DockToolBarHolder* mainToolBarDockingHolder); + void mainToolBarDockingHolderChanged(DockingHolderView* mainToolBarDockingHolder); private slots: void onQuit(); @@ -131,23 +130,26 @@ private: QList topLevelToolBars(const DockPageView* page) const; - DockToolBarHolder* resolveToolbarDockingHolder(const QPoint& localPos) const; - void showToolBarDockingHolder(const QPoint& globalPos); - void hideCurrentToolBarDockingHolder(); - bool isMouseOverCurrentToolBarDockingHolder(const QPoint& mouseLocalPos) const; + bool isMouseOverDock(const QPoint& mouseLocalPos, const DockBase* dock) const; + void updateToolBarOrientation(DockToolBarView* draggedToolBar, const DropDestination& dropDestination = DropDestination()); + void setCurrentDropDestination(const DockBase* draggedDock, const DropDestination& dropDestination); - DockPanelHolder* resolvePanelDockingHolder(const QPoint& localPos) const; - void showPanelDockingHolder(const QPoint& globalPos); - void hideCurrentPanelDockingHolder(); - bool isMouseOverCurrentPanelDockingHolder(const QPoint& mouseLocalPos) const; + DropDestination resolveDropDestination(const DockBase* draggedDock, const QPoint& localPos) const; + DockingHolderView* resolveDockingHolder(DockType draggedDockType, const QPoint& localPos) const; + DockingHolderView* resolveToolbarDockingHolder(const QPoint& localPos) const; + DockingHolderView* resolvePanelDockingHolder(const QPoint& localPos) const; + + DockPanelView* findTabifyPanel(const DockPanelView* panel, const QPoint& localPos) const; + DockPanelView* findRootPanel(const DockPanelView* panel) const; + + DockBase* dockByName(const QString& dockName) const; KDDockWidgets::MainWindowBase* m_mainWindow = nullptr; QString m_currentPageUri; uicomponents::QmlListProperty m_toolBars; - DockToolBarHolder* m_mainToolBarDockingHolder = nullptr; + DockingHolderView* m_mainToolBarDockingHolder = nullptr; uicomponents::QmlListProperty m_pages; - DockToolBarHolder* m_currentToolBarDockingHolder = nullptr; - DockPanelHolder* m_currentPanelDockingHolder = nullptr; + DropDestination m_currentDropDestination; async::Channel m_docksOpenStatusChanged; bool m_quiting = false; diff --git a/src/appshell/view/dockwindow/idockwindow.h b/src/appshell/view/dockwindow/idockwindow.h index eb67cb8049..ea81b5ab24 100644 --- a/src/appshell/view/dockwindow/idockwindow.h +++ b/src/appshell/view/dockwindow/idockwindow.h @@ -22,7 +22,7 @@ #ifndef MU_DOCK_IDOCKWINDOW_H #define MU_DOCK_IDOCKWINDOW_H -#include "globaltypes.h" +#include "docktypes.h" #include "async/channel.h" #include @@ -35,15 +35,6 @@ class IDockWindow public: virtual ~IDockWindow() = default; - enum DockingHolderType { - Panel, - ToolBar - }; - - virtual void setToolBarOrientation(const QString& toolBarName, framework::Orientation orientation) = 0; - virtual void showDockingHolder(const QPoint& globalPos, DockingHolderType type) = 0; - virtual void hideAllDockingHolders() = 0; - virtual bool isDockOpen(const QString& dockName) const = 0; virtual void setDockOpen(const QString& dockName, bool open) = 0; virtual void toggleDock(const QString& dockName) = 0; @@ -52,6 +43,9 @@ public: virtual bool isDockFloating(const QString& dockName) const = 0; virtual void toggleDockFloating(const QString& dockName) = 0; + + virtual DropLocation::Location hover(const QString& draggedDockName, const QPoint& globalPos) = 0; + virtual void endHover() = 0; }; } diff --git a/src/appshell/view/dockwindow/internal/dockbase.cpp b/src/appshell/view/dockwindow/internal/dockbase.cpp index 2564976c1c..103327c384 100644 --- a/src/appshell/view/dockwindow/internal/dockbase.cpp +++ b/src/appshell/view/dockwindow/internal/dockbase.cpp @@ -99,14 +99,41 @@ QSize DockBase::preferredSize() const return QSize(width(), height()); } -Qt::DockWidgetAreas DockBase::allowedAreas() const +DockBase::DockLocation DockBase::location() const { - return m_allowedAreas; + return m_location; } -bool DockBase::floating() const +QVariantList DockBase::dropDestinationsProperty() const { - return m_floating; + return m_dropDestinations; +} + +QList DockBase::dropDestinations() const +{ + QList result; + + for (const QVariant& obj : m_dropDestinations) { + QVariantMap map = obj.toMap(); + + DropDestination destination; + destination.dock = map["dock"].value(); + + if (map.contains("dropLocation")) { + destination.dropLocation = static_cast(map["dropLocation"].toInt()); + } else { + destination.dropLocation = DropLocation::Left; + } + + result << destination; + } + + return result; +} + +bool DockBase::persistent() const +{ + return m_persistent; } bool DockBase::resizable() const @@ -119,6 +146,11 @@ bool DockBase::separatorsVisible() const return m_separatorsVisible; } +bool DockBase::floating() const +{ + return m_floating; +} + KDDockWidgets::DockWidgetQuick* DockBase::dockWidget() const { return m_dockWidget; @@ -194,26 +226,6 @@ void DockBase::setContentHeight(int height) emit contentSizeChanged(); } -void DockBase::setAllowedAreas(Qt::DockWidgetAreas areas) -{ - if (areas == allowedAreas()) { - return; - } - - m_allowedAreas = areas; - emit allowedAreasChanged(); -} - -void DockBase::setFloating(bool floating) -{ - if (floating == m_floating) { - return; - } - - m_dockWidget->setFloating(floating); - doSetFloating(floating); -} - void DockBase::setLocation(DockLocation location) { if (location == m_location) { @@ -221,7 +233,27 @@ void DockBase::setLocation(DockLocation location) } m_location = location; - emit locationChanged(m_location); + emit locationChanged(); +} + +void DockBase::setDropDestinations(const QVariantList& destinations) +{ + if (m_dropDestinations == destinations) { + return; + } + + m_dropDestinations = destinations; + emit dropDestinationsChanged(); +} + +void DockBase::setPersistent(bool persistent) +{ + if (persistent == m_persistent) { + return; + } + + m_persistent = persistent; + emit persistentChanged(); } void DockBase::setResizable(bool resizable) @@ -244,6 +276,16 @@ void DockBase::setSeparatorsVisible(bool visible) emit separatorsVisibleChanged(); } +void DockBase::setFloating(bool floating) +{ + if (floating == m_floating) { + return; + } + + m_dockWidget->setFloating(floating); + doSetFloating(floating); +} + DockType DockBase::type() const { return DockType::Undefined; @@ -283,9 +325,14 @@ void DockBase::close() setVisible(false); } -DockBase::DockLocation DockBase::location() const +void DockBase::setSelected(bool selected) { - return m_location; + if (selected == m_selected) { + return; + } + + m_selected = selected; + writeProperties(); } void DockBase::componentComplete() @@ -310,13 +357,7 @@ void DockBase::componentComplete() m_dockWidget->setWidget(content); m_dockWidget->setTitle(m_title); - DockProperties properties; - properties.type = type(); - properties.allowedAreas = allowedAreas(); - properties.separatorsVisible = separatorsVisible(); - - writePropertiesToObject(properties, *m_dockWidget); - + writeProperties(); listenFloatingChanges(); connect(m_dockWidget, &KDDockWidgets::DockWidgetQuick::widthChanged, this, [this]() { @@ -393,6 +434,11 @@ void DockBase::listenFloatingChanges() applySizeConstraints(); }, Qt::UniqueConnection); }); + + connect(m_dockWidget, &KDDockWidgets::DockWidgetQuick::isFloatingChanged, this, [this]() { + doSetFloating(m_dockWidget->isFloating()); + applySizeConstraints(); + }); } void DockBase::doSetFloating(bool floating) @@ -400,3 +446,34 @@ void DockBase::doSetFloating(bool floating) m_floating = floating; emit floatingChanged(); } + +void DockBase::writeProperties() +{ + if (!m_dockWidget) { + return; + } + + DockProperties properties; + properties.type = type(); + properties.persistent = persistent(); + properties.separatorsVisible = separatorsVisible(); + properties.selected = m_selected; + + writePropertiesToObject(properties, *m_dockWidget); +} + +bool DropDestination::operator==(const DropDestination& dest) const +{ + return dock == dest.dock && dropLocation == dest.dropLocation; +} + +bool DropDestination::isValid() const +{ + return dock != nullptr; +} + +void DropDestination::clear() +{ + dock = nullptr; + dropLocation = DropLocation::None; +} diff --git a/src/appshell/view/dockwindow/internal/dockbase.h b/src/appshell/view/dockwindow/internal/dockbase.h index 89abc0c46c..ebdb8542dc 100644 --- a/src/appshell/view/dockwindow/internal/dockbase.h +++ b/src/appshell/view/dockwindow/internal/dockbase.h @@ -25,12 +25,14 @@ #include #include "../docktypes.h" +#include "uicomponents/view/qmllistproperty.h" namespace KDDockWidgets { class DockWidgetQuick; } namespace mu::dock { +struct DropDestination; class DockBase : public QQuickItem { Q_OBJECT @@ -41,19 +43,18 @@ class DockBase : public QQuickItem Q_PROPERTY(int minimumHeight READ minimumHeight WRITE setMinimumHeight NOTIFY minimumSizeChanged) Q_PROPERTY(int maximumWidth READ maximumWidth WRITE setMaximumWidth NOTIFY maximumSizeChanged) Q_PROPERTY(int maximumHeight READ maximumHeight WRITE setMaximumHeight NOTIFY maximumSizeChanged) - Q_PROPERTY(int contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentSizeChanged) Q_PROPERTY(int contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentSizeChanged) - Q_PROPERTY(Qt::DockWidgetAreas allowedAreas READ allowedAreas WRITE setAllowedAreas NOTIFY allowedAreasChanged) - - Q_PROPERTY(bool floating READ floating NOTIFY floatingChanged) - Q_PROPERTY(DockLocation location READ location WRITE setLocation NOTIFY locationChanged) + Q_PROPERTY(QVariantList dropDestinations READ dropDestinationsProperty WRITE setDropDestinations NOTIFY dropDestinationsChanged) + Q_PROPERTY(bool persistent READ persistent WRITE setPersistent NOTIFY persistentChanged) Q_PROPERTY(bool resizable READ resizable WRITE setResizable NOTIFY resizableChanged) Q_PROPERTY(bool separatorsVisible READ separatorsVisible WRITE setSeparatorsVisible NOTIFY separatorsVisibleChanged) + Q_PROPERTY(bool floating READ floating NOTIFY floatingChanged) + public: explicit DockBase(QQuickItem* parent = nullptr); @@ -73,13 +74,17 @@ public: int minimumHeight() const; int maximumWidth() const; int maximumHeight() const; - int contentWidth() const; int contentHeight() const; - QSize preferredSize() const; - Qt::DockWidgetAreas allowedAreas() const; + DockLocation location() const; + QVariantList dropDestinationsProperty() const; + QList dropDestinations() const; + + bool persistent() const; + bool resizable() const; + bool separatorsVisible() const; bool floating() const; @@ -89,10 +94,7 @@ public: void open(); void close(); - DockLocation location() const; - - bool resizable() const; - bool separatorsVisible() const; + void setSelected(bool selected); public slots: void setTitle(const QString& title); @@ -101,40 +103,41 @@ public slots: void setMinimumHeight(int height); void setMaximumWidth(int width); void setMaximumHeight(int height); - void setContentWidth(int width); void setContentHeight(int height); - void setAllowedAreas(Qt::DockWidgetAreas areas); - - void setFloating(bool floating); - void setLocation(DockLocation location); + void setDropDestinations(const QVariantList& destinations); + void setPersistent(bool persistent); void setResizable(bool resizable); void setSeparatorsVisible(bool visible); + void setFloating(bool floating); + signals: void titleChanged(); + void minimumSizeChanged(); void maximumSizeChanged(); void contentSizeChanged(); - void allowedAreasChanged(); - void floatingChanged(); - - void locationChanged(DockLocation location); + void locationChanged(); + void dropDestinationsChanged(); + void persistentChanged(); void resizableChanged(); void separatorsVisibleChanged(); + void floatingChanged(); + protected: friend class DockWindow; - virtual DockType type() const; - void componentComplete() override; + virtual DockType type() const; + KDDockWidgets::DockWidgetQuick* dockWidget() const; private slots: @@ -144,6 +147,10 @@ private: void listenFloatingChanges(); void doSetFloating(bool floating); + void writeProperties(); + + QString m_title; + int m_minimumWidth = 0; int m_minimumHeight = 0; int m_maximumWidth = 0; @@ -151,13 +158,28 @@ private: int m_contentWidth = 0; int m_contentHeight = 0; - QString m_title; - Qt::DockWidgetAreas m_allowedAreas = Qt::NoDockWidgetArea; - KDDockWidgets::DockWidgetQuick* m_dockWidget = nullptr; - bool m_floating = false; DockLocation m_location = DockLocation::Undefined; + QVariantList m_dropDestinations; + + bool m_persistent = false; bool m_resizable = false; bool m_separatorsVisible = false; + bool m_selected = false; + + bool m_floating = false; + + KDDockWidgets::DockWidgetQuick* m_dockWidget = nullptr; +}; + +struct DropDestination +{ + DockBase* dock = nullptr; + DropLocation::Location dropLocation = DropLocation::None; + + bool operator==(const DropDestination& dest) const; + + bool isValid() const; + void clear(); }; } diff --git a/src/appshell/view/dockwindow/internal/dockframemodel.cpp b/src/appshell/view/dockwindow/internal/dockframemodel.cpp index 4f2b122be6..6aeb8751a5 100644 --- a/src/appshell/view/dockwindow/internal/dockframemodel.cpp +++ b/src/appshell/view/dockwindow/internal/dockframemodel.cpp @@ -46,6 +46,10 @@ DockFrameModel::DockFrameModel(QObject* parent) bool DockFrameModel::eventFilter(QObject* watched, QEvent* event) { + if (event->type() != QEvent::DynamicPropertyChange) { + return QObject::eventFilter(watched, event); + } + auto propertyChangeEvent = dynamic_cast(event); if (!propertyChangeEvent) { return QObject::eventFilter(watched, event); @@ -59,6 +63,10 @@ bool DockFrameModel::eventFilter(QObject* watched, QEvent* event) } } + if (propertyChangeEvent->propertyName() == "selected") { + emit selectionVisibleChanged(); + } + return QObject::eventFilter(watched, event); } @@ -71,12 +79,11 @@ QVariantList DockFrameModel::tabs() const { QVariantList result; - auto frame = dynamic_cast(m_frame); - if (!frame || frame->hasSingleDockWidget()) { + if (!m_frame || m_frame->hasSingleDockWidget()) { return result; } - for (const KDDockWidgets::DockWidgetBase* dock : frame->dockWidgets()) { + for (const KDDockWidgets::DockWidgetBase* dock : m_frame->dockWidgets()) { QVariantMap tab; tab["title"] = dock->title(); tab[CONTEXT_MENU_MODEL_PROPERTY] = dock->property(CONTEXT_MENU_MODEL_PROPERTY); @@ -98,7 +105,7 @@ void DockFrameModel::setFrame(QQuickItem* frame) return; } - m_frame = frame; + m_frame = dynamic_cast(frame); emit frameChanged(frame); listenChangesInFrame(); @@ -106,19 +113,18 @@ void DockFrameModel::setFrame(QQuickItem* frame) void DockFrameModel::listenChangesInFrame() { - auto frame = dynamic_cast(m_frame); - if (!frame) { + if (!m_frame) { return; } - connect(frame, &KDDockWidgets::Frame::numDockWidgetsChanged, this, [this, frame]() { + connect(m_frame, &KDDockWidgets::Frame::numDockWidgetsChanged, this, [this]() { emit tabsChanged(); - auto currentDock = frame->currentDockWidget(); - auto allDocks = frame->dockWidgets(); + auto currentDock = m_frame->currentDockWidget(); + auto allDocks = m_frame->dockWidgets(); if (!allDocks.contains(currentDock)) { - frame->setCurrentTabIndex(0); + m_frame->setCurrentTabIndex(0); } if (allDocks.size() != 1) { @@ -127,13 +133,13 @@ void DockFrameModel::listenChangesInFrame() } DockProperties properties = readPropertiesFromObject(allDocks.first()); - bool visible = (properties.type == DockType::Panel && properties.allowedAreas != Qt::NoDockWidgetArea); + bool visible = (properties.type == DockType::Panel) && !properties.persistent; setTitleBarVisible(visible); updateNavigationSection(); }); - connect(frame, &KDDockWidgets::Frame::currentDockWidgetChanged, this, [this]() { + connect(m_frame, &KDDockWidgets::Frame::currentDockWidgetChanged, this, [this]() { updateNavigationSection(); emit currentDockChanged(); @@ -172,9 +178,8 @@ QObject* DockFrameModel::navigationSection() const QString DockFrameModel::currentDockUniqueName() const { - auto frame = dynamic_cast(m_frame); - if (frame && frame->currentDockWidget()) { - return frame->currentDockWidget()->uniqueName(); + if (m_frame && m_frame->currentDockWidget()) { + return m_frame->currentDockWidget()->uniqueName(); } return QString(); @@ -185,10 +190,26 @@ QVariant DockFrameModel::currentDockContextMenuModel() const return currentDockProperty(CONTEXT_MENU_MODEL_PROPERTY); } +bool DockFrameModel::selectionVisible() const +{ + if (!m_frame) { + return false; + } + + for (auto dock : m_frame->dockWidgets()) { + DockProperties properties = readPropertiesFromObject(dock); + + if (properties.selected) { + return true; + } + } + + return false; +} + const QObject* DockFrameModel::currentDockObject() const { - auto frame = dynamic_cast(m_frame); - return frame ? frame->currentDockWidget() : nullptr; + return m_frame ? m_frame->currentDockWidget() : nullptr; } QVariant DockFrameModel::currentDockProperty(const char* propertyName) const diff --git a/src/appshell/view/dockwindow/internal/dockframemodel.h b/src/appshell/view/dockwindow/internal/dockframemodel.h index 6783789f47..e18ac12317 100644 --- a/src/appshell/view/dockwindow/internal/dockframemodel.h +++ b/src/appshell/view/dockwindow/internal/dockframemodel.h @@ -28,6 +28,10 @@ #include "modularity/ioc.h" #include "actions/iactionsdispatcher.h" +namespace KDDockWidgets { +class Frame; +} + namespace mu::dock { class DockFrameModel : public QObject { @@ -43,6 +47,8 @@ class DockFrameModel : public QObject Q_PROPERTY(QString currentDockUniqueName READ currentDockUniqueName NOTIFY currentDockChanged) Q_PROPERTY(QVariant currentDockContextMenuModel READ currentDockContextMenuModel NOTIFY currentDockChanged) + Q_PROPERTY(bool selectionVisible READ selectionVisible NOTIFY selectionVisibleChanged) + public: explicit DockFrameModel(QObject* parent = nullptr); @@ -54,6 +60,8 @@ public: QString currentDockUniqueName() const; QVariant currentDockContextMenuModel() const; + bool selectionVisible() const; + Q_INVOKABLE void handleMenuItem(const QString& itemId) const; public slots: @@ -65,6 +73,7 @@ signals: void titleBarVisibleChanged(bool visible); void navigationSectionChanged(); void currentDockChanged(); + void selectionVisibleChanged(); private: bool eventFilter(QObject* watched, QEvent* event); @@ -78,7 +87,7 @@ private: QObject* currentNavigationSection() const; void updateNavigationSection(); - QQuickItem* m_frame = nullptr; + KDDockWidgets::Frame* m_frame = nullptr; bool m_titleBarVisible = false; QObject* m_navigationSection = nullptr; }; diff --git a/src/appshell/view/dockwindow/internal/dragcontroller.cpp b/src/appshell/view/dockwindow/internal/dragcontroller.cpp new file mode 100644 index 0000000000..c04c0dc22e --- /dev/null +++ b/src/appshell/view/dockwindow/internal/dragcontroller.cpp @@ -0,0 +1,101 @@ +/* + * SPDX-License-Identifier: GPL-3.0-only + * MuseScore-CLA-applies + * + * MuseScore + * Music Composition & Notation + * + * Copyright (C) 2021 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 . + */ + +#include "dragcontroller.h" + +#include "../idockwindow.h" +#include "../docktypes.h" + +using namespace mu::dock; + +using DockWidget = KDDockWidgets::DockWidgetBase; +using KDDropLocation = KDDockWidgets::DropIndicatorOverlayInterface::DropLocation; + +namespace mu::dock { +static const DockWidget* draggedDock() +{ + auto windowBeingDragged = KDDockWidgets::DragController::instance()->windowBeingDragged(); + if (!windowBeingDragged || windowBeingDragged->dockWidgets().isEmpty()) { + return nullptr; + } + + return windowBeingDragged->dockWidgets().first(); +} + +static KDDropLocation dropLocationToKDDockLocation(DropLocation::Location location) +{ + switch (location) { + case DropLocation::None: return KDDropLocation::DropLocation_None; + case DropLocation::Left: return KDDropLocation::DropLocation_Left; + case DropLocation::Right: return KDDropLocation::DropLocation_Right; + case DropLocation::Center: return KDDropLocation::DropLocation_Center; + case DropLocation::Top: return KDDropLocation::DropLocation_Top; + case DropLocation::Bottom: return KDDropLocation::DropLocation_Bottom; + } + + return KDDropLocation::DropLocation_None; +} +} + +DragController::DragController(KDDockWidgets::DropArea* dropArea) + : KDDockWidgets::DropIndicatorOverlayInterface(dropArea) +{ + +} + +KDDropLocation DragController::hover_impl(QPoint globalPos) +{ + IDockWindow* window = dockWindow(); + const DockWidget* dock = draggedDock(); + + if (!window || !dock) { + return DropLocation_None; + } + + dock::DropLocation::Location location = window->hover(dock->uniqueName(), globalPos); + setCurrentDropLocation(dropLocationToKDDockLocation(location)); + + return currentDropLocation(); +} + +void DragController::updateVisibility() +{ + if (draggedDock()) { + return; + } + + setCurrentDropLocation(DropLocation_None); + + if (auto window = dockWindow()) { + window->endHover(); + } +} + +QPoint DragController::posForIndicator(KDDropLocation) const +{ + return QPoint(); +} + +IDockWindow* DragController::dockWindow() const +{ + return dockWindowProvider()->window(); +} diff --git a/src/appshell/view/dockwindow/dockpanelholder.h b/src/appshell/view/dockwindow/internal/dragcontroller.h similarity index 55% rename from src/appshell/view/dockwindow/dockpanelholder.h rename to src/appshell/view/dockwindow/internal/dragcontroller.h index 923758703a..3f25544948 100644 --- a/src/appshell/view/dockwindow/dockpanelholder.h +++ b/src/appshell/view/dockwindow/internal/dragcontroller.h @@ -20,22 +20,30 @@ * along with this program. If not, see . */ -#ifndef MU_DOCK_DOCKPANELHOLDER_H -#define MU_DOCK_DOCKPANELHOLDER_H +#ifndef MU_DOCK_DRAGCONTROLLER_H +#define MU_DOCK_DRAGCONTROLLER_H -#include "dockpanelview.h" +#include "modularity/ioc.h" +#include "../idockwindowprovider.h" + +#include "thirdparty/KDDockWidgets/src/private/DropIndicatorOverlayInterface_p.h" namespace mu::dock { -class DockPanelHolder : public DockPanelView +class DragController : public KDDockWidgets::DropIndicatorOverlayInterface { - Q_OBJECT + INJECT(dock, IDockWindowProvider, dockWindowProvider) public: - explicit DockPanelHolder(QQuickItem* parent = nullptr); + explicit DragController(KDDockWidgets::DropArea* dropArea); + + DropLocation hover_impl(QPoint globalPos) override; + QPoint posForIndicator(DropLocation) const override; private: - DockType type() const override; + void updateVisibility() override; + + IDockWindow* dockWindow() const; }; } -#endif // MU_DOCK_DOCKPANELHOLDER_H +#endif // MU_DOCK_DRAGCONTROLLER_H diff --git a/src/appshell/view/dockwindow/internal/dropindicators.cpp b/src/appshell/view/dockwindow/internal/dropindicators.cpp index f0897892a2..5b04984144 100644 --- a/src/appshell/view/dockwindow/internal/dropindicators.cpp +++ b/src/appshell/view/dockwindow/internal/dropindicators.cpp @@ -107,11 +107,11 @@ KDDockWidgets::DropIndicatorOverlayInterface::DropLocation DropIndicators::hover } if (needShowToolBarHolders()) { - dockWindow()->showDockingHolder(globalPos, IDockWindow::ToolBar); +// dockWindow()->showDockingHolder(globalPos, IDockWindow::ToolBar); } if (needShowPanelHolders()) { - dockWindow()->showDockingHolder(globalPos, IDockWindow::Panel); +// dockWindow()->showDockingHolder(globalPos, IDockWindow::Panel); } if (isDropAllowed(dropLocation)) { @@ -199,7 +199,7 @@ void DropIndicators::updateVisibility() updateWindowPosition(); m_indicatorsWindow->raise(); } else { - dockWindow()->hideAllDockingHolders(); + dockWindow()->endHover(); hideDropArea(); } @@ -242,8 +242,8 @@ bool DropIndicators::isDropAllowed(DropLocation location) const switch (hoveredDockType) { case DockType::Central: { if (isDragged(DockType::Panel)) { - Qt::DockWidgetArea area = locationToDockArea(location); - bool isAreaAllowed = draggedDockProperties.allowedAreas.testFlag(area); +// Qt::DockWidgetArea area = locationToDockArea(location); + bool isAreaAllowed = false;//draggedDockProperties.allowedAreas.testFlag(area); // For top/bottom location, we need to use the Panel-/Toolbar docking holders // Because a panel or toolbar at the top needs to go also outside the left/right @@ -252,34 +252,34 @@ bool DropIndicators::isDropAllowed(DropLocation location) const } } break; - case DockType::Panel: - case DockType::PanelDockingHolder: { - if (!isDragged(DockType::Panel)) { - return false; - } +// case DockType::Panel: +// case DockType::PanelDockingHolder: { +// if (!isDragged(DockType::Panel)) { +// return false; +// } - // TODO: Determine location of hovered panel or panel docking holder and check if - // that is one of the allowed areas of the dragged panel +// // TODO: Determine location of hovered panel or panel docking holder and check if +// // that is one of the allowed areas of the dragged panel - if (isHovered(DockType::PanelDockingHolder)) { - // Avoid tabbing with docking holder, because it breaks the holders system - return location != DropLocation_Center; - } +// if (isHovered(DockType::PanelDockingHolder)) { +// // Avoid tabbing with docking holder, because it breaks the holders system +// return location != DropLocation_Center; +// } - return true; - } break; +// return true; +// } break; - case DockType::ToolBar: - case DockType::ToolBarDockingHolder: { - if (!isDragged(DockType::ToolBar)) { - return false; - } +// case DockType::ToolBar: +// case DockType::DockingHolder: { +// if (!isDragged(DockType::ToolBar)) { +// return false; +// } - // TODO: what is our policy with vertical toolbars? - // Currently not important because there's at most one toolbar that may become vertical. - bool equalOrientations = dockOrientation(*hoveredDock) == dockOrientation(*draggedDock); - return isSideLocation && equalOrientations; - } break; +// // TODO: what is our policy with vertical toolbars? +// // Currently not important because there's at most one toolbar that may become vertical. +// bool equalOrientations = dockOrientation(*hoveredDock) == dockOrientation(*draggedDock); +// return isSideLocation && equalOrientations; +// } break; default: break; @@ -293,11 +293,11 @@ bool DropIndicators::isDropOnHoveredDockAllowed() const DockType hoveredDockType = dockType(hoveredDock()); if (isDraggedDockToolBar()) { - return hoveredDockType == DockType::ToolBar || hoveredDockType == DockType::ToolBarDockingHolder; + return hoveredDockType == DockType::ToolBar || hoveredDockType == DockType::DockingHolder; } if (isDraggedDockPanel()) { - return hoveredDockType == DockType::Panel || hoveredDockType == DockType::PanelDockingHolder; +// return hoveredDockType == DockType::Panel || hoveredDockType == DockType::PanelDockingHolder; } return true; @@ -319,8 +319,9 @@ bool DropIndicators::needShowToolBarHolders() const return false; } - Qt::DockWidgetAreas areas = readPropertiesFromObject(draggedDock()).allowedAreas; - return areas.testFlag(Qt::LeftDockWidgetArea) || areas.testFlag(Qt::RightDockWidgetArea); +// Qt::DockWidgetAreas areas = readPropertiesFromObject(draggedDock()).allowedAreas; +// return areas.testFlag(Qt::LeftDockWidgetArea) || areas.testFlag(Qt::RightDockWidgetArea); + return false; } bool DropIndicators::needShowPanelHolders() const @@ -329,8 +330,9 @@ bool DropIndicators::needShowPanelHolders() const return false; } - Qt::DockWidgetAreas areas = readPropertiesFromObject(draggedDock()).allowedAreas; - return areas.testFlag(Qt::TopDockWidgetArea) || areas.testFlag(Qt::BottomDockWidgetArea); +// Qt::DockWidgetAreas areas = readPropertiesFromObject(draggedDock()).allowedAreas; +// return areas.testFlag(Qt::TopDockWidgetArea) || areas.testFlag(Qt::BottomDockWidgetArea); + return false; } const KDDockWidgets::DockWidgetBase* DropIndicators::draggedDock() const @@ -472,7 +474,7 @@ void DropIndicators::updateToolBarOrientation() newOrientation = framework::Orientation::Vertical; } - dockWindow()->setToolBarOrientation(draggedDock->uniqueName(), newOrientation); +// dockWindow()->setToolBarOrientation(draggedDock->uniqueName(), newOrientation); } void DropIndicators::updateWindowPosition()