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 "dockframemodel.h"
24 :
25 : #include <QQuickItem>
26 : #include <QGuiApplication>
27 :
28 : #include "kddockwidgets/src/core/Group.h"
29 : #include "kddockwidgets/src/qtquick/views/Group.h"
30 : #include "kddockwidgets/src/qtquick/views/DockWidget.h"
31 : #include "kddockwidgets/src/qtquick/views/View.h"
32 :
33 : #include "ui/qml/Muse/Ui/navigationsection.h"
34 : #include "uicomponents/qml/Muse/UiComponents/abstractmenumodel.h"
35 :
36 : #include "docktypes.h"
37 :
38 : #include "dockpanelview.h"
39 :
40 : using namespace muse::dock;
41 : using namespace muse::actions;
42 : using namespace muse::uicomponents;
43 :
44 0 : DockFrameModel::DockFrameModel(QObject* parent)
45 0 : : QObject(parent), muse::Contextable(muse::iocCtxForQmlObject(this))
46 : {
47 0 : qApp->installEventFilter(this);
48 0 : m_tabsModel = new DockTabsModel(this);
49 0 : }
50 :
51 0 : bool DockFrameModel::eventFilter(QObject* watched, QEvent* event)
52 : {
53 0 : if (event->type() != QEvent::DynamicPropertyChange) {
54 0 : return QObject::eventFilter(watched, event);
55 : }
56 :
57 0 : auto propertyChangeEvent = dynamic_cast<QDynamicPropertyChangeEvent*>(event);
58 0 : if (!propertyChangeEvent) {
59 0 : return QObject::eventFilter(watched, event);
60 : }
61 :
62 0 : if (propertyChangeEvent->propertyName() == CONTEXT_MENU_MODEL_PROPERTY) {
63 0 : onContextMenuChanged(watched);
64 0 : } else if (propertyChangeEvent->propertyName() == TOOLBAR_COMPONENT_PROPERTY) {
65 0 : onToolBarComponentChanged(watched);
66 : }
67 :
68 0 : if (propertyChangeEvent->propertyName() == "highlightingRect") {
69 0 : emit highlightingVisibleChanged();
70 : }
71 :
72 0 : return QObject::eventFilter(watched, event);
73 : }
74 :
75 0 : void DockFrameModel::onContextMenuChanged(QObject* obj)
76 : {
77 0 : const auto* dwv = qobject_cast<const KDDockWidgets::QtQuick::DockWidget*>(obj);
78 0 : if (!dwv) {
79 0 : return;
80 : }
81 :
82 0 : m_tabsModel->contextMenuChanged(dwv);
83 :
84 0 : if (dwv == currentDockWidget()) {
85 0 : emit currentDockChanged();
86 : }
87 : }
88 :
89 0 : void DockFrameModel::onToolBarComponentChanged(QObject* obj)
90 : {
91 0 : const auto* dwv = qobject_cast<const KDDockWidgets::QtQuick::DockWidget*>(obj);
92 0 : if (!dwv) {
93 0 : return;
94 : }
95 :
96 0 : m_tabsModel->toolBarComponentChanged(dwv);
97 :
98 0 : if (dwv == currentDockWidget()) {
99 0 : emit currentDockChanged();
100 : }
101 : }
102 :
103 0 : QQuickItem* DockFrameModel::frame() const
104 : {
105 0 : return m_frame;
106 : }
107 :
108 0 : QQmlComponent* DockFrameModel::titleBar() const
109 : {
110 0 : return m_titleBar;
111 : }
112 :
113 0 : bool DockFrameModel::titleBarAllowed() const
114 : {
115 0 : return m_titleBarAllowed;
116 : }
117 :
118 0 : bool DockFrameModel::isHorizontalPanel() const
119 : {
120 0 : return m_isHorizontalPanel;
121 : }
122 :
123 0 : void DockFrameModel::setFrame(QQuickItem* frame)
124 : {
125 0 : if (frame == m_frame.data()) {
126 0 : return;
127 : }
128 :
129 0 : m_frame = qobject_cast<KDDockWidgets::QtQuick::Group*>(frame);
130 0 : emit frameChanged(frame);
131 :
132 0 : listenChangesInFrame();
133 : }
134 :
135 0 : void DockFrameModel::listenChangesInFrame()
136 : {
137 0 : if (!m_frame) {
138 0 : return;
139 : }
140 :
141 0 : connect(m_frame, &KDDockWidgets::QtQuick::Group::currentDockWidgetChanged, this, [this]() {
142 0 : auto* group = m_frame ? m_frame->group() : nullptr;
143 0 : if (!group) {
144 0 : return;
145 : }
146 :
147 0 : auto allDocks = group->dockWidgets();
148 0 : m_tabsModel->init(allDocks);
149 :
150 0 : if (allDocks.isEmpty()) {
151 0 : setTitleBarAllowed(false);
152 0 : updateNavigationSection();
153 0 : emit currentDockChanged();
154 0 : return;
155 : }
156 :
157 0 : DockProperties properties = readPropertiesFromObject(allDocks.first());
158 0 : bool isHorizontalPanel = (properties.type == DockType::Panel)
159 0 : && (properties.location == Location::Top || properties.location == Location::Bottom);
160 0 : setIsHorizontalPanel(isHorizontalPanel);
161 :
162 0 : updateTitleBar();
163 :
164 0 : bool titleBarAllowed = (properties.type == DockType::Panel) && (properties.floatable || properties.closable);
165 0 : setTitleBarAllowed(titleBarAllowed);
166 :
167 0 : updateNavigationSection();
168 0 : emit currentDockChanged();
169 0 : });
170 : }
171 :
172 0 : void DockFrameModel::setTitleBarAllowed(bool allowed)
173 : {
174 0 : if (allowed == m_titleBarAllowed) {
175 0 : return;
176 : }
177 :
178 0 : m_titleBarAllowed = allowed;
179 0 : emit titleBarAllowedChanged(allowed);
180 : }
181 :
182 0 : void DockFrameModel::setIsHorizontalPanel(bool is)
183 : {
184 0 : if (is == m_isHorizontalPanel) {
185 0 : return;
186 : }
187 :
188 0 : m_isHorizontalPanel = is;
189 0 : emit isHorizontalPanelChanged();
190 : }
191 :
192 0 : QObject* DockFrameModel::currentNavigationSection() const
193 : {
194 0 : auto dockPanel = currentDockProperty(DOCK_PANEL_PROPERTY).value<DockPanelView*>();
195 0 : return dockPanel ? dockPanel->navigationSection_property() : nullptr;
196 : }
197 :
198 0 : void DockFrameModel::updateNavigationSection()
199 : {
200 0 : QObject* n = currentNavigationSection();
201 0 : if (m_navigationSection != n) {
202 0 : m_navigationSection = n;
203 0 : emit navigationSectionChanged();
204 : }
205 0 : }
206 :
207 0 : QQmlComponent* DockFrameModel::currentTitleBar() const
208 : {
209 0 : QQmlComponent* titleBar = currentDockProperty(TITLEBAR_PROPERTY).value<QQmlComponent*>();
210 0 : return titleBar;
211 : }
212 :
213 0 : void DockFrameModel::updateTitleBar()
214 : {
215 0 : QQmlComponent* tb = currentTitleBar();
216 0 : if (m_titleBar != tb) {
217 0 : m_titleBar = tb;
218 0 : emit titleBarChanged();
219 : }
220 0 : }
221 :
222 0 : QObject* DockFrameModel::navigationSection() const
223 : {
224 0 : return m_navigationSection;
225 : }
226 :
227 0 : QString DockFrameModel::currentDockUniqueName() const
228 : {
229 0 : auto* dock = currentDockWidget();
230 0 : return dock ? dock->uniqueName() : QString();
231 : }
232 :
233 0 : QVariant DockFrameModel::currentDockContextMenuModel() const
234 : {
235 0 : return currentDockProperty(CONTEXT_MENU_MODEL_PROPERTY);
236 : }
237 :
238 0 : QVariant DockFrameModel::currentDockToolbarComponent() const
239 : {
240 0 : return currentDockProperty(TOOLBAR_COMPONENT_PROPERTY);
241 : }
242 :
243 0 : bool DockFrameModel::highlightingVisible() const
244 : {
245 0 : return highlightingRect().isValid();
246 : }
247 :
248 0 : QRect DockFrameModel::highlightingRect() const
249 : {
250 0 : if (!m_frame) {
251 0 : return QRect();
252 : }
253 :
254 0 : auto* group = m_frame->group();
255 0 : for (auto* dock : group->dockWidgets()) {
256 0 : DockProperties properties = readPropertiesFromObject(dock);
257 :
258 0 : if (properties.highlightingRect.isValid()) {
259 0 : return properties.highlightingRect;
260 : }
261 0 : }
262 :
263 0 : return QRect();
264 : }
265 :
266 0 : KDDockWidgets::QtQuick::DockWidget* DockFrameModel::currentDockWidget() const
267 : {
268 0 : if (!m_frame) {
269 0 : return nullptr;
270 : }
271 0 : auto* group = m_frame->group();
272 0 : if (!group || group->isEmpty()) {
273 0 : return nullptr;
274 : }
275 0 : auto* ctrl = group->currentDockWidget();
276 0 : return ctrl ? qobject_cast<KDDockWidgets::QtQuick::DockWidget*>(
277 0 : KDDockWidgets::QtQuick::asQQuickItem(ctrl)) : nullptr;
278 : }
279 :
280 0 : QVariant DockFrameModel::currentDockProperty(const char* propertyName) const
281 : {
282 0 : const QObject* dock = currentDockWidget();
283 0 : return dock ? dock->property(propertyName) : QVariant();
284 : }
285 :
286 0 : void DockFrameModel::handleMenuItem(const QString& itemId) const
287 : {
288 0 : auto menuModel = currentDockContextMenuModel().value<AbstractMenuModel*>();
289 :
290 0 : if (menuModel) {
291 0 : menuModel->handleMenuItem(itemId);
292 : }
293 0 : }
|