1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Data Visualization module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include "abstractdeclarative_p.h"
31#include "declarativetheme_p.h"
32#include "declarativerendernode_p.h"
33#include <QtGui/QGuiApplication>
34#if defined(Q_OS_IOS)
35#include <QtCore/QTimer>
36#endif
37#if defined(Q_OS_OSX)
38#include <qpa/qplatformnativeinterface.h>
39#endif
40
41#if !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID) && !defined(Q_OS_WINRT)
42#define USE_SHARED_CONTEXT
43#else
44#include "glstatestore_p.h"
45#endif
46
47QT_BEGIN_NAMESPACE_DATAVISUALIZATION
48
49static QList<const QQuickWindow *> clearList;
50static QHash<AbstractDeclarative *, QQuickWindow *> graphWindowList;
51static QHash<QQuickWindow *, bool> windowClearList;
52
53AbstractDeclarative::AbstractDeclarative(QQuickItem *parent) :
54 QQuickItem(parent),
55 m_controller(0),
56 m_contextWindow(0),
57 m_renderMode(RenderIndirect),
58 m_samples(0),
59 m_windowSamples(0),
60 m_initialisedSize(0, 0),
61 m_contextOrStateStore(0),
62 m_qtContext(0),
63 m_mainThread(QThread::currentThread()),
64 m_contextThread(0)
65{
66 m_nodeMutex = QSharedPointer<QMutex>::create();
67
68 connect(sender: this, signal: &QQuickItem::windowChanged, receiver: this, slot: &AbstractDeclarative::handleWindowChanged);
69
70 // Set contents to false in case we are in qml designer to make component look nice
71 m_runningInDesigner = QGuiApplication::applicationDisplayName() == "Qml2Puppet";
72 setFlag(flag: ItemHasContents, enabled: !m_runningInDesigner);
73}
74
75AbstractDeclarative::~AbstractDeclarative()
76{
77 destroyContext();
78
79 disconnect(sender: this, signal: 0, receiver: this, member: 0);
80 checkWindowList(window: 0);
81
82 // Make sure not deleting locked mutex
83 QMutexLocker locker(&m_mutex);
84 locker.unlock();
85
86 m_nodeMutex.clear();
87}
88
89void AbstractDeclarative::setRenderingMode(AbstractDeclarative::RenderingMode mode)
90{
91 if (mode == m_renderMode)
92 return;
93
94 RenderingMode previousMode = m_renderMode;
95
96 m_renderMode = mode;
97
98 QQuickWindow *win = window();
99
100 switch (mode) {
101 case RenderDirectToBackground:
102 // Intentional flowthrough
103 case RenderDirectToBackground_NoClear:
104 m_initialisedSize = QSize(0, 0);
105 if (previousMode == RenderIndirect) {
106 update();
107 setFlag(flag: ItemHasContents, enabled: false);
108 if (win) {
109 QObject::connect(sender: win, signal: &QQuickWindow::beforeRendering, receiver: this,
110 slot: &AbstractDeclarative::render, type: Qt::DirectConnection);
111 checkWindowList(window: win);
112 setAntialiasing(m_windowSamples > 0);
113 if (m_windowSamples != m_samples)
114 emit msaaSamplesChanged(samples: m_windowSamples);
115 }
116 }
117 break;
118 case RenderIndirect:
119 m_initialisedSize = QSize(0, 0);
120 setFlag(flag: ItemHasContents, enabled: !m_runningInDesigner);
121 update();
122 if (win) {
123 QObject::disconnect(sender: win, signal: &QQuickWindow::beforeRendering, receiver: this,
124 slot: &AbstractDeclarative::render);
125 checkWindowList(window: win);
126 }
127 setAntialiasing(m_samples > 0);
128 if (m_windowSamples != m_samples)
129 emit msaaSamplesChanged(samples: m_samples);
130 break;
131 }
132
133 updateWindowParameters();
134
135 emit renderingModeChanged(mode);
136}
137
138AbstractDeclarative::RenderingMode AbstractDeclarative::renderingMode() const
139{
140 return m_renderMode;
141}
142
143QSGNode *AbstractDeclarative::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
144{
145 QSize boundingSize = boundingRect().size().toSize() * m_controller->scene()->devicePixelRatio();
146 if (m_runningInDesigner || boundingSize.width() <= 0 || boundingSize.height() <= 0
147 || m_controller.isNull() || !window()) {
148 delete oldNode;
149 return 0;
150 }
151 DeclarativeRenderNode *node = static_cast<DeclarativeRenderNode *>(oldNode);
152
153 if (!node) {
154 node = new DeclarativeRenderNode(this, m_nodeMutex);
155 node->setController(m_controller.data());
156 node->setQuickWindow(window());
157 }
158
159 node->setSize(boundingSize);
160 node->setSamples(m_samples);
161 node->update();
162 node->markDirty(bits: QSGNode::DirtyMaterial);
163
164 return node;
165}
166
167Declarative3DScene* AbstractDeclarative::scene() const
168{
169 return static_cast<Declarative3DScene *>(m_controller->scene());
170}
171
172void AbstractDeclarative::setTheme(Q3DTheme *theme)
173{
174 m_controller->setActiveTheme(theme, force: isComponentComplete());
175}
176
177Q3DTheme *AbstractDeclarative::theme() const
178{
179 return m_controller->activeTheme();
180}
181
182void AbstractDeclarative::clearSelection()
183{
184 m_controller->clearSelection();
185}
186
187void AbstractDeclarative::setSelectionMode(SelectionFlags mode)
188{
189 int intmode = int(mode);
190 m_controller->setSelectionMode(QAbstract3DGraph::SelectionFlags(intmode));
191}
192
193AbstractDeclarative::SelectionFlags AbstractDeclarative::selectionMode() const
194{
195 int intmode = int(m_controller->selectionMode());
196 return SelectionFlags(intmode);
197}
198
199void AbstractDeclarative::setShadowQuality(ShadowQuality quality)
200{
201 m_controller->setShadowQuality(QAbstract3DGraph::ShadowQuality(quality));
202}
203
204AbstractDeclarative::ShadowQuality AbstractDeclarative::shadowQuality() const
205{
206 return ShadowQuality(m_controller->shadowQuality());
207}
208
209bool AbstractDeclarative::shadowsSupported() const
210{
211 return m_controller->shadowsSupported();
212}
213
214int AbstractDeclarative::addCustomItem(QCustom3DItem *item)
215{
216 return m_controller->addCustomItem(item);
217}
218
219void AbstractDeclarative::removeCustomItems()
220{
221 m_controller->deleteCustomItems();
222}
223
224void AbstractDeclarative::removeCustomItem(QCustom3DItem *item)
225{
226 m_controller->deleteCustomItem(item);
227}
228
229void AbstractDeclarative::removeCustomItemAt(const QVector3D &position)
230{
231 m_controller->deleteCustomItem(position);
232}
233
234void AbstractDeclarative::releaseCustomItem(QCustom3DItem *item)
235{
236 m_controller->releaseCustomItem(item);
237}
238
239int AbstractDeclarative::selectedLabelIndex() const
240{
241 return m_controller->selectedLabelIndex();
242}
243
244QAbstract3DAxis *AbstractDeclarative::selectedAxis() const
245{
246 return m_controller->selectedAxis();
247}
248
249int AbstractDeclarative::selectedCustomItemIndex() const
250{
251 return m_controller->selectedCustomItemIndex();
252}
253
254QCustom3DItem *AbstractDeclarative::selectedCustomItem() const
255{
256 return m_controller->selectedCustomItem();
257}
258
259QQmlListProperty<QCustom3DItem> AbstractDeclarative::customItemList()
260{
261 return QQmlListProperty<QCustom3DItem>(this, this,
262 &AbstractDeclarative::appendCustomItemFunc,
263 &AbstractDeclarative::countCustomItemFunc,
264 &AbstractDeclarative::atCustomItemFunc,
265 &AbstractDeclarative::clearCustomItemFunc);
266}
267
268void AbstractDeclarative::appendCustomItemFunc(QQmlListProperty<QCustom3DItem> *list,
269 QCustom3DItem *item)
270{
271 AbstractDeclarative *decl = reinterpret_cast<AbstractDeclarative *>(list->data);
272 decl->addCustomItem(item);
273}
274
275int AbstractDeclarative::countCustomItemFunc(QQmlListProperty<QCustom3DItem> *list)
276{
277 return reinterpret_cast<AbstractDeclarative *>(list->data)->m_controller->m_customItems.size();
278}
279
280QCustom3DItem *AbstractDeclarative::atCustomItemFunc(QQmlListProperty<QCustom3DItem> *list,
281 int index)
282{
283 return reinterpret_cast<AbstractDeclarative *>(list->data)->m_controller->m_customItems.at(i: index);
284}
285
286void AbstractDeclarative::clearCustomItemFunc(QQmlListProperty<QCustom3DItem> *list)
287{
288 AbstractDeclarative *decl = reinterpret_cast<AbstractDeclarative *>(list->data);
289 decl->removeCustomItems();
290}
291
292void AbstractDeclarative::setSharedController(Abstract3DController *controller)
293{
294 Q_ASSERT(controller);
295 m_controller = controller;
296
297 if (!m_controller->isOpenGLES())
298 m_samples = 4;
299 setAntialiasing(m_samples > 0);
300
301 // Reset default theme, as the default C++ theme is Q3DTheme, not DeclarativeTheme3D.
302 DeclarativeTheme3D *defaultTheme = new DeclarativeTheme3D;
303 defaultTheme->d_ptr->setDefaultTheme(true);
304 defaultTheme->setType(Q3DTheme::ThemeQt);
305 m_controller->setActiveTheme(theme: defaultTheme);
306
307 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::shadowQualityChanged, receiver: this,
308 slot: &AbstractDeclarative::handleShadowQualityChange);
309 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::activeInputHandlerChanged, receiver: this,
310 slot: &AbstractDeclarative::inputHandlerChanged);
311 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::activeThemeChanged, receiver: this,
312 slot: &AbstractDeclarative::themeChanged);
313 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::selectionModeChanged, receiver: this,
314 slot: &AbstractDeclarative::handleSelectionModeChange);
315 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::elementSelected, receiver: this,
316 slot: &AbstractDeclarative::handleSelectedElementChange);
317
318 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::axisXChanged, receiver: this,
319 slot: &AbstractDeclarative::handleAxisXChanged);
320 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::axisYChanged, receiver: this,
321 slot: &AbstractDeclarative::handleAxisYChanged);
322 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::axisZChanged, receiver: this,
323 slot: &AbstractDeclarative::handleAxisZChanged);
324
325 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::measureFpsChanged, receiver: this,
326 slot: &AbstractDeclarative::measureFpsChanged);
327 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::currentFpsChanged, receiver: this,
328 slot: &AbstractDeclarative::currentFpsChanged);
329
330 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::orthoProjectionChanged, receiver: this,
331 slot: &AbstractDeclarative::orthoProjectionChanged);
332
333 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::aspectRatioChanged, receiver: this,
334 slot: &AbstractDeclarative::aspectRatioChanged);
335 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::optimizationHintsChanged, receiver: this,
336 slot: &AbstractDeclarative::handleOptimizationHintChange);
337 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::polarChanged, receiver: this,
338 slot: &AbstractDeclarative::polarChanged);
339 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::radialLabelOffsetChanged, receiver: this,
340 slot: &AbstractDeclarative::radialLabelOffsetChanged);
341 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::horizontalAspectRatioChanged, receiver: this,
342 slot: &AbstractDeclarative::horizontalAspectRatioChanged);
343 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::reflectionChanged, receiver: this,
344 slot: &AbstractDeclarative::reflectionChanged);
345 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::reflectivityChanged, receiver: this,
346 slot: &AbstractDeclarative::reflectivityChanged);
347 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::localeChanged, receiver: this,
348 slot: &AbstractDeclarative::localeChanged);
349 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::queriedGraphPositionChanged, receiver: this,
350 slot: &AbstractDeclarative::queriedGraphPositionChanged);
351 QObject::connect(sender: m_controller.data(), signal: &Abstract3DController::marginChanged, receiver: this,
352 slot: &AbstractDeclarative::marginChanged);
353}
354
355void AbstractDeclarative::activateOpenGLContext(QQuickWindow *window)
356{
357 // We can assume we are not in middle of AbstractDeclarative destructor when we are here,
358 // since m_context creation is always done when this function is called from
359 // synchDataToRenderer(), which blocks main thread -> no need to mutex.
360 if (!m_contextOrStateStore || !m_qtContext || m_contextWindow != window) {
361 QOpenGLContext *currentContext = QOpenGLContext::currentContext();
362
363 // Note: Changing graph to different window when using multithreaded renderer will break!
364
365 delete m_contextOrStateStore;
366
367 m_contextThread = QThread::currentThread();
368 m_contextWindow = window;
369 m_qtContext = currentContext;
370
371#ifdef USE_SHARED_CONTEXT
372 m_context = new QOpenGLContext();
373 m_context->setFormat(m_qtContext->format());
374 m_context->setShareContext(m_qtContext);
375 m_context->create();
376 m_context->makeCurrent(surface: window);
377#else
378 // Shared contexts don't work properly in some platforms, so just store the
379 // context state on those
380 m_stateStore = new GLStateStore(QOpenGLContext::currentContext());
381 m_stateStore->storeGLState();
382#endif
383 m_controller->initializeOpenGL();
384
385 // Make sure context / state store gets deleted.
386 QObject::connect(sender: m_contextThread, signal: &QThread::finished, receiver: this,
387 slot: &AbstractDeclarative::destroyContext, type: Qt::DirectConnection);
388 } else {
389#ifdef USE_SHARED_CONTEXT
390 m_context->makeCurrent(surface: window);
391#else
392 m_stateStore->storeGLState();
393#endif
394 }
395}
396
397void AbstractDeclarative::doneOpenGLContext(QQuickWindow *window)
398{
399#ifdef USE_SHARED_CONTEXT
400 m_qtContext->makeCurrent(surface: window);
401#else
402 Q_UNUSED(window)
403 m_stateStore->restoreGLState();
404#endif
405}
406
407void AbstractDeclarative::synchDataToRenderer()
408{
409 if (m_renderMode == RenderDirectToBackground && clearList.size())
410 clearList.clear();
411
412 QQuickWindow *win = window();
413 activateOpenGLContext(window: win);
414 m_controller->synchDataToRenderer();
415 doneOpenGLContext(window: win);
416}
417
418int AbstractDeclarative::msaaSamples() const
419{
420 if (m_renderMode == RenderIndirect)
421 return m_samples;
422 else
423 return m_windowSamples;
424}
425
426void AbstractDeclarative::setMsaaSamples(int samples)
427{
428 if (m_renderMode != RenderIndirect) {
429 qWarning(msg: "Multisampling cannot be adjusted in this render mode");
430 } else {
431 if (m_controller->isOpenGLES()) {
432 if (samples > 0)
433 qWarning(msg: "Multisampling is not supported in OpenGL ES2");
434 } else if (m_samples != samples) {
435 m_samples = samples;
436 setAntialiasing(m_samples > 0);
437 emit msaaSamplesChanged(samples);
438 update();
439 }
440 }
441}
442
443void AbstractDeclarative::handleWindowChanged(QQuickWindow *window)
444{
445 checkWindowList(window);
446
447 if (!window)
448 return;
449
450#if defined(Q_OS_OSX)
451 bool previousVisibility = window->isVisible();
452 // Enable touch events for Mac touchpads
453 window->setVisible(true);
454 typedef void * (*EnableTouch)(QWindow*, bool);
455 EnableTouch enableTouch =
456 (EnableTouch)QGuiApplication::platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow");
457 if (enableTouch)
458 enableTouch(window, true);
459 window->setVisible(previousVisibility);
460#endif
461
462 connect(sender: window, signal: &QObject::destroyed, receiver: this, slot: &AbstractDeclarative::windowDestroyed);
463
464 int oldWindowSamples = m_windowSamples;
465 m_windowSamples = window->format().samples();
466 if (m_windowSamples < 0)
467 m_windowSamples = 0;
468
469 connect(sender: window, signal: &QQuickWindow::beforeSynchronizing,
470 receiver: this, slot: &AbstractDeclarative::synchDataToRenderer,
471 type: Qt::DirectConnection);
472
473 if (m_renderMode == RenderDirectToBackground_NoClear
474 || m_renderMode == RenderDirectToBackground) {
475 connect(sender: window, signal: &QQuickWindow::beforeRendering, receiver: this, slot: &AbstractDeclarative::render,
476 type: Qt::DirectConnection);
477 setAntialiasing(m_windowSamples > 0);
478 if (m_windowSamples != oldWindowSamples)
479 emit msaaSamplesChanged(samples: m_windowSamples);
480 }
481
482 connect(sender: m_controller.data(), signal: &Abstract3DController::needRender, receiver: window, slot: &QQuickWindow::update);
483
484 updateWindowParameters();
485
486#if defined(Q_OS_IOS)
487 // Scenegraph render cycle in iOS sometimes misses update after beforeSynchronizing signal.
488 // This ensures we don't end up displaying the graph without any data, in case update is
489 // skipped after synchDataToRenderer.
490 QTimer::singleShot(0, window, SLOT(update()));
491#endif
492}
493
494void AbstractDeclarative::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
495{
496 QQuickItem::geometryChanged(newGeometry, oldGeometry);
497
498 m_cachedGeometry = newGeometry;
499
500 updateWindowParameters();
501}
502
503void AbstractDeclarative::itemChange(ItemChange change, const ItemChangeData & value)
504{
505 QQuickItem::itemChange(change, value);
506 updateWindowParameters();
507}
508
509void AbstractDeclarative::updateWindowParameters()
510{
511 const QMutexLocker locker(&m_mutex);
512
513 // Update the device pixel ratio, window size and bounding box
514 QQuickWindow *win = window();
515 if (win && !m_controller.isNull()) {
516 Q3DScene *scene = m_controller->scene();
517 if (win->devicePixelRatio() != scene->devicePixelRatio()) {
518 scene->setDevicePixelRatio(win->devicePixelRatio());
519 win->update();
520 }
521
522 bool directRender = m_renderMode == RenderDirectToBackground
523 || m_renderMode == RenderDirectToBackground_NoClear;
524 QSize windowSize;
525
526 if (directRender)
527 windowSize = win->size();
528 else
529 windowSize = m_cachedGeometry.size().toSize();
530
531 if (windowSize != scene->d_ptr->windowSize()) {
532 scene->d_ptr->setWindowSize(windowSize);
533 win->update();
534 }
535
536 if (directRender) {
537 // Origin mapping is needed when rendering directly to background
538 QPointF point = QQuickItem::mapToScene(point: QPointF(0.0, 0.0));
539 scene->d_ptr->setViewport(QRect(point.x() + 0.5f, point.y() + 0.5f,
540 m_cachedGeometry.width() + 0.5f,
541 m_cachedGeometry.height() + 0.5f));
542 } else {
543 // No translation needed when rendering to FBO
544 scene->d_ptr->setViewport(QRect(0.0, 0.0, m_cachedGeometry.width() + 0.5f,
545 m_cachedGeometry.height() + 0.5f));
546 }
547 }
548}
549
550void AbstractDeclarative::handleSelectionModeChange(QAbstract3DGraph::SelectionFlags mode)
551{
552 int intmode = int(mode);
553 emit selectionModeChanged(mode: SelectionFlags(intmode));
554}
555
556void AbstractDeclarative::handleShadowQualityChange(QAbstract3DGraph::ShadowQuality quality)
557{
558 emit shadowQualityChanged(quality: ShadowQuality(quality));
559}
560
561void AbstractDeclarative::handleSelectedElementChange(QAbstract3DGraph::ElementType type)
562{
563 emit selectedElementChanged(type: ElementType(type));
564}
565
566void AbstractDeclarative::handleOptimizationHintChange(QAbstract3DGraph::OptimizationHints hints)
567{
568 int intHints = int(hints);
569 emit optimizationHintsChanged(hints: OptimizationHints(intHints));
570}
571
572void AbstractDeclarative::render()
573{
574 updateWindowParameters();
575
576 // If we're not rendering directly to the background, return
577 if (m_renderMode != RenderDirectToBackground && m_renderMode != RenderDirectToBackground_NoClear)
578 return;
579
580 // Clear the background once per window as that is not done by default
581 QQuickWindow *win = window();
582 activateOpenGLContext(window: win);
583 QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
584 if (m_renderMode == RenderDirectToBackground && !clearList.contains(t: win)) {
585 clearList.append(t: win);
586 QColor clearColor = win->color();
587 funcs->glClearColor(red: clearColor.redF(), green: clearColor.greenF(), blue: clearColor.blueF(), alpha: 1.0f);
588 funcs->glClear(GL_COLOR_BUFFER_BIT);
589 }
590
591 if (isVisible()) {
592 funcs->glDepthMask(GL_TRUE);
593 funcs->glEnable(GL_DEPTH_TEST);
594 funcs->glDepthFunc(GL_LESS);
595 funcs->glEnable(GL_CULL_FACE);
596 funcs->glCullFace(GL_BACK);
597 funcs->glDisable(GL_BLEND);
598
599 m_controller->render();
600
601 funcs->glEnable(GL_BLEND);
602 }
603 doneOpenGLContext(window: win);
604}
605
606QAbstract3DInputHandler* AbstractDeclarative::inputHandler() const
607{
608 return m_controller->activeInputHandler();
609}
610
611void AbstractDeclarative::setInputHandler(QAbstract3DInputHandler *inputHandler)
612{
613 m_controller->setActiveInputHandler(inputHandler);
614}
615
616void AbstractDeclarative::mouseDoubleClickEvent(QMouseEvent *event)
617{
618 m_controller->mouseDoubleClickEvent(event);
619}
620
621void AbstractDeclarative::touchEvent(QTouchEvent *event)
622{
623 m_controller->touchEvent(event);
624 window()->update();
625}
626
627void AbstractDeclarative::mousePressEvent(QMouseEvent *event)
628{
629 QPoint mousePos = event->pos();
630 m_controller->mousePressEvent(event, mousePos);
631}
632
633void AbstractDeclarative::mouseReleaseEvent(QMouseEvent *event)
634{
635 QPoint mousePos = event->pos();
636 m_controller->mouseReleaseEvent(event, mousePos);
637}
638
639void AbstractDeclarative::mouseMoveEvent(QMouseEvent *event)
640{
641 QPoint mousePos = event->pos();
642 m_controller->mouseMoveEvent(event, mousePos);
643}
644
645#if QT_CONFIG(wheelevent)
646void AbstractDeclarative::wheelEvent(QWheelEvent *event)
647{
648 m_controller->wheelEvent(event);
649}
650#endif
651
652void AbstractDeclarative::checkWindowList(QQuickWindow *window)
653{
654 QQuickWindow *oldWindow = graphWindowList.value(akey: this);
655
656 graphWindowList[this] = window;
657
658 if (oldWindow != window && oldWindow) {
659 QObject::disconnect(sender: oldWindow, signal: &QObject::destroyed, receiver: this,
660 slot: &AbstractDeclarative::windowDestroyed);
661 QObject::disconnect(sender: oldWindow, signal: &QQuickWindow::beforeSynchronizing, receiver: this,
662 slot: &AbstractDeclarative::synchDataToRenderer);
663 QObject::disconnect(sender: oldWindow, signal: &QQuickWindow::beforeRendering, receiver: this,
664 slot: &AbstractDeclarative::render);
665 if (!m_controller.isNull()) {
666 QObject::disconnect(sender: m_controller.data(), signal: &Abstract3DController::needRender,
667 receiver: oldWindow, slot: &QQuickWindow::update);
668 }
669 }
670
671 QList<QQuickWindow *> windowList;
672
673 foreach (AbstractDeclarative *graph, graphWindowList.keys()) {
674 if (graph->m_renderMode == RenderDirectToBackground
675 || graph->m_renderMode == RenderDirectToBackground_NoClear) {
676 windowList.append(t: graphWindowList.value(akey: graph));
677 }
678 }
679
680 if (oldWindow && !windowList.contains(t: oldWindow)
681 && windowClearList.contains(akey: oldWindow)) {
682 // Return window clear value
683 oldWindow->setClearBeforeRendering(windowClearList.value(akey: oldWindow));
684 windowClearList.remove(akey: oldWindow);
685 }
686
687 if (!window) {
688 graphWindowList.remove(akey: this);
689 return;
690 }
691
692 if ((m_renderMode == RenderDirectToBackground
693 || m_renderMode == RenderDirectToBackground_NoClear)
694 && !windowClearList.contains(akey: window)) {
695 // Save old clear value
696 windowClearList[window] = window->clearBeforeRendering();
697 // Disable clearing of the window as we render underneath
698 window->setClearBeforeRendering(false);
699 }
700}
701
702void AbstractDeclarative::setMeasureFps(bool enable)
703{
704 m_controller->setMeasureFps(enable);
705}
706
707bool AbstractDeclarative::measureFps() const
708{
709 return m_controller->measureFps();
710}
711
712qreal AbstractDeclarative::currentFps() const
713{
714 return m_controller->currentFps();
715}
716
717void AbstractDeclarative::setOrthoProjection(bool enable)
718{
719 m_controller->setOrthoProjection(enable);
720}
721
722bool AbstractDeclarative::isOrthoProjection() const
723{
724 return m_controller->isOrthoProjection();
725}
726
727AbstractDeclarative::ElementType AbstractDeclarative::selectedElement() const
728{
729 return ElementType(m_controller->selectedElement());
730}
731
732void AbstractDeclarative::setAspectRatio(qreal ratio)
733{
734 m_controller->setAspectRatio(ratio);
735}
736
737qreal AbstractDeclarative::aspectRatio() const
738{
739 return m_controller->aspectRatio();
740}
741
742void AbstractDeclarative::setOptimizationHints(OptimizationHints hints)
743{
744 int intmode = int(hints);
745 m_controller->setOptimizationHints(QAbstract3DGraph::OptimizationHints(intmode));
746}
747
748AbstractDeclarative::OptimizationHints AbstractDeclarative::optimizationHints() const
749{
750 int intmode = int(m_controller->optimizationHints());
751 return OptimizationHints(intmode);
752}
753
754void AbstractDeclarative::setPolar(bool enable)
755{
756 m_controller->setPolar(enable);
757}
758
759bool AbstractDeclarative::isPolar() const
760{
761 return m_controller->isPolar();
762}
763
764void AbstractDeclarative::setRadialLabelOffset(float offset)
765{
766 m_controller->setRadialLabelOffset(offset);
767}
768
769float AbstractDeclarative::radialLabelOffset() const
770{
771 return m_controller->radialLabelOffset();
772}
773
774void AbstractDeclarative::setHorizontalAspectRatio(qreal ratio)
775{
776 m_controller->setHorizontalAspectRatio(ratio);
777}
778
779qreal AbstractDeclarative::horizontalAspectRatio() const
780{
781 return m_controller->horizontalAspectRatio();
782}
783
784void AbstractDeclarative::setReflection(bool enable)
785{
786 m_controller->setReflection(enable);
787}
788
789bool AbstractDeclarative::isReflection() const
790{
791 return m_controller->reflection();
792}
793
794void AbstractDeclarative::setReflectivity(qreal reflectivity)
795{
796 m_controller->setReflectivity(reflectivity);
797}
798
799qreal AbstractDeclarative::reflectivity() const
800{
801 return m_controller->reflectivity();
802}
803
804void AbstractDeclarative::setLocale(const QLocale &locale)
805{
806 m_controller->setLocale(locale);
807}
808
809QLocale AbstractDeclarative::locale() const
810{
811 return m_controller->locale();
812}
813
814QVector3D AbstractDeclarative::queriedGraphPosition() const
815{
816 return m_controller->queriedGraphPosition();
817}
818
819void AbstractDeclarative::setMargin(qreal margin)
820{
821 m_controller->setMargin(margin);
822}
823
824qreal AbstractDeclarative::margin() const
825{
826 return m_controller->margin();
827}
828
829void AbstractDeclarative::windowDestroyed(QObject *obj)
830{
831 // Remove destroyed window from window lists
832 QQuickWindow *win = static_cast<QQuickWindow *>(obj);
833 QQuickWindow *oldWindow = graphWindowList.value(akey: this);
834
835 if (win == oldWindow)
836 graphWindowList.remove(akey: this);
837
838 windowClearList.remove(akey: win);
839}
840
841void AbstractDeclarative::destroyContext()
842{
843 if (m_contextThread && m_contextThread != m_mainThread) {
844 if (m_contextOrStateStore)
845 m_contextOrStateStore->deleteLater();
846 } else {
847 delete m_contextOrStateStore;
848 }
849 m_contextOrStateStore = 0;
850
851 if (m_contextThread) {
852 QObject::disconnect(sender: m_contextThread, signal: &QThread::finished, receiver: this,
853 slot: &AbstractDeclarative::destroyContext);
854 m_contextThread = 0;
855 }
856}
857
858QT_END_NAMESPACE_DATAVISUALIZATION
859

source code of qtdatavis3d/src/datavisualizationqml2/abstractdeclarative.cpp