1 /*
2   quickitemmodel.h
3 
4   This file is part of GammaRay, the Qt application inspection and
5   manipulation tool.
6 
7   Copyright (C) 2014-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
8   Author: Volker Krause <volker.krause@kdab.com>
9 
10   Licensees holding valid commercial KDAB GammaRay licenses may use this file in
11   accordance with GammaRay Commercial License Agreement provided with the Software.
12 
13   Contact info@kdab.com if any conditions of this licensing are not clear to you.
14 
15   This program is free software; you can redistribute it and/or modify
16   it under the terms of the GNU General Public License as published by
17   the Free Software Foundation, either version 2 of the License, or
18   (at your option) any later version.
19 
20   This program is distributed in the hope that it will be useful,
21   but WITHOUT ANY WARRANTY; without even the implied warranty of
22   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23   GNU General Public License for more details.
24 
25   You should have received a copy of the GNU General Public License
26   along with this program.  If not, see <http://www.gnu.org/licenses/>.
27 */
28 
29 #ifndef GAMMARAY_QUICKINSPECTOR_QUICKITEMMODEL_H
30 #define GAMMARAY_QUICKINSPECTOR_QUICKITEMMODEL_H
31 
32 #include <core/objectmodelbase.h>
33 
34 #include <QHash>
35 #include <QPointer>
36 #include <QTimer>
37 #include <QVector>
38 
39 #include <array>
40 #include <unordered_map>
41 #include <vector>
42 
43 QT_BEGIN_NAMESPACE
44 class QQuickItem;
45 class QQuickWindow;
46 QT_END_NAMESPACE
47 
48 namespace GammaRay {
49 
50 //forward
51 class QuickEventMonitor;
52 
53 /** QQ2 item tree model. */
54 class QuickItemModel : public ObjectModelBase<QAbstractItemModel>
55 {
56     Q_OBJECT
57 
58 public:
59     explicit QuickItemModel(QObject *parent = nullptr);
60     ~QuickItemModel() override;
61 
62     void setWindow(QQuickWindow *window);
63 
64     QVariant data(const QModelIndex &index, int role) const override;
65     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
66     QModelIndex parent(const QModelIndex &child) const override;
67     QModelIndex index(int row, int column, const QModelIndex &parent) const override;
68     QMap< int, QVariant > itemData(const QModelIndex &index) const override;
69 
70 public slots:
71     void objectAdded(QObject *obj);
72     void objectRemoved(QObject *obj);
73 
74 private slots:
75     void itemReparented(QQuickItem *item);
76     void itemWindowChanged(QQuickItem *item);
77     void itemUpdated(QQuickItem *item);
78 
79 private:
80     friend class QuickEventMonitor;
81     void updateItem(QQuickItem *item, int role);
82     void recursivelyUpdateItem(QQuickItem *item);
83     void updateItemFlags(QQuickItem *item);
84     void clear();
85     void populateFromItem(QQuickItem *item);
86 
87     /**
88      * Reports problems (e.g. visible but out of view) about all items of this
89      * model. Uses the item flags from the model.
90      */
91     void reportProblems();
92 
93     /// Track all changes to item @p item in this model (parentChanged, windowChanged, ...)
94     void connectItem(QQuickItem *item);
95 
96     /// Untrack item @p item
97     void disconnectItem(QQuickItem *item);
98     QModelIndex indexForItem(QQuickItem *item) const;
99 
100     /// Add item @p item to this model
101     void addItem(QQuickItem *item);
102 
103     /// Remove item @p item from this model.
104     /// Set @p danglingPointer to true if the item has already been destructed
105     void removeItem(QQuickItem *item, bool danglingPointer = false);
106 
107     /**
108      * Remove item @p item from the internal data set.
109      * This function won't cause rowsRemoved to be emitted.
110      * Set @p danglingPointer to true if the item has already been destructed.
111      */
112     void doRemoveSubtree(QQuickItem *item, bool danglingPointer = false);
113 
114     QPointer<QQuickWindow> m_window;
115 
116     QHash<QQuickItem *, QQuickItem *> m_childParentMap;
117     QHash<QQuickItem *, QVector<QQuickItem *> > m_parentChildMap;
118 
119     // TODO: Merge these two?
120     QHash<QQuickItem *, int> m_itemFlags;
121     std::unordered_map<QQuickItem *, std::array<QMetaObject::Connection, 8>> m_itemConnections;
122 
123     // dataChange signal compression
124     struct PendingDataChange {
125         QQuickItem *item = nullptr;
126         bool eventChange = false;
127         bool flagChange = false;
128         inline bool operator<(QQuickItem *rhs) const { return item < rhs; }
129     };
130     std::vector<PendingDataChange> m_pendingDataChanges;
131     QTimer *m_dataChangeTimer = nullptr;
132     void emitPendingDataChanges();
133 
134     QuickEventMonitor *m_clickEventFilter;
135 };
136 
137 class QuickEventMonitor : public QObject
138 {
139     Q_OBJECT
140 public:
141     explicit QuickEventMonitor(QuickItemModel *parent);
142 
143 protected:
144     bool eventFilter(QObject *obj, QEvent *event) override;
145 
146 private:
147     QuickItemModel *m_model;
148 };
149 }
150 
151 #endif // GAMMARAY_QUICKITEMMODEL_H
152