1 | // Copyright (C) 2023 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | // |
4 | // W A R N I N G |
5 | // ------------- |
6 | // |
7 | // This file is not part of the QtGraphs API. It exists purely as an |
8 | // implementation detail. This header file may change from version to |
9 | // version without notice, or even be removed. |
10 | // |
11 | // We mean it. |
12 | #ifndef QQUICKGRAPHSSCATTER_P_H |
13 | #define QQUICKGRAPHSSCATTER_P_H |
14 | |
15 | #include "qquickgraphsitem_p.h" |
16 | #include "qscatter3dseries.h" |
17 | #include "qvalue3daxis.h" |
18 | #include <private/scatterinstancing_p.h> |
19 | |
20 | #include <private/qgraphsglobal_p.h> |
21 | #include <private/qqmldelegatemodel_p.h> |
22 | |
23 | QT_BEGIN_NAMESPACE |
24 | |
25 | struct Scatter3DChangeBitField |
26 | { |
27 | bool selectedItemChanged : 1; |
28 | bool itemChanged : 1; |
29 | |
30 | Scatter3DChangeBitField() |
31 | : selectedItemChanged(true) |
32 | , itemChanged(false) |
33 | {} |
34 | }; |
35 | |
36 | class Q_GRAPHS_EXPORT QQuickGraphsScatter : public QQuickGraphsItem |
37 | { |
38 | Q_OBJECT |
39 | Q_PROPERTY(QValue3DAxis *axisX READ axisX WRITE setAxisX NOTIFY axisXChanged) |
40 | Q_PROPERTY(QValue3DAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged) |
41 | Q_PROPERTY(QValue3DAxis *axisZ READ axisZ WRITE setAxisZ NOTIFY axisZChanged) |
42 | Q_PROPERTY(QScatter3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged) |
43 | Q_PROPERTY(QQmlListProperty<QScatter3DSeries> seriesList READ seriesList CONSTANT) |
44 | Q_CLASSINFO("DefaultProperty" , "seriesList" ) |
45 | |
46 | QML_NAMED_ELEMENT(Scatter3D) |
47 | |
48 | public: |
49 | explicit QQuickGraphsScatter(QQuickItem *parent = 0); |
50 | ~QQuickGraphsScatter() override; |
51 | |
52 | struct ChangeItem |
53 | { |
54 | QScatter3DSeries *series; |
55 | qsizetype index; |
56 | }; |
57 | |
58 | void setAxisX(QValue3DAxis *axis); |
59 | QValue3DAxis *axisX() const; |
60 | void setAxisY(QValue3DAxis *axis); |
61 | QValue3DAxis *axisY() const; |
62 | void setAxisZ(QValue3DAxis *axis); |
63 | QValue3DAxis *axisZ() const; |
64 | |
65 | QQmlListProperty<QScatter3DSeries> seriesList(); |
66 | static void appendSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, QScatter3DSeries *series); |
67 | static qsizetype countSeriesFunc(QQmlListProperty<QScatter3DSeries> *list); |
68 | static QScatter3DSeries *atSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, qsizetype index); |
69 | static void clearSeriesFunc(QQmlListProperty<QScatter3DSeries> *list); |
70 | Q_INVOKABLE void clearSelection() override; |
71 | Q_INVOKABLE void addSeries(QScatter3DSeries *series); |
72 | Q_INVOKABLE void removeSeries(QScatter3DSeries *series); |
73 | QList<QScatter3DSeries *> scatterSeriesList(); |
74 | |
75 | QScatter3DSeries *selectedSeries() const; |
76 | void setSelectedItem(qsizetype index, QScatter3DSeries *series); |
77 | |
78 | static constexpr qsizetype invalidSelectionIndex() { return -1; } |
79 | void setSelectionMode(QtGraphs3D::SelectionFlags mode) override; |
80 | |
81 | bool hasSelectedItemChanged() const { return m_changeTracker.selectedItemChanged; } |
82 | void setSelectedItemChanged(bool changed) { m_changeTracker.selectedItemChanged = changed; } |
83 | bool hasItemChanged() const { return m_changeTracker.itemChanged; } |
84 | void setItemChanged(bool changed) { m_changeTracker.itemChanged = changed; } |
85 | |
86 | void handleAxisAutoAdjustRangeChangedInOrientation(QAbstract3DAxis::AxisOrientation orientation, |
87 | bool autoAdjust) override; |
88 | void handleAxisRangeChangedBySender(QObject *sender) override; |
89 | void adjustAxisRanges() override; |
90 | bool hasChangedSeriesList() const { return !m_changedSeriesList.empty(); } |
91 | bool isSeriesVisualsDirty() const { return m_isSeriesVisualsDirty; } |
92 | void setSeriesVisualsDirty() { m_isSeriesVisualsDirty = true; } |
93 | bool isDataDirty() const { return m_isDataDirty; } |
94 | |
95 | public Q_SLOTS: |
96 | void handleAxisXChanged(QAbstract3DAxis *axis) override; |
97 | void handleAxisYChanged(QAbstract3DAxis *axis) override; |
98 | void handleAxisZChanged(QAbstract3DAxis *axis) override; |
99 | void handleSeriesMeshChanged(); |
100 | void handleMeshSmoothChanged(bool enable); |
101 | |
102 | void handleArrayReset(); |
103 | void handleItemsAdded(qsizetype startIndex, qsizetype count); |
104 | void handleItemsChanged(qsizetype startIndex, qsizetype count); |
105 | void handleItemsRemoved(qsizetype startIndex, qsizetype count); |
106 | void handleItemsInserted(qsizetype startIndex, qsizetype count); |
107 | |
108 | Q_SIGNALS: |
109 | void axisXChanged(QValue3DAxis *axis); |
110 | void axisYChanged(QValue3DAxis *axis); |
111 | void axisZChanged(QValue3DAxis *axis); |
112 | void selectedSeriesChanged(QScatter3DSeries *series); |
113 | |
114 | protected: |
115 | void calculateSceneScalingFactors() override; |
116 | void componentComplete() override; |
117 | bool doPicking(QPointF position) override; |
118 | void updateShadowQuality(QtGraphs3D::ShadowQuality quality) override; |
119 | void updateLightStrength() override; |
120 | void startRecordingRemovesAndInserts() override; |
121 | |
122 | private: |
123 | Scatter3DChangeBitField m_changeTracker; |
124 | QList<ChangeItem> m_changedItems; |
125 | |
126 | struct InsertRemoveRecord |
127 | { |
128 | bool m_isInsert; |
129 | qsizetype m_startIndex; |
130 | qsizetype m_count; |
131 | QAbstract3DSeries *m_series; |
132 | |
133 | InsertRemoveRecord() |
134 | : m_isInsert(false) |
135 | , m_startIndex(0) |
136 | , m_count(0) |
137 | , m_series(0) |
138 | {} |
139 | |
140 | InsertRemoveRecord(bool isInsert, qsizetype startIndex, qsizetype count, QAbstract3DSeries *series) |
141 | : m_isInsert(isInsert) |
142 | , m_startIndex(startIndex) |
143 | , m_count(count) |
144 | , m_series(series) |
145 | {} |
146 | }; |
147 | |
148 | QList<InsertRemoveRecord> m_insertRemoveRecords; |
149 | bool m_recordInsertsAndRemoves; |
150 | |
151 | struct ScatterModel |
152 | { |
153 | QList<QQuick3DModel *> dataItems; |
154 | QQuick3DTexture *seriesTexture; |
155 | QQuick3DTexture *highlightTexture; |
156 | QScatter3DSeries *series; |
157 | |
158 | //Legacy optimiaztion material reference models |
159 | QQuick3DModel *baseRef = nullptr; |
160 | QQuick3DModel *selectionRef = nullptr; |
161 | // For instanced, i.e. Default optimization |
162 | ScatterInstancing *instancing = nullptr; |
163 | QQuick3DModel *instancingRootItem = nullptr; |
164 | QQuick3DModel *selectionIndicator = nullptr; |
165 | }; |
166 | |
167 | float m_maxItemSize = 0.0f; |
168 | |
169 | const float m_defaultMinSize = 0.01f; |
170 | const float m_defaultMaxSize = 0.1f; |
171 | const float m_itemScaler = 3.0f; |
172 | float m_pointScale = 0; |
173 | |
174 | const float m_indicatorScaleAdjustment = 1.1f; |
175 | const float m_rangeGradientYHelper = 0.5f; |
176 | |
177 | bool m_polarGraph = false; |
178 | |
179 | float m_selectedGradientPos = 0.0f; |
180 | qsizetype m_selectedItem = invalidSelectionIndex(); |
181 | QScatter3DSeries *m_selectedItemSeries = nullptr; // Points to the series for which the bar is |
182 | // selected in single series selection cases. |
183 | QQuick3DModel *m_selected = nullptr; |
184 | QQuick3DModel *m_previousSelected = nullptr; |
185 | |
186 | QList<ScatterModel *> m_scatterGraphs; |
187 | |
188 | bool m_optimizationChanged = false; |
189 | |
190 | void connectSeries(QScatter3DSeries *series); |
191 | void disconnectSeries(QScatter3DSeries *series); |
192 | qsizetype getItemIndex(QQuick3DModel *item); |
193 | QVector3D selectedItemPosition(); |
194 | |
195 | float m_dotSizedScale = 1.0f; |
196 | |
197 | void updateMaterialReference(ScatterModel *model); |
198 | void updateInstancedMaterialProperties(ScatterModel *graphModel, |
199 | const bool isHighlight = false, |
200 | QQuick3DTexture *seriesTexture = nullptr, |
201 | QQuick3DTexture *highlightTexture = nullptr, |
202 | const bool transparency = false); |
203 | void updateItemMaterial(QQuick3DModel *item, |
204 | bool useGradient, |
205 | bool rangeGradient, |
206 | bool usePoint, |
207 | const QString &materialName); |
208 | void updateMaterialProperties(QQuick3DModel *item, |
209 | QQuick3DTexture *texture, |
210 | QColor color = Qt::white, |
211 | const bool transparency = false); |
212 | QQuick3DTexture *createTexture(); |
213 | QQuick3DModel *createDataItemModel(QAbstract3DSeries::Mesh meshType); |
214 | QQuick3DNode *createSeriesRoot(); |
215 | QQuick3DModel *createDataItem(QAbstract3DSeries *series); |
216 | void removeDataItems(ScatterModel *graphModel, QtGraphs3D::OptimizationHint optimizationHint); |
217 | void fixMeshFileName(QString &fileName, QAbstract3DSeries *series); |
218 | QString getMeshFileName(QAbstract3DSeries *series); |
219 | |
220 | void deleteDataItem(QQuick3DModel *item); |
221 | void removeDataItems(QList<QQuick3DModel *> &items, qsizetype count); |
222 | void recreateDataItems(); |
223 | void recreateDataItems(const QList<ScatterModel *> &); |
224 | void addPointsToScatterModel(ScatterModel *graphModel, qsizetype count); |
225 | qsizetype sizeDifference(qsizetype size1, qsizetype size2); |
226 | void handleSeriesChanged(QList<QAbstract3DSeries *> changedSeries); |
227 | |
228 | QColor m_selectedSeriesColor; |
229 | bool selectedItemInSeries(const QScatter3DSeries *series); |
230 | |
231 | bool isDotPositionInAxisRange(QVector3D dotPos); |
232 | |
233 | QQmlComponent *createRepeaterDelegate(QAbstract3DSeries::Mesh MeshType); |
234 | float calculatePointScaleSize(); |
235 | void updatePointScaleSize(); |
236 | void calculatePolarXZ(const float posX, const float posZ, float &x, float &z) const; |
237 | |
238 | void generatePointsForScatterModel(ScatterModel *series); |
239 | void updateScatterGraphItemPositions(ScatterModel *graphModel); |
240 | void updateScatterGraphItemVisuals(ScatterModel *graphModel); |
241 | |
242 | QQuick3DModel *selected() const; |
243 | void setSelected(QQuick3DModel *newSelected); |
244 | void setSelected(QQuick3DModel *root, qsizetype index); |
245 | void clearSelectionModel(); |
246 | void clearAllSelectionInstanced(); |
247 | |
248 | void optimizationChanged(QtGraphs3D::OptimizationHint toOptimization); |
249 | |
250 | void updateGraph() override; |
251 | void synchData() override; |
252 | void handleOptimizationHintChange(QtGraphs3D::OptimizationHint hint) override; |
253 | |
254 | bool selectedItemInRange(const ScatterModel *graphModel); |
255 | |
256 | private slots: |
257 | void cameraRotationChanged(); |
258 | |
259 | friend class Q3DScatterWidgetItem; |
260 | }; |
261 | |
262 | QT_END_NAMESPACE |
263 | #endif // QQUICKGRAPHSSCATTER_P_H |
264 | |