1 | // Copyright (C) 2023 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "qabstract3dgraph.h" |
5 | #include "q3dscene_p.h" |
6 | #include "qquickgraphsitem_p.h" |
7 | #ifdef Q_OS_DARWIN |
8 | #include <QtQuick3D/qquick3d.h> |
9 | #endif |
10 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | /*! |
14 | * \class QAbstract3DGraph |
15 | * \inmodule QtGraphs |
16 | * \brief The QAbstract3DGraph class provides a window and render loop for graphs. |
17 | * |
18 | * This class subclasses a QWindow and provides render loop for graphs inheriting it. |
19 | * |
20 | * You should not need to use this class directly, but one of its subclasses instead. |
21 | * |
22 | * Anti-aliasing is turned on by default on C++, except in OpenGL ES2 |
23 | * environments, where anti-aliasing is not supported by Qt Graphs. |
24 | * To specify non-default anti-aliasing for a graph, give a custom surface format as |
25 | * a constructor parameter. You can use the convenience function \c qDefaultSurfaceFormat() |
26 | * to create the surface format object. |
27 | * |
28 | * \note QAbstract3DGraph sets window flag \c Qt::FramelessWindowHint on by default. If you want to display |
29 | * graph windows as standalone windows with regular window frame, clear this flag after constructing |
30 | * the graph. For example: |
31 | * |
32 | * \code |
33 | * Q3DBars *graphWindow = new Q3DBars; |
34 | * graphWindow->setFlags(graphWindow->flags() ^ Qt::FramelessWindowHint); |
35 | * \endcode |
36 | * |
37 | * \sa Q3DBars, Q3DScatter, Q3DSurface, {Qt Graphs C++ Classes} |
38 | */ |
39 | |
40 | /*! |
41 | \enum QAbstract3DGraph::SelectionFlag |
42 | |
43 | Item selection modes. Values of this enumeration can be combined with OR operator. |
44 | |
45 | \value SelectionNone |
46 | Selection mode disabled. |
47 | \value SelectionItem |
48 | Selection highlights a single item. |
49 | \value SelectionRow |
50 | Selection highlights a single row. |
51 | \value SelectionItemAndRow |
52 | Combination flag for highlighting both item and row with different colors. |
53 | \value SelectionColumn |
54 | Selection highlights a single column. |
55 | \value SelectionItemAndColumn |
56 | Combination flag for highlighting both item and column with different colors. |
57 | \value SelectionRowAndColumn |
58 | Combination flag for highlighting both row and column. |
59 | \value SelectionItemRowAndColumn |
60 | Combination flag for highlighting item, row, and column. |
61 | \value SelectionSlice |
62 | Setting this mode flag indicates that the graph should take care of the slice view handling |
63 | automatically. If you wish to control the slice view yourself via Q3DScene, do not set this |
64 | flag. When setting this mode flag, either \c SelectionRow or \c SelectionColumn must also |
65 | be set, but not both. Slicing is supported by Q3DBars and Q3DSurface only. |
66 | When this flag is set, slice mode is entered in the following situations: |
67 | \list |
68 | \li When selection is changed explicitly via series API to a visible item |
69 | \li When selection is changed by clicking on the graph |
70 | \li When the selection mode changes and the selected item is visible |
71 | \endlist |
72 | \value SelectionMultiSeries |
73 | Setting this mode means that items for all series at same position are highlighted, instead |
74 | of just the selected item. The actual selection in the other series doesn't change. |
75 | When setting this mode flag, one or more of the basic selection flags (\c {SelectionItem}, |
76 | \c {SelectionRow}, or \c SelectionColumn) must also be set. |
77 | Multi-series selection is not supported for Q3DScatter. |
78 | */ |
79 | |
80 | /*! |
81 | \enum QAbstract3DGraph::ShadowQuality |
82 | |
83 | Quality of shadows. |
84 | |
85 | \value ShadowQualityNone |
86 | Shadows are disabled. |
87 | \value ShadowQualityLow |
88 | Shadows are rendered in low quality. |
89 | \value ShadowQualityMedium |
90 | Shadows are rendered in medium quality. |
91 | \value ShadowQualityHigh |
92 | Shadows are rendered in high quality. |
93 | \value ShadowQualitySoftLow |
94 | Shadows are rendered in low quality with softened edges. |
95 | \value ShadowQualitySoftMedium |
96 | Shadows are rendered in medium quality with softened edges. |
97 | \value ShadowQualitySoftHigh |
98 | Shadows are rendered in high quality with softened edges. |
99 | */ |
100 | |
101 | /*! |
102 | \enum QAbstract3DGraph::ElementType |
103 | |
104 | Type of an element in the graph. |
105 | |
106 | \value ElementNone |
107 | No defined element. |
108 | \value ElementSeries |
109 | An item in a series. |
110 | \value ElementAxisXLabel |
111 | The x-axis label. |
112 | \value ElementAxisYLabel |
113 | The y-axis label. |
114 | \value ElementAxisZLabel |
115 | The z-axis label. |
116 | \value ElementCustomItem |
117 | A custom item. |
118 | */ |
119 | |
120 | /*! |
121 | \enum QAbstract3DGraph::OptimizationHint |
122 | |
123 | The optimization hint for rendering. |
124 | |
125 | \value OptimizationDefault |
126 | Provides the full feature set with instancing at a good performance. |
127 | \value OptimizationStatic |
128 | Optimizes the rendering of static data sets at the expense of some features. |
129 | Usable only with Q3DScatter graphs. |
130 | \value OptimizationLegacy |
131 | Provides the full feature set at a reasonable performance. To be used if |
132 | OptimizationDefault performs poorly or does not work. |
133 | */ |
134 | |
135 | /*! |
136 | * \internal |
137 | */ |
138 | QAbstract3DGraph::QAbstract3DGraph() |
139 | { |
140 | #ifdef Q_OS_DARWIN |
141 | // Take care of widget users (or CI) wanting to use OpenGL backend on macOS |
142 | if (QQuickWindow::graphicsApi() == QSGRendererInterface::OpenGL) |
143 | QSurfaceFormat::setDefaultFormat(QQuick3D::idealSurfaceFormat(4)); |
144 | #endif |
145 | } |
146 | |
147 | /*! |
148 | * Destroys QAbstract3DGraph. |
149 | */ |
150 | QAbstract3DGraph::~QAbstract3DGraph() |
151 | { |
152 | } |
153 | |
154 | /*! |
155 | * Adds the given \a inputHandler to the graph. The input handlers added via addInputHandler |
156 | * are not taken in to use directly. Only the ownership of the \a inputHandler is given to the graph. |
157 | * The \a inputHandler must not be null or already added to another graph. |
158 | * |
159 | * \sa releaseInputHandler(), setActiveInputHandler() |
160 | */ |
161 | void QAbstract3DGraph::addInputHandler(QAbstract3DInputHandler *inputHandler) |
162 | { |
163 | m_graphsItem->addInputHandler(inputHandler); |
164 | } |
165 | |
166 | /*! |
167 | * Releases the ownership of the \a inputHandler back to the caller, if it was added to this graph. |
168 | * If the released \a inputHandler is in use there will be no input handler active after this call. |
169 | * |
170 | * If the default input handler is released and added back later, it behaves as any other input handler would. |
171 | * |
172 | * \sa addInputHandler(), setActiveInputHandler() |
173 | */ |
174 | void QAbstract3DGraph::releaseInputHandler(QAbstract3DInputHandler *inputHandler) |
175 | { |
176 | m_graphsItem->releaseInputHandler(inputHandler); |
177 | } |
178 | |
179 | /*! |
180 | * \property QAbstract3DGraph::activeInputHandler |
181 | * |
182 | * \brief The active input handler used in the graph. |
183 | */ |
184 | |
185 | /*! |
186 | * Sets \a inputHandler as the active input handler used in the graph. |
187 | * Implicitly calls addInputHandler() to transfer ownership of \a inputHandler |
188 | * to this graph. |
189 | * |
190 | * If \a inputHandler is null, no input handler will be active after this call. |
191 | * |
192 | * \sa addInputHandler(), releaseInputHandler() |
193 | */ |
194 | void QAbstract3DGraph::setActiveInputHandler(QAbstract3DInputHandler *inputHandler) |
195 | { |
196 | m_graphsItem->setActiveInputHandler(inputHandler); |
197 | } |
198 | |
199 | QAbstract3DInputHandler *QAbstract3DGraph::activeInputHandler() const |
200 | { |
201 | return m_graphsItem->activeInputHandler(); |
202 | } |
203 | |
204 | /*! |
205 | * Returns the list of all added input handlers. |
206 | * |
207 | * \sa addInputHandler() |
208 | */ |
209 | QList<QAbstract3DInputHandler *> QAbstract3DGraph::inputHandlers() const |
210 | { |
211 | return m_graphsItem->inputHandlers(); |
212 | } |
213 | |
214 | /*! |
215 | * Adds the given \a theme to the graph. The themes added via addTheme are not taken in to use |
216 | * directly. Only the ownership of the theme is given to the graph. |
217 | * The \a theme must not be null or already added to another graph. |
218 | * |
219 | * \sa releaseTheme(), setActiveTheme() |
220 | */ |
221 | void QAbstract3DGraph::addTheme(Q3DTheme *theme) |
222 | { |
223 | m_graphsItem->addTheme(theme); |
224 | } |
225 | |
226 | /*! |
227 | * Releases the ownership of the \a theme back to the caller, if it was added to this graph. |
228 | * If the released \a theme is in use, a new default theme will be created and set active. |
229 | * |
230 | * If the default theme is released and added back later, it behaves as any other theme would. |
231 | * |
232 | * \sa addTheme(), setActiveTheme() |
233 | */ |
234 | void QAbstract3DGraph::releaseTheme(Q3DTheme *theme) |
235 | { |
236 | m_graphsItem->releaseTheme(theme); |
237 | } |
238 | |
239 | /*! |
240 | * \property QAbstract3DGraph::activeTheme |
241 | * |
242 | * \brief The active theme of the graph. |
243 | * |
244 | * Sets \a activeTheme as the active theme to be used for the graph. Implicitly calls |
245 | * addTheme() to transfer the ownership of the theme to this graph. |
246 | * |
247 | * If \a activeTheme is null, a temporary default theme is created. This temporary theme is destroyed |
248 | * if any theme is explicitly set later. |
249 | * Properties of the theme can be modified even after setting it, and the modifications take |
250 | * effect immediately. |
251 | */ |
252 | Q3DTheme *QAbstract3DGraph::activeTheme() const |
253 | { |
254 | return m_graphsItem->theme(); |
255 | } |
256 | |
257 | void QAbstract3DGraph::setActiveTheme(Q3DTheme *activeTheme) |
258 | { |
259 | m_graphsItem->setTheme(activeTheme); |
260 | emit activeThemeChanged(activeTheme); |
261 | } |
262 | |
263 | /*! |
264 | * Returns the list of all added themes. |
265 | * |
266 | * \sa addTheme() |
267 | */ |
268 | QList<Q3DTheme *> QAbstract3DGraph::themes() const |
269 | { |
270 | return m_graphsItem->themes(); |
271 | } |
272 | |
273 | /*! |
274 | * \property QAbstract3DGraph::selectionMode |
275 | * |
276 | * \brief Item selection mode. |
277 | * |
278 | * A combination of SelectionFlags. By default, \c SelectionItem. |
279 | * Different graph types support different selection modes. |
280 | * |
281 | * \sa SelectionFlags |
282 | */ |
283 | QAbstract3DGraph::SelectionFlags QAbstract3DGraph::selectionMode() const |
284 | { |
285 | return m_graphsItem->selectionMode(); |
286 | } |
287 | |
288 | void QAbstract3DGraph::setSelectionMode(const QAbstract3DGraph::SelectionFlags &selectionMode) |
289 | { |
290 | m_graphsItem->setSelectionMode(selectionMode); |
291 | emit selectionModeChanged(selectionMode); |
292 | } |
293 | |
294 | /*! |
295 | * \property QAbstract3DGraph::shadowQuality |
296 | * |
297 | * \brief The quality of the shadow. |
298 | * |
299 | * One of the ShadowQuality enum values. By default, \c ShadowQualityMedium. |
300 | * |
301 | * \note If setting the shadow quality to a certain level fails, the level is lowered |
302 | * until it is successfully set. The \c shadowQualityChanged signal is emitted each time |
303 | * a change is made. |
304 | * |
305 | * \sa ShadowQuality |
306 | */ |
307 | QAbstract3DGraph::ShadowQuality QAbstract3DGraph::shadowQuality() const |
308 | { |
309 | return m_graphsItem->shadowQuality(); |
310 | } |
311 | |
312 | void QAbstract3DGraph::setShadowQuality(const QAbstract3DGraph::ShadowQuality &shadowQuality) |
313 | { |
314 | m_graphsItem->setShadowQuality(shadowQuality); |
315 | emit shadowQualityChanged(quality: shadowQuality); |
316 | } |
317 | |
318 | /*! |
319 | * \property QAbstract3DGraph::scene |
320 | * |
321 | * \brief The Q3DScene pointer that can be used to manipulate the scene and |
322 | * access the scene elements, such as the active camera. |
323 | * |
324 | * This property is read-only. |
325 | */ |
326 | Q3DScene *QAbstract3DGraph::scene() const |
327 | { |
328 | return (Q3DScene *)m_graphsItem->scene(); |
329 | } |
330 | |
331 | /*! |
332 | * Clears selection from all attached series. |
333 | */ |
334 | void QAbstract3DGraph::clearSelection() |
335 | { |
336 | m_graphsItem->clearSelection(); |
337 | } |
338 | |
339 | /*! |
340 | * Returns whether the \a series has already been added to the graph. |
341 | */ |
342 | bool QAbstract3DGraph::hasSeries(QAbstract3DSeries *series) const |
343 | { |
344 | return m_graphsItem->hasSeries(series); |
345 | } |
346 | |
347 | /*! |
348 | * Adds a QCustom3DItem \a item to the graph. Graph takes ownership of the added item. |
349 | * |
350 | * Returns the index to the added item if the add operation was successful, -1 |
351 | * if trying to add a null item, and the index of the item if trying to add an |
352 | * already added item. |
353 | * |
354 | * Items are rendered in the order they have been inserted. The rendering order needs to |
355 | * be taken into account when having solid and transparent items. |
356 | * |
357 | * \sa removeCustomItems(), removeCustomItem(), removeCustomItemAt(), customItems() |
358 | */ |
359 | int QAbstract3DGraph::addCustomItem(QCustom3DItem *item) |
360 | { |
361 | return m_graphsItem->addCustomItem(item); |
362 | } |
363 | |
364 | /*! |
365 | * Removes all custom items. Deletes the resources allocated to them. |
366 | */ |
367 | void QAbstract3DGraph::removeCustomItems() |
368 | { |
369 | m_graphsItem->removeCustomItems(); |
370 | } |
371 | |
372 | /*! |
373 | * Removes the custom \a {item}. Deletes the resources allocated to it. |
374 | */ |
375 | void QAbstract3DGraph::removeCustomItem(QCustom3DItem *item) |
376 | { |
377 | m_graphsItem->removeCustomItem(item); |
378 | } |
379 | |
380 | /*! |
381 | * Removes all custom items at \a {position}. Deletes the resources allocated to them. |
382 | */ |
383 | void QAbstract3DGraph::removeCustomItemAt(const QVector3D &position) |
384 | { |
385 | m_graphsItem->removeCustomItemAt(position); |
386 | } |
387 | |
388 | /*! |
389 | * Gets ownership of given \a item back and removes the \a item from the graph. |
390 | * |
391 | * \note If the same item is added back to the graph, the texture or the texture file needs to be |
392 | * re-set. |
393 | * |
394 | * \sa QCustom3DItem::setTextureImage(), QCustom3DItem::setTextureFile() |
395 | */ |
396 | void QAbstract3DGraph::releaseCustomItem(QCustom3DItem *item) |
397 | { |
398 | return m_graphsItem->releaseCustomItem(item); |
399 | } |
400 | |
401 | /*! |
402 | * Returns the list of all added custom items. |
403 | * \sa addCustomItem() |
404 | */ |
405 | QList<QCustom3DItem *> QAbstract3DGraph::customItems() const |
406 | { |
407 | // TODO: API missing in QQuickGraphsItem (QTBUG-99844) |
408 | return {}; |
409 | // return m_graphsItem->customItems(); |
410 | } |
411 | |
412 | /*! |
413 | * Can be used to query the index of the selected label after receiving \c selectedElementChanged |
414 | * signal with any label type. Selection is valid until the next \c selectedElementChanged signal. |
415 | * |
416 | * Returns the index of the selected label, or -1. |
417 | * |
418 | * \sa selectedElement |
419 | */ |
420 | int QAbstract3DGraph::selectedLabelIndex() const |
421 | { |
422 | return m_graphsItem->selectedLabelIndex(); |
423 | } |
424 | |
425 | /*! |
426 | * Can be used to get the selected axis after receiving \c selectedElementChanged signal with any label |
427 | * type. Selection is valid until the next \c selectedElementChanged signal. |
428 | * |
429 | * Returns the pointer to the selected axis, or null. |
430 | * |
431 | * \sa selectedElement |
432 | */ |
433 | QAbstract3DAxis *QAbstract3DGraph::selectedAxis() const |
434 | { |
435 | return m_graphsItem->selectedAxis(); |
436 | } |
437 | |
438 | /*! |
439 | * Can be used to query the index of the selected custom item after receiving \c selectedElementChanged |
440 | * signal with QAbstract3DGraph::ElementCustomItem type. Selection is valid until the next |
441 | * \c selectedElementChanged signal. |
442 | * |
443 | * Returns the index of the selected custom item, or -1. |
444 | * |
445 | * \sa selectedElement |
446 | */ |
447 | int QAbstract3DGraph::selectedCustomItemIndex() const |
448 | { |
449 | return m_graphsItem->selectedCustomItemIndex(); |
450 | } |
451 | |
452 | /*! |
453 | * Can be used to get the selected custom item after receiving \c selectedElementChanged signal with |
454 | * QAbstract3DGraph::ElementCustomItem type. Ownership of the item remains with the graph. |
455 | * Selection is valid until the next \c selectedElementChanged signal. |
456 | * |
457 | * Returns the pointer to the selected custom item, or null. |
458 | * |
459 | * \sa selectedElement |
460 | */ |
461 | QCustom3DItem *QAbstract3DGraph::selectedCustomItem() const |
462 | { |
463 | return m_graphsItem->selectedCustomItem(); |
464 | } |
465 | |
466 | /*! |
467 | * \property QAbstract3DGraph::selectedElement |
468 | * |
469 | * \brief The element selected in the graph. |
470 | * |
471 | * This property can be used to query the selected element type. The type is |
472 | * valid until a new selection is made in the graph and the |
473 | * \c selectedElementChanged signal is emitted. |
474 | * |
475 | * The signal can be used for example for implementing custom input handlers, as |
476 | * demonstrated in the \l {Graph Gallery} example under \uicontrol {Scatter Graph} tab. |
477 | * |
478 | * \sa selectedLabelIndex(), selectedAxis(), selectedCustomItemIndex(), selectedCustomItem(), |
479 | * Q3DBars::selectedSeries(), Q3DScatter::selectedSeries(), Q3DSurface::selectedSeries(), |
480 | * Q3DScene::setSelectionQueryPosition() |
481 | */ |
482 | QAbstract3DGraph::ElementType QAbstract3DGraph::selectedElement() const |
483 | { |
484 | return m_graphsItem->selectedElement(); |
485 | } |
486 | |
487 | /*! |
488 | * Renders current frame to an image of \a imageSize. Default size is the window size. Image is |
489 | * rendered with antialiasing level given in \a msaaSamples. Default level is \c{0}. |
490 | * |
491 | * Returns the rendered image. |
492 | * |
493 | * \note OpenGL ES2 does not support anitialiasing, so \a msaaSamples is always forced to \c{0}. |
494 | */ |
495 | QImage QAbstract3DGraph::renderToImage(int msaaSamples, const QSize &imageSize) |
496 | { |
497 | // TODO: API missing in QQuickGraphsItem (QTBUG-111712) |
498 | Q_UNUSED(msaaSamples) |
499 | QSize renderSize = imageSize; |
500 | if (renderSize.isEmpty()) |
501 | renderSize = size(); |
502 | // TODO: API missing in QQuickGraphsItem (QTBUG-111712) |
503 | return {};//m_graphsItem->renderToImage(msaaSamples, renderSize); |
504 | } |
505 | |
506 | /*! |
507 | * \property QAbstract3DGraph::measureFps |
508 | * |
509 | * \brief Whether rendering is done continuously instead of on demand. |
510 | * |
511 | * If \c {true}, rendering is continuous and the value of the currentFps |
512 | * property is updated. Defaults to \c{false}. |
513 | * |
514 | * \sa currentFps |
515 | */ |
516 | void QAbstract3DGraph::setMeasureFps(bool enable) |
517 | { |
518 | m_graphsItem->setMeasureFps(enable); |
519 | if (enable) { |
520 | QObject::connect(sender: m_graphsItem.data(), signal: &QQuickGraphsItem::currentFpsChanged, |
521 | context: this, slot: &QAbstract3DGraph::currentFpsChanged); |
522 | } else { |
523 | QObject::disconnect(sender: m_graphsItem.data(), signal: &QQuickGraphsItem::currentFpsChanged, |
524 | receiver: this, slot: &QAbstract3DGraph::currentFpsChanged); |
525 | } |
526 | } |
527 | |
528 | bool QAbstract3DGraph::measureFps() const |
529 | { |
530 | return m_graphsItem->measureFps(); |
531 | } |
532 | |
533 | /*! |
534 | * \property QAbstract3DGraph::currentFps |
535 | * |
536 | * \brief The rendering results for the last second. |
537 | * |
538 | * The results are stored in this read-only property when FPS measuring is |
539 | * enabled. It takes at least a second before this value is updated after |
540 | * measuring is activated. |
541 | * |
542 | * \sa measureFps |
543 | */ |
544 | int QAbstract3DGraph::currentFps() const |
545 | { |
546 | return m_graphsItem->currentFps(); |
547 | } |
548 | |
549 | /*! |
550 | * \property QAbstract3DGraph::orthoProjection |
551 | * |
552 | * \brief Whether orthographic projection is used for displaying the graph. |
553 | * |
554 | * Defaults to \c{false}. |
555 | * \note Shadows will be disabled when set to \c{true}. |
556 | * |
557 | * \sa QAbstract3DAxis::labelAutoRotation, Q3DCamera::cameraPreset |
558 | */ |
559 | void QAbstract3DGraph::setOrthoProjection(bool enable) |
560 | { |
561 | m_graphsItem->setOrthoProjection(enable); |
562 | } |
563 | |
564 | bool QAbstract3DGraph::isOrthoProjection() const |
565 | { |
566 | return m_graphsItem->isOrthoProjection(); |
567 | } |
568 | |
569 | /*! |
570 | * \property QAbstract3DGraph::aspectRatio |
571 | * |
572 | * \brief The ratio of the graph scaling between the longest axis on the |
573 | * horizontal plane and the y-axis. |
574 | * |
575 | * Defaults to \c{2.0}. |
576 | * |
577 | * \note Has no effect on Q3DBars. |
578 | * |
579 | * \sa horizontalAspectRatio |
580 | */ |
581 | void QAbstract3DGraph::setAspectRatio(qreal ratio) |
582 | { |
583 | m_graphsItem->setAspectRatio(ratio); |
584 | } |
585 | |
586 | qreal QAbstract3DGraph::aspectRatio() const |
587 | { |
588 | return m_graphsItem->aspectRatio(); |
589 | } |
590 | |
591 | /*! |
592 | * \property QAbstract3DGraph::optimizationHints |
593 | * |
594 | * \brief Whether the default, static, or legacy mode is used for rendering optimization. |
595 | * |
596 | * The default mode uses instanced rendering, and provides the full feature set at the best level of |
597 | * performance on most systems. The static mode optimizes graph rendering and is ideal for |
598 | * large non-changing data sets. It is slower with dynamic data changes and item rotations. |
599 | * Selection is not optimized, so using the static mode with massive data sets is not advisable. |
600 | * Static optimization works only on scatter graphs. |
601 | * Legacy mode renders all items in th graph individually, without instancing. It should be used |
602 | * only if default mode does not work, i.e. if the target system does not support instancing. |
603 | * Defaults to \l{OptimizationDefault}. |
604 | * |
605 | * \note On some environments, large graphs using static optimization may not render, because |
606 | * all of the items are rendered using a single draw call, and different graphics drivers |
607 | * support different maximum vertice counts per call. |
608 | * This is mostly an issue on 32bit and OpenGL ES2 platforms. |
609 | * To work around this issue, choose an item mesh with a low vertex count or use |
610 | * the point mesh. |
611 | * |
612 | * \sa QAbstract3DSeries::mesh |
613 | */ |
614 | void QAbstract3DGraph::setOptimizationHints(QAbstract3DGraph::OptimizationHints hints) |
615 | { |
616 | m_graphsItem->setOptimizationHints(hints); |
617 | } |
618 | |
619 | QAbstract3DGraph::OptimizationHints QAbstract3DGraph::optimizationHints() const |
620 | { |
621 | return m_graphsItem->optimizationHints(); |
622 | } |
623 | |
624 | /*! |
625 | * \property QAbstract3DGraph::polar |
626 | * |
627 | * \brief Whether horizontal axes are changed into polar axes. |
628 | * |
629 | * If \c {true}, the x-axis becomes the angular axis and the z-axis becomes the |
630 | * radial axis. |
631 | * Polar mode is not available for bar graphs. |
632 | * |
633 | * Defaults to \c{false}. |
634 | * |
635 | * \sa orthoProjection, radialLabelOffset |
636 | */ |
637 | void QAbstract3DGraph::setPolar(bool enable) |
638 | { |
639 | m_graphsItem->setPolar(enable); |
640 | } |
641 | |
642 | bool QAbstract3DGraph::isPolar() const |
643 | { |
644 | return m_graphsItem->isPolar(); |
645 | } |
646 | |
647 | /*! |
648 | * \property QAbstract3DGraph::radialLabelOffset |
649 | * |
650 | * \brief The normalized horizontal offset for the axis labels of the radial |
651 | * polar axis. |
652 | * |
653 | * The value \c 0.0 indicates that the labels should be drawn next to the 0-angle |
654 | * angular axis grid line. The value \c 1.0 indicates that the labels are drawn |
655 | * in their usual place at the edge of the graph background. Defaults to \c 1.0. |
656 | * |
657 | * This property is ignored if the \l polar property value is \c{false}. |
658 | * |
659 | * \sa polar |
660 | */ |
661 | void QAbstract3DGraph::setRadialLabelOffset(float offset) |
662 | { |
663 | m_graphsItem->setRadialLabelOffset(offset); |
664 | } |
665 | |
666 | float QAbstract3DGraph::radialLabelOffset() const |
667 | { |
668 | return m_graphsItem->radialLabelOffset(); |
669 | } |
670 | |
671 | /*! |
672 | * \property QAbstract3DGraph::horizontalAspectRatio |
673 | * |
674 | * \brief The ratio of the graph scaling between the x-axis and z-axis. |
675 | * |
676 | * The value of \c 0.0 indicates automatic scaling according to axis ranges. |
677 | * Defaults to \c{0.0}. |
678 | * |
679 | * Has no effect on Q3DBars, which handles scaling on the horizontal plane via |
680 | * the \l{Q3DBars::barThickness}{barThickness} and \l{Q3DBars::barSpacing}{barSpacing} properties. |
681 | * Polar graphs also ignore this property. |
682 | * |
683 | * \sa aspectRatio, polar, Q3DBars::barThickness, Q3DBars::barSpacing |
684 | */ |
685 | void QAbstract3DGraph::setHorizontalAspectRatio(qreal ratio) |
686 | { |
687 | m_graphsItem->setHorizontalAspectRatio(ratio); |
688 | } |
689 | |
690 | qreal QAbstract3DGraph::horizontalAspectRatio() const |
691 | { |
692 | return m_graphsItem->horizontalAspectRatio(); |
693 | } |
694 | |
695 | /*! |
696 | * \property QAbstract3DGraph::reflection |
697 | * |
698 | * \brief Whether floor reflections are on or off. |
699 | * |
700 | * Defaults to \c{false}. |
701 | * |
702 | * Affects only Q3DBars. However, in Q3DBars graphs holding both positive and |
703 | * negative values, reflections are not supported for custom items that |
704 | * intersect the floor plane. In that case, reflections should be turned off |
705 | * to avoid incorrect rendering. |
706 | * |
707 | * If using a custom surface format, the stencil buffer needs to be defined |
708 | * (QSurfaceFormat::setStencilBufferSize()) for reflections to work. |
709 | * |
710 | * \sa reflectivity |
711 | */ |
712 | void QAbstract3DGraph::setReflection(bool enable) |
713 | { |
714 | m_graphsItem->setReflection(enable); |
715 | } |
716 | |
717 | bool QAbstract3DGraph::isReflection() const |
718 | { |
719 | // TODO: API missing in QQuickGraphsItem (QTBUG-99816) |
720 | return false; |
721 | // return m_graphsItem->reflection(); |
722 | } |
723 | |
724 | /*! |
725 | * \property QAbstract3DGraph::reflectivity |
726 | * |
727 | * \brief Floor reflectivity. |
728 | * |
729 | * Larger numbers make the floor more reflective. The valid range is \c{[0...1]}. |
730 | * Defaults to \c{0.5}. |
731 | * |
732 | * \note Affects only Q3DBars. |
733 | * |
734 | * \sa reflection |
735 | */ |
736 | void QAbstract3DGraph::setReflectivity(qreal reflectivity) |
737 | { |
738 | m_graphsItem->setReflectivity(reflectivity); |
739 | } |
740 | |
741 | qreal QAbstract3DGraph::reflectivity() const |
742 | { |
743 | return m_graphsItem->reflectivity(); |
744 | } |
745 | |
746 | /*! |
747 | * \property QAbstract3DGraph::locale |
748 | * |
749 | * \brief The locale used for formatting various numeric labels. |
750 | * |
751 | * Defaults to the \c{"C"} locale. |
752 | * |
753 | * \sa QValue3DAxis::labelFormat |
754 | */ |
755 | void QAbstract3DGraph::setLocale(const QLocale &locale) |
756 | { |
757 | m_graphsItem->setLocale(locale); |
758 | } |
759 | |
760 | QLocale QAbstract3DGraph::locale() const |
761 | { |
762 | return m_graphsItem->locale(); |
763 | } |
764 | |
765 | /*! |
766 | * \property QAbstract3DGraph::queriedGraphPosition |
767 | * |
768 | * \brief The latest queried graph position values along each axis. |
769 | * |
770 | * This read-only property contains the results from |
771 | * Q3DScene::graphPositionQuery. The values are normalized to the range \c{[-1, 1]}. |
772 | * If the queried position was outside the graph bounds, the values |
773 | * will not reflect the real position, but will instead indicate an undefined position outside |
774 | * the range \c{[-1, 1]}. The value will be undefined until a query is made. |
775 | * |
776 | * There is no single correct 3D coordinate to match a particular screen position, so to be |
777 | * consistent, the queries are always done against the inner sides of an invisible box surrounding |
778 | * the graph. |
779 | * |
780 | * \note Bar graphs only allow querying graph position at the graph floor level, |
781 | * so the y-value is always zero for bar graphs and the valid queries can be only made at |
782 | * screen positions that contain the floor of the graph. |
783 | * |
784 | * \sa Q3DScene::graphPositionQuery |
785 | */ |
786 | QVector3D QAbstract3DGraph::queriedGraphPosition() const |
787 | { |
788 | return m_graphsItem->queriedGraphPosition(); |
789 | } |
790 | |
791 | /*! |
792 | * \property QAbstract3DGraph::margin |
793 | * |
794 | * \brief The absolute value used for the space left between the edge of the |
795 | * plottable graph area and the edge of the graph background. |
796 | * |
797 | * If the margin value is negative, the margins are determined automatically and can vary according |
798 | * to the size of the items in the series and the type of the graph. |
799 | * The value is interpreted as a fraction of the y-axis range if the graph |
800 | * aspect ratios have not beed changed from the default values. |
801 | * Defaults to \c{-1.0}. |
802 | * |
803 | * \note Setting a smaller margin for a scatter graph than the automatically |
804 | * determined margin can cause the scatter items at the edges of the graph to |
805 | * overlap with the graph background. |
806 | * |
807 | * \note On scatter and surface graphs, if the margin is small in comparison to the axis label |
808 | * size, the positions of the edge labels of the axes are adjusted to avoid overlap with |
809 | * the edge labels of the neighboring axes. |
810 | */ |
811 | void QAbstract3DGraph::setMargin(qreal margin) |
812 | { |
813 | m_graphsItem->setMargin(margin); |
814 | } |
815 | |
816 | qreal QAbstract3DGraph::margin() const |
817 | { |
818 | return m_graphsItem->margin(); |
819 | } |
820 | |
821 | /*! |
822 | * \internal |
823 | */ |
824 | bool QAbstract3DGraph::event(QEvent *event) |
825 | { |
826 | switch (event->type()) { |
827 | case QEvent::TouchBegin: |
828 | case QEvent::TouchCancel: |
829 | case QEvent::TouchUpdate: |
830 | case QEvent::TouchEnd: |
831 | m_graphsItem->touchEvent(event: static_cast<QTouchEvent *>(event)); |
832 | return true; |
833 | default: |
834 | return QWidget::event(event); |
835 | } |
836 | } |
837 | |
838 | /*! |
839 | * \internal |
840 | */ |
841 | void QAbstract3DGraph::resizeEvent(QResizeEvent *event) |
842 | { |
843 | Q_UNUSED(event); |
844 | |
845 | if (m_graphsItem) { |
846 | QQuickWidget::resizeEvent(event); |
847 | |
848 | Q3DScene *scene = (Q3DScene *)m_graphsItem->scene(); |
849 | scene->d_func()->setWindowSize(QSize(width(), height())); |
850 | scene->d_func()->setViewport(QRect(0, 0, width(), height())); |
851 | if (m_graphsItem->sliceView() && m_graphsItem->sliceView()->isVisible()) |
852 | m_graphsItem->minimizeMainGraph(); |
853 | } |
854 | } |
855 | |
856 | /*! |
857 | * \internal |
858 | */ |
859 | void QAbstract3DGraph::mouseDoubleClickEvent(QMouseEvent *event) |
860 | { |
861 | m_graphsItem->mouseDoubleClickEvent(event); |
862 | } |
863 | |
864 | /*! |
865 | * \internal |
866 | */ |
867 | void QAbstract3DGraph::mousePressEvent(QMouseEvent *event) |
868 | { |
869 | m_graphsItem->mousePressEvent(event); |
870 | } |
871 | |
872 | /*! |
873 | * \internal |
874 | */ |
875 | void QAbstract3DGraph::mouseReleaseEvent(QMouseEvent *event) |
876 | { |
877 | m_graphsItem->mouseReleaseEvent(event); |
878 | } |
879 | |
880 | /*! |
881 | * \internal |
882 | */ |
883 | void QAbstract3DGraph::mouseMoveEvent(QMouseEvent *event) |
884 | { |
885 | m_graphsItem->mouseMoveEvent(event); |
886 | } |
887 | |
888 | #if QT_CONFIG(wheelevent) |
889 | /*! |
890 | * \internal |
891 | */ |
892 | void QAbstract3DGraph::wheelEvent(QWheelEvent *event) |
893 | { |
894 | m_graphsItem->wheelEvent(event); |
895 | } |
896 | #endif |
897 | |
898 | QT_END_NAMESPACE |
899 | |