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 : #pragma once
24 :
25 : #include <QAbstractItemModel>
26 : #include <QHash>
27 : #include <QTimer>
28 : #include <qqmlintegration.h>
29 :
30 : #include "modularity/ioc.h"
31 : #include "accessibility/iaccessibilitycontroller.h"
32 :
33 : #include "async/asyncable.h"
34 :
35 : class QAccessibleInterface;
36 : class QAccessibleEvent;
37 : namespace muse::diagnostics {
38 : class DiagnosticAccessibleModel : public QAbstractItemModel, public muse::Contextable, public muse::async::Asyncable
39 : {
40 : Q_OBJECT
41 :
42 : Q_PROPERTY(bool isAutoRefresh READ isAutoRefresh WRITE setIsAutoRefresh NOTIFY isAutoRefreshChanged)
43 :
44 : QML_ELEMENT
45 :
46 : muse::ContextInject<muse::accessibility::IAccessibilityController> accessibilityController = { this };
47 :
48 : public:
49 : explicit DiagnosticAccessibleModel(QObject* parent = nullptr);
50 : ~DiagnosticAccessibleModel();
51 :
52 : bool isAutoRefresh() const;
53 :
54 : QModelIndex index(int row, int column, const QModelIndex& parent) const override;
55 : QModelIndex parent(const QModelIndex& child) const override;
56 : int rowCount(const QModelIndex& parent) const override;
57 : int columnCount(const QModelIndex& parent) const override;
58 : QVariant data(const QModelIndex& index, int role) const override;
59 : QHash<int, QByteArray> roleNames() const override;
60 :
61 : Q_INVOKABLE void init();
62 : Q_INVOKABLE void reload();
63 :
64 : void dumpTree();
65 :
66 : public slots:
67 : void setIsAutoRefresh(bool isAutoRefresh);
68 :
69 : signals:
70 : void beforeReload();
71 : void afterReload();
72 : void focusedItem(QModelIndex index);
73 :
74 : void isAutoRefreshChanged();
75 :
76 : private:
77 :
78 : enum Roles {
79 : rItemData = Qt::UserRole + 1
80 : };
81 :
82 : struct Item
83 : {
84 0 : quintptr key() const { return reinterpret_cast<quintptr>(this); }
85 :
86 0 : int row() const
87 : {
88 0 : if (m_parent) {
89 0 : return m_parent->m_children.indexOf(const_cast<Item*>(this));
90 : }
91 0 : return 0;
92 : }
93 :
94 0 : Item* parent() const { return m_parent; }
95 :
96 0 : void addChild(Item* child) { m_children.append(child); }
97 0 : Item* child(int row) const { return m_children.at(row); }
98 0 : int childCount() const { return m_children.count(); }
99 :
100 0 : void setData(const QVariant& d) { m_data = d; }
101 0 : QVariant data() const { return m_data; }
102 :
103 0 : void setIface(QAccessibleInterface* iface) { m_iface = iface; }
104 0 : QAccessibleInterface* iface() const { return m_iface; }
105 :
106 0 : Item(Item* parent)
107 0 : : m_parent(parent)
108 : {
109 0 : if (m_parent) {
110 0 : m_parent->addChild(this);
111 : }
112 0 : }
113 :
114 0 : ~Item()
115 : {
116 0 : for (Item* item : m_children) {
117 0 : delete item;
118 : }
119 0 : }
120 :
121 : private:
122 : Item* m_parent = nullptr;
123 : QList<Item*> m_children;
124 : QVariant m_data;
125 : QAccessibleInterface* m_iface = nullptr;
126 : };
127 :
128 : Item* createItem(Item* parent);
129 : Item* itemByModelIndex(const QModelIndex& index) const;
130 :
131 : void load(QAccessibleInterface* iface, Item* parent);
132 : QVariant makeData(const QAccessibleInterface* iface) const;
133 :
134 : void onAccessibleEvent(QAccessibleEvent* ev);
135 : void onItemChanged(QObject* accessibleObject);
136 : Item* findItemForIface(const QAccessibleInterface* iface, Item* rootItem) const;
137 :
138 : QObject* m_accessibleRootObject;
139 : Item* m_rootItem = nullptr;
140 : QTimer m_refresher;
141 : bool m_isAutoRefresh = false;
142 : QHash<quintptr, Item*> m_allItems;
143 : };
144 : }
|