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 : #include "abstractnavigation.h"
23 :
24 : #include <QQuickWindow>
25 :
26 : #include "qmlaccessible.h"
27 :
28 : #include "log.h"
29 :
30 : using namespace muse;
31 : using namespace muse::ui;
32 : using namespace muse::accessibility;
33 :
34 0 : AbstractNavigation::AbstractNavigation(QObject* parent)
35 0 : : QObject(parent), Contextable(muse::iocCtxForQmlObject(this))
36 : {
37 0 : }
38 :
39 560 : AbstractNavigation::AbstractNavigation(const muse::modularity::ContextPtr& iocCtx, QObject* parent)
40 2240 : : QObject(parent), Contextable(iocCtx)
41 : {
42 2240 : }
43 :
44 0 : bool AbstractNavigation::isComponentCompleted() const
45 : {
46 0 : return m_isComponentCompleted;
47 : }
48 :
49 0 : void AbstractNavigation::componentComplete()
50 : {
51 0 : IF_ASSERT_FAILED(!isComponentCompleted()) {
52 0 : return;
53 : }
54 :
55 0 : if (m_accessible) {
56 0 : m_accessible->setState(IAccessible::State::Enabled, enabled());
57 0 : m_accessible->setState(IAccessible::State::Active, active());
58 0 : m_accessible->componentComplete();
59 : }
60 :
61 0 : navigationController()->highlightChanged().onNotify(this, [this](){
62 0 : emit highlightChanged();
63 0 : }, async::Asyncable::Mode::SetReplace);
64 :
65 0 : m_isComponentCompleted = true;
66 : }
67 :
68 2 : void AbstractNavigation::setName(QString name)
69 : {
70 2 : if (m_name == name) {
71 0 : return;
72 : }
73 :
74 2 : m_name = name;
75 2 : emit nameChanged(m_name);
76 : }
77 :
78 10 : QString AbstractNavigation::name() const
79 : {
80 10 : return m_name;
81 : }
82 :
83 780 : const INavigation::Index& AbstractNavigation::index() const
84 : {
85 780 : return m_index;
86 : }
87 :
88 0 : void AbstractNavigation::setIndex(const INavigation::Index& index)
89 : {
90 0 : if (m_index == index) {
91 0 : return;
92 : }
93 :
94 0 : bool _rowChanged = m_index.row != index.row;
95 0 : bool _columnChanged = m_index.column != index.column;
96 0 : bool _orderChanged = m_index.order() != index.order();
97 :
98 0 : m_index = index;
99 :
100 0 : if (m_indexChanged.isConnected()) {
101 0 : m_indexChanged.send(m_index);
102 : }
103 :
104 0 : if (_rowChanged) {
105 0 : emit rowChanged(m_index.row);
106 : }
107 :
108 0 : if (_columnChanged) {
109 0 : emit columnChanged(m_index.column);
110 : }
111 :
112 0 : if (_orderChanged) {
113 0 : emit orderChanged(m_index.order());
114 : }
115 : }
116 :
117 0 : async::Channel<INavigation::Index> AbstractNavigation::indexChanged() const
118 : {
119 0 : return m_indexChanged;
120 : }
121 :
122 560 : void AbstractNavigation::setOrder(int order)
123 : {
124 560 : if (m_index.order() == order) {
125 560 : return;
126 : }
127 :
128 0 : m_index.setOrder(order);
129 0 : emit orderChanged(order);
130 :
131 0 : if (m_indexChanged.isConnected()) {
132 0 : m_indexChanged.send(m_index);
133 : }
134 : }
135 :
136 0 : int AbstractNavigation::order() const
137 : {
138 0 : return m_index.order();
139 : }
140 :
141 560 : void AbstractNavigation::setColumn(int column)
142 : {
143 560 : if (m_index.column == column) {
144 0 : return;
145 : }
146 :
147 560 : m_index.column = column;
148 560 : emit columnChanged(column);
149 :
150 560 : if (m_indexChanged.isConnected()) {
151 0 : m_indexChanged.send(m_index);
152 : }
153 : }
154 :
155 0 : int AbstractNavigation::column() const
156 : {
157 0 : return m_index.column;
158 : }
159 :
160 560 : void AbstractNavigation::setRow(int row)
161 : {
162 560 : if (m_index.row == row) {
163 548 : return;
164 : }
165 :
166 12 : m_index.row = row;
167 12 : emit rowChanged(row);
168 :
169 12 : if (m_indexChanged.isConnected()) {
170 0 : m_indexChanged.send(m_index);
171 : }
172 : }
173 :
174 0 : int AbstractNavigation::row() const
175 : {
176 0 : return m_index.row;
177 : }
178 :
179 567 : void AbstractNavigation::setEnabled(bool enabled)
180 : {
181 567 : if (m_enabled == enabled) {
182 560 : return;
183 : }
184 :
185 7 : m_enabled = enabled;
186 7 : emit enabledChanged(m_enabled);
187 :
188 7 : if (m_enabledChanged.isConnected()) {
189 6 : m_enabledChanged.send(m_enabled);
190 : }
191 :
192 7 : if (m_accessible) {
193 0 : m_accessible->setState(IAccessible::State::Enabled, enabled);
194 : }
195 : }
196 :
197 683 : bool AbstractNavigation::enabled() const
198 : {
199 683 : return m_enabled;
200 : }
201 :
202 78 : async::Channel<bool> AbstractNavigation::enabledChanged() const
203 : {
204 78 : return m_enabledChanged;
205 : }
206 :
207 824 : void AbstractNavigation::setActive(bool active)
208 : {
209 824 : if (m_active == active) {
210 564 : return;
211 : }
212 :
213 260 : m_active = active;
214 260 : emit activeChanged(m_active);
215 260 : emit highlightChanged();
216 :
217 260 : if (m_activeChanged.isConnected()) {
218 0 : m_activeChanged.send(m_active);
219 : }
220 : }
221 :
222 1057 : bool AbstractNavigation::active() const
223 : {
224 1057 : return m_active;
225 : }
226 :
227 0 : async::Channel<bool> AbstractNavigation::activeChanged() const
228 : {
229 0 : return m_activeChanged;
230 : }
231 :
232 42 : void AbstractNavigation::onEvent(INavigation::EventPtr e)
233 : {
234 42 : NavigationEvent ev(e);
235 42 : emit navigationEvent(&ev);
236 42 : }
237 :
238 0 : QWindow* AbstractNavigation::window() const
239 : {
240 0 : QQuickItem* visualItem = this->visualItem();
241 0 : return visualItem ? visualItem->window() : nullptr;
242 : }
243 :
244 0 : QQuickItem* AbstractNavigation::visualItem() const
245 : {
246 0 : QObject* prn = parent();
247 0 : while (prn) {
248 0 : QQuickItem* vitem = qobject_cast<QQuickItem*>(prn);
249 0 : if (vitem) {
250 0 : return vitem;
251 : }
252 :
253 0 : prn = prn->parent();
254 : }
255 :
256 0 : return nullptr;
257 : }
258 :
259 1115 : AccessibleItem* AbstractNavigation::accessible() const
260 : {
261 1115 : if (!m_accessible) {
262 496 : const modularity::ContextPtr& ctx = iocContext();
263 496 : IF_ASSERT_FAILED(ctx) {
264 0 : return nullptr;
265 : }
266 496 : AbstractNavigation* self = const_cast<AbstractNavigation*>(this);
267 496 : m_accessible = new AccessibleItem(ctx, self);
268 : }
269 1115 : return m_accessible;
270 : }
271 :
272 0 : void AbstractNavigation::setAccessible(AccessibleItem* accessible)
273 : {
274 0 : if (m_accessible == accessible) {
275 0 : return;
276 : }
277 :
278 0 : if (m_accessible) {
279 0 : delete m_accessible;
280 : }
281 :
282 0 : m_accessible = accessible;
283 :
284 0 : if (m_accessible) {
285 0 : m_accessible->setParent(this);
286 0 : m_accessible->setState(IAccessible::State::Enabled, enabled());
287 0 : m_accessible->setState(IAccessible::State::Active, active());
288 : }
289 :
290 0 : emit accessibleChanged();
291 : }
292 :
293 743 : void AbstractNavigation::setAccessibleParent(AccessibleItem* p)
294 : {
295 743 : accessible()->setAccessibleParent(p);
296 743 : }
297 :
298 0 : bool AbstractNavigation::highlight() const
299 : {
300 0 : return active() && navigationController()->isHighlight();
301 : }
|