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 "dockseparator.h"
24 :
25 : #include "log.h"
26 : #include "../docktypes.h"
27 :
28 : #include "kddockwidgets/src/core/Separator.h"
29 : #include "kddockwidgets/src/core/DockRegistry.h"
30 : #include "kddockwidgets/src/core/Group.h"
31 : #include "kddockwidgets/src/core/DockWidget.h"
32 : #include "kddockwidgets/src/core/layouting/LayoutingSeparator_p.h"
33 :
34 : // This include pulls in kdbindings/signal.h which is incompatible with
35 : // Qt's `emit` macro being defined. Temporarily undefine it, then restore it.
36 : #ifdef emit
37 : #undef emit
38 : #include "kddockwidgets/src/core/layouting/Item_p.h"
39 : #define emit
40 : #else
41 : #include "kddockwidgets/src/core/layouting/Item_p.h"
42 : #endif
43 :
44 : #include <QTimer>
45 :
46 : using namespace muse::dock;
47 : using namespace KDDockWidgets;
48 :
49 : namespace muse::dock {
50 0 : static const QObject* findNearestDockView(const DockSeparator* separator, int ctx)
51 : {
52 0 : auto* coreSeparator = static_cast<Core::Separator*>(separator->controller());
53 0 : auto* layoutingSeparator = coreSeparator->asLayoutingSeparator();
54 0 : auto* container = layoutingSeparator->parentContainer();
55 0 : if (!container) {
56 0 : return nullptr;
57 : }
58 :
59 0 : int separatorPos = layoutingSeparator->position();
60 0 : Qt::Orientation orientation = layoutingSeparator->orientation();
61 0 : Core::Item::List children = container->visibleChildren();
62 :
63 0 : const Core::Item* nearestItem = nullptr;
64 0 : int minPosDiff = std::numeric_limits<int>::max();
65 :
66 0 : for (const Core::Item* child : children) {
67 0 : int childPos = child->pos(orientation);
68 0 : int diff = std::abs(childPos - separatorPos);
69 0 : if (diff < minPosDiff) {
70 0 : nearestItem = child;
71 0 : minPosDiff = diff;
72 : }
73 : }
74 :
75 0 : if (!nearestItem) {
76 0 : return nullptr;
77 : }
78 :
79 0 : auto* guest = nearestItem->guest();
80 0 : for (Core::Group* group : DockRegistry::self(ctx)->groups()) {
81 0 : if (group->asLayoutingGuest() == guest) {
82 0 : if (group->isEmpty()) {
83 0 : return nullptr;
84 : }
85 :
86 0 : return group->currentDockWidget();
87 : }
88 0 : }
89 :
90 0 : return nullptr;
91 0 : }
92 : }
93 :
94 0 : DockSeparator::DockSeparator(Core::Separator* controller, QQuickItem* parent)
95 0 : : KDDockWidgets::QtQuick::Separator(controller, parent), Contextable(muse::iocCtxForQmlObject(this)),
96 0 : m_isSeparatorVisible(true)
97 : {
98 0 : QTimer::singleShot(0, this, [this]() {
99 : // Set inited before emitting showResizeCursorChanged so QML bindings
100 : // can safely call showResizeCursor() — minPosForSeparator_global() asserts
101 : // if called during construction before the separator is in the layout.
102 0 : m_inited = true;
103 0 : emit showResizeCursorChanged();
104 0 : initAvailability();
105 0 : });
106 0 : }
107 :
108 0 : void DockSeparator::initAvailability()
109 : {
110 0 : const QObject* dock = findNearestDockView(this, iocContext()->id);
111 0 : DockProperties properties = readPropertiesFromObject(dock);
112 :
113 0 : if (properties.isValid()) {
114 0 : m_isSeparatorVisible = properties.separatorsVisible;
115 0 : emit isSeparatorVisibleChanged();
116 0 : emit showResizeCursorChanged();
117 : }
118 0 : }
119 :
120 0 : bool DockSeparator::isSeparatorVisible() const
121 : {
122 0 : return m_isSeparatorVisible;
123 : }
124 :
125 0 : bool DockSeparator::showResizeCursor() const
126 : {
127 0 : if (!m_inited) {
128 : // Called during QML item construction before the separator is in the layout.
129 : // minPosForSeparator_global() would assert — return false until inited.
130 0 : return false;
131 : }
132 0 : auto* coreSepa = static_cast<Core::Separator*>(controller());
133 0 : auto* layoutingSep = coreSepa->asLayoutingSeparator();
134 0 : auto* container = layoutingSep->parentContainer();
135 : return container
136 0 : && (container->minPosForSeparator_global(layoutingSep)
137 0 : != container->maxPosForSeparator_global(layoutingSep));
138 : }
|