1 | // Copyright (C) 2023 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | // |
5 | // W A R N I N G |
6 | // ------------- |
7 | // |
8 | // This file is not part of the QtGraphs API. It exists purely as an |
9 | // implementation detail. This header file may change from version to |
10 | // version without notice, or even be removed. |
11 | // |
12 | // We mean it. |
13 | |
14 | #ifndef QQUICKGRAPHSBARS_H |
15 | #define QQUICKGRAPHSBARS_H |
16 | |
17 | #include "qabstract3daxis.h" |
18 | #include "qbar3dseries.h" |
19 | #include "qquickgraphsitem_p.h" |
20 | #include <private/barinstancing_p.h> |
21 | |
22 | #include <QtQuick3D/private/qquick3dmaterial_p.h> |
23 | |
24 | QT_BEGIN_NAMESPACE |
25 | |
26 | class QCategory3DAxis; |
27 | |
28 | struct Bars3DChangeBitField |
29 | { |
30 | bool multiSeriesScalingChanged : 1; |
31 | bool barSpecsChanged : 1; |
32 | bool selectedBarChanged : 1; |
33 | bool rowsChanged : 1; |
34 | bool itemChanged : 1; |
35 | bool floorLevelChanged : 1; |
36 | bool barSeriesMarginChanged : 1; |
37 | |
38 | Bars3DChangeBitField() |
39 | : multiSeriesScalingChanged(true) |
40 | , barSpecsChanged(true) |
41 | , selectedBarChanged(true) |
42 | , rowsChanged(false) |
43 | , itemChanged(false) |
44 | , floorLevelChanged(false) |
45 | , barSeriesMarginChanged(false) |
46 | {} |
47 | }; |
48 | |
49 | class Q_GRAPHS_EXPORT QQuickGraphsBars : public QQuickGraphsItem |
50 | { |
51 | Q_OBJECT |
52 | Q_PROPERTY(QCategory3DAxis *rowAxis READ rowAxis WRITE setRowAxis NOTIFY rowAxisChanged) |
53 | Q_PROPERTY(QValue3DAxis *valueAxis READ valueAxis WRITE setValueAxis NOTIFY valueAxisChanged) |
54 | Q_PROPERTY( |
55 | QCategory3DAxis *columnAxis READ columnAxis WRITE setColumnAxis NOTIFY columnAxisChanged) |
56 | Q_PROPERTY(bool multiSeriesUniform READ isMultiSeriesUniform WRITE setMultiSeriesUniform NOTIFY |
57 | multiSeriesUniformChanged) |
58 | Q_PROPERTY(float barThickness READ barThickness WRITE setBarThickness NOTIFY barThicknessChanged) |
59 | Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing NOTIFY barSpacingChanged) |
60 | Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative NOTIFY |
61 | barSpacingRelativeChanged) |
62 | Q_PROPERTY(QSizeF barSeriesMargin READ barSeriesMargin WRITE setBarSeriesMargin NOTIFY |
63 | barSeriesMarginChanged) |
64 | Q_PROPERTY(QQmlListProperty<QBar3DSeries> seriesList READ seriesList CONSTANT) |
65 | Q_PROPERTY(QBar3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged) |
66 | Q_PROPERTY(QBar3DSeries *primarySeries READ primarySeries WRITE setPrimarySeries NOTIFY |
67 | primarySeriesChanged) |
68 | Q_PROPERTY(float floorLevel READ floorLevel WRITE setFloorLevel NOTIFY floorLevelChanged) |
69 | Q_CLASSINFO("DefaultProperty" , "seriesList" ) |
70 | |
71 | QML_NAMED_ELEMENT(Bars3D) |
72 | |
73 | public: |
74 | explicit QQuickGraphsBars(QQuickItem *parent = 0); |
75 | ~QQuickGraphsBars() override; |
76 | |
77 | struct ChangeItem |
78 | { |
79 | QBar3DSeries *series; |
80 | QPoint point; |
81 | }; |
82 | struct ChangeRow |
83 | { |
84 | QBar3DSeries *series; |
85 | qsizetype row; |
86 | }; |
87 | |
88 | QCategory3DAxis *rowAxis() const; |
89 | void setRowAxis(QCategory3DAxis *axis); |
90 | QValue3DAxis *valueAxis() const; |
91 | void setValueAxis(QValue3DAxis *axis); |
92 | QCategory3DAxis *columnAxis() const; |
93 | void setColumnAxis(QCategory3DAxis *axis); |
94 | |
95 | void setMultiSeriesUniform(bool uniform); |
96 | bool isMultiSeriesUniform() const; |
97 | |
98 | void setBarThickness(float thicknessRatio); |
99 | float barThickness() const; |
100 | |
101 | void setBarSpacing(QSizeF spacing); |
102 | QSizeF barSpacing() const; |
103 | |
104 | void setBarSpacingRelative(bool relative); |
105 | bool isBarSpacingRelative() const; |
106 | |
107 | void setBarSeriesMargin(QSizeF margin); |
108 | QSizeF barSeriesMargin() const; |
109 | |
110 | void setMultiSeriesScaling(bool uniform); |
111 | bool multiSeriesScaling() const; |
112 | |
113 | void setBarSpecs(float thicknessRatio = 1.0f, |
114 | QSizeF spacing = QSizeF(1.0, 1.0), |
115 | bool relative = true); |
116 | |
117 | void setFloorLevel(float level); |
118 | float floorLevel() const; |
119 | |
120 | QQmlListProperty<QBar3DSeries> seriesList(); |
121 | static void appendSeriesFunc(QQmlListProperty<QBar3DSeries> *list, QBar3DSeries *series); |
122 | static qsizetype countSeriesFunc(QQmlListProperty<QBar3DSeries> *list); |
123 | static QBar3DSeries *atSeriesFunc(QQmlListProperty<QBar3DSeries> *list, qsizetype index); |
124 | static void clearSeriesFunc(QQmlListProperty<QBar3DSeries> *list); |
125 | Q_INVOKABLE void addSeries(QBar3DSeries *series); |
126 | Q_INVOKABLE void removeSeries(QBar3DSeries *series); |
127 | Q_INVOKABLE void insertSeries(qsizetype index, QBar3DSeries *series); |
128 | Q_INVOKABLE void clearSelection() override; |
129 | |
130 | void setPrimarySeries(QBar3DSeries *series); |
131 | QBar3DSeries *primarySeries() const; |
132 | QBar3DSeries *selectedSeries() const; |
133 | static QPoint invalidSelectionPosition() { return QPoint(-1, -1); } |
134 | void setSelectionMode(QtGraphs3D::SelectionFlags mode) override; |
135 | |
136 | void handleAxisAutoAdjustRangeChangedInOrientation(QAbstract3DAxis::AxisOrientation orientation, |
137 | bool autoAdjust) override; |
138 | void handleSeriesVisibilityChangedBySender(QObject *sender) override; |
139 | |
140 | void handleAxisRangeChangedBySender(QObject *sender) override; |
141 | void adjustAxisRanges() override; |
142 | |
143 | void setSelectedBar(QPoint coord, QBar3DSeries *series, bool enterSlice); |
144 | |
145 | QList<QBar3DSeries *> barSeriesList(); |
146 | |
147 | bool isSeriesVisualsDirty() const { return m_isSeriesVisualsDirty; } |
148 | void setSeriesVisualsDirty(bool dirty) { m_isSeriesVisualsDirty = dirty; } |
149 | bool isDataDirty() const { return m_isDataDirty; } |
150 | void setDataDirty(bool dirty) { m_isDataDirty = dirty; } |
151 | |
152 | protected: |
153 | void componentComplete() override; |
154 | void synchData() override; |
155 | void updateParameters(); |
156 | void updateFloorLevel(float level); |
157 | void updateGraph() override; |
158 | void updateAxisRange(float min, float max) override; |
159 | void updateAxisReversed(bool enable) override; |
160 | void updateLightStrength() override; |
161 | void calculateSceneScalingFactors() override; |
162 | QVector3D calculateCategoryLabelPosition(QAbstract3DAxis *axis, |
163 | QVector3D labelPosition, |
164 | int index) override; |
165 | float calculateCategoryGridLinePosition(QAbstract3DAxis *axis, int index) override; |
166 | void createSliceView() override; |
167 | void toggleSliceGraph() override; |
168 | void handleLabelCountChanged(QQuick3DRepeater *repeater, QColor axisLabelColor) override; |
169 | void updateSelectionMode(QtGraphs3D::SelectionFlags mode) override; |
170 | bool doPicking(QPointF position) override; |
171 | QAbstract3DAxis *createDefaultAxis(QAbstract3DAxis::AxisOrientation orientation) override; |
172 | void updateSliceItemLabel(const QString &label, QVector3D position) override; |
173 | |
174 | public Q_SLOTS: |
175 | void handleAxisXChanged(QAbstract3DAxis *axis) override; |
176 | void handleAxisYChanged(QAbstract3DAxis *axis) override; |
177 | void handleAxisZChanged(QAbstract3DAxis *axis) override; |
178 | void handleSeriesMeshChanged(QAbstract3DSeries::Mesh mesh); |
179 | void handleMeshSmoothChanged(bool enable); |
180 | void handleCameraRotationChanged(); |
181 | void handleArrayReset(); |
182 | void handleRowsAdded(qsizetype startIndex, qsizetype count); |
183 | void handleRowsChanged(qsizetype startIndex, qsizetype count); |
184 | void handleRowsRemoved(qsizetype startIndex, qsizetype count); |
185 | void handleRowsInserted(qsizetype startIndex, qsizetype count); |
186 | void handleItemChanged(qsizetype rowIndex, qsizetype columnIndex); |
187 | void handleDataRowLabelsChanged(); |
188 | void handleDataColumnLabelsChanged(); |
189 | void handleRowColorsChanged(); |
190 | |
191 | Q_SIGNALS: |
192 | void rowAxisChanged(QCategory3DAxis *axis); |
193 | void valueAxisChanged(QValue3DAxis *axis); |
194 | void columnAxisChanged(QCategory3DAxis *axis); |
195 | void multiSeriesUniformChanged(bool uniform); |
196 | void barThicknessChanged(float thicknessRatio); |
197 | void barSpacingChanged(QSizeF spacing); |
198 | void barSpacingRelativeChanged(bool relative); |
199 | void barSeriesMarginChanged(QSizeF margin); |
200 | void meshFileNameChanged(const QString &filename); |
201 | void primarySeriesChanged(QBar3DSeries *series); |
202 | void selectedSeriesChanged(QBar3DSeries *series); |
203 | void floorLevelChanged(float level); |
204 | |
205 | private: |
206 | Bars3DChangeBitField m_changeTracker; |
207 | QList<ChangeItem> m_changedItems; |
208 | QList<ChangeRow> m_changedRows; |
209 | |
210 | QBar3DSeries *m_primarySeries = nullptr; |
211 | |
212 | bool m_isMultiSeriesUniform = false; |
213 | bool m_isBarSpecRelative = true; |
214 | float m_barThicknessRatio = 1.0f; |
215 | QSizeF m_barSpacing = QSizeF(1.0f, 1.0f); |
216 | float m_floorLevel = 0.0f; |
217 | QSizeF m_barSeriesMargin = QSizeF(0.0f, 0.0f); |
218 | |
219 | qsizetype m_cachedRowCount = 0; |
220 | qsizetype m_cachedColumnCount = 0; |
221 | qsizetype m_minRow = 0; |
222 | qsizetype m_maxRow = 0; |
223 | qsizetype m_minCol = 0; |
224 | qsizetype m_maxCol = 0; |
225 | qsizetype m_newRows = 0; |
226 | qsizetype m_newCols = 0; |
227 | |
228 | float m_maxSceneSize = 40.f; |
229 | float m_rowWidth = 0.0f; |
230 | float m_columnDepth = 0.0f; |
231 | float m_maxDimension = 0.0f; |
232 | float m_scaleFactor = 0.0f; |
233 | float m_xScaleFactor = 1.f; |
234 | float m_zScaleFactor = 1.f; |
235 | |
236 | QSizeF m_cachedBarSeriesMargin = QSizeF(0.0f, 0.0f); |
237 | QSizeF m_cachedBarThickness = QSizeF(1.0f, 1.0f); |
238 | QSizeF m_cachedBarSpacing = QSizeF(1.0f, 1.0f); |
239 | |
240 | float m_xScale = scale().x(); |
241 | float m_yScale = scale().y(); |
242 | float m_zScale = scale().z(); |
243 | |
244 | float m_requestedMargin = -1.0f; |
245 | float m_vBackgroundMargin = 0.1f; |
246 | float m_hBackgroundMargin = 0.1f; |
247 | |
248 | bool m_hasNegativeValues = false; |
249 | bool m_noZeroInRange = false; |
250 | float m_actualFloorLevel = 0.0f; |
251 | float m_heightNormalizer = 1.0f; |
252 | float m_backgroundAdjustment = 0.0f; |
253 | |
254 | bool m_axisRangeChanged = false; |
255 | |
256 | QQuick3DModel *m_floorBackground = nullptr; |
257 | QQuick3DNode *m_floorBackgroundScale = nullptr; |
258 | QQuick3DNode *m_floorBackgroundRotation = nullptr; |
259 | |
260 | QBar3DSeries *m_selectedBarSeries = nullptr; |
261 | QPoint m_selectedBar = invalidSelectionPosition(); // Points to row & column in data window. |
262 | QVector3D m_selectedBarPos = QVector3D(0.0f, 0.0f, 0.0f); |
263 | |
264 | struct BarModel |
265 | { |
266 | QQuick3DModel *model = nullptr; |
267 | QBarDataItem *barItem; |
268 | QPoint coord; |
269 | int visualIndex; |
270 | float heightValue; |
271 | QQuick3DTexture *texture; |
272 | BarInstancing *instancing = nullptr; |
273 | BarInstancing *selectionInstancing = nullptr; |
274 | QQuick3DModel *selectedModel = nullptr; |
275 | BarInstancing *multiSelectionInstancing = nullptr; |
276 | QQuick3DModel *multiSelectedModel = nullptr; |
277 | }; |
278 | |
279 | QHash<QBar3DSeries *, QList<BarModel *> *> m_barModelsMap; |
280 | QAbstract3DSeries::Mesh m_meshType = QAbstract3DSeries::Mesh::Sphere; |
281 | bool m_smooth = false; |
282 | bool m_keepSeriesUniform = false; |
283 | bool m_hasHighlightTexture = false; |
284 | float m_seriesScaleX = 0.0f; |
285 | float m_seriesScaleZ = 0.0f; |
286 | float m_seriesStep = 0.0f; |
287 | float m_seriesStart = 0.0f; |
288 | float m_zeroPosition = 0.0f; |
289 | int m_visibleSeriesCount = 0; |
290 | QQuick3DTexture *m_highlightTexture = nullptr; |
291 | QQuick3DTexture *m_multiHighlightTexture = nullptr; |
292 | QHash<QBar3DSeries *, QList<BarModel *>> m_slicedBarModels; |
293 | bool m_selectionDirty = false; |
294 | |
295 | void calculateHeightAdjustment(); |
296 | void calculateSeriesStartPosition(); |
297 | void connectSeries(QBar3DSeries *series); |
298 | void disconnectSeries(QBar3DSeries *series); |
299 | void generateBars(QList<QBar3DSeries *> &barSeriesList); |
300 | QQuick3DModel *createDataItem(QQuick3DNode *scene, QAbstract3DSeries *series); |
301 | QString getMeshFileName(); |
302 | void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh meshType); |
303 | void updateBarVisuality(QBar3DSeries *series, int visualIndex); |
304 | void updateBarPositions(QBar3DSeries *series); |
305 | float updateBarHeightParameters(const QBarDataItem *item); |
306 | void updateBarVisuals(QBar3DSeries *series); |
307 | void updateItemMaterial(QQuick3DModel *item, |
308 | bool useGradient, |
309 | bool rangeGradient, |
310 | const QString &materialName); |
311 | void updateMaterialProperties(QQuick3DModel *item, |
312 | const bool isHighlight, |
313 | const bool isMultiHighlight, |
314 | QQuick3DTexture *texture, |
315 | QColor color, |
316 | const bool transparency = false); |
317 | void removeBarModels(); |
318 | void deleteBarModels(QQuick3DModel *model); |
319 | void deleteBarItemHolders(BarInstancing *instancing); |
320 | QQuick3DTexture *createTexture(); |
321 | void updateSelectedBar(); |
322 | QQuickGraphsItem::SelectionType isSelected(int row, int bar, QBar3DSeries *series); |
323 | void resetClickedStatus(); |
324 | void removeSlicedBarModels(); |
325 | void createBarItemHolders(QBar3DSeries *series, QList<BarModel *> barList, bool slice); |
326 | |
327 | void updateBarSpecs(float thicknessRatio, QSizeF spacing, bool relative); |
328 | void updateBarSeriesMargin(QSizeF margin); |
329 | |
330 | void adjustSelectionPosition(QPoint &pos, const QBar3DSeries *series); |
331 | |
332 | friend class Q3DBarsWidgetItem; |
333 | }; |
334 | |
335 | QT_END_NAMESPACE |
336 | #endif // QQUICKGRAPHSBARS_H |
337 | |