diff options
Diffstat (limited to 'src/datavisualizationqml/abstractdeclarative.cpp')
-rw-r--r-- | src/datavisualizationqml/abstractdeclarative.cpp | 818 |
1 files changed, 818 insertions, 0 deletions
diff --git a/src/datavisualizationqml/abstractdeclarative.cpp b/src/datavisualizationqml/abstractdeclarative.cpp new file mode 100644 index 00000000..af19d46f --- /dev/null +++ b/src/datavisualizationqml/abstractdeclarative.cpp @@ -0,0 +1,818 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "abstractdeclarative_p.h" +#include "declarativetheme_p.h" +#include "declarativerendernode_p.h" +#include <QtGui/QGuiApplication> +#if defined(Q_OS_IOS) +#include <QtCore/QTimer> +#endif +#if defined(Q_OS_MACOS) +#include <qpa/qplatformnativeinterface.h> +#endif + +#if !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID) && !defined(Q_OS_WINRT) +#define USE_SHARED_CONTEXT +#else +#include "glstatestore_p.h" +#endif + +QT_BEGIN_NAMESPACE + +static QHash<AbstractDeclarative *, QQuickWindow *> graphWindowList; + +AbstractDeclarative::AbstractDeclarative(QQuickItem *parent) : + QQuickItem(parent), + AbstractDeclarativeInterface(), + m_controller(0), + m_contextWindow(0), + m_renderMode(RenderIndirect), + m_samples(0), + m_windowSamples(0), + m_initialisedSize(0, 0), + m_contextOrStateStore(0), + m_qtContext(0), + m_mainThread(QThread::currentThread()), + m_contextThread(0) +{ + m_nodeMutex = QSharedPointer<QMutex>::create(); + + connect(this, &QQuickItem::windowChanged, this, &AbstractDeclarative::handleWindowChanged); + + // Set contents to false in case we are in qml designer to make component look nice + m_runningInDesigner = QGuiApplication::applicationDisplayName() == QLatin1String("Qml2Puppet"); + setFlag(ItemHasContents, !m_runningInDesigner); + + // Accept touchevents + setAcceptTouchEvents(true); +} + +AbstractDeclarative::~AbstractDeclarative() +{ + destroyContext(); + + disconnect(this, 0, this, 0); + checkWindowList(0); + + // Make sure not deleting locked mutex + QMutexLocker locker(&m_mutex); + locker.unlock(); + + m_nodeMutex.clear(); +} + +void AbstractDeclarative::setRenderingMode(AbstractDeclarative::RenderingMode mode) +{ + if (mode == m_renderMode + || mode <= AbstractDeclarative::RenderingMode::RenderDirectToBackground + || mode >= AbstractDeclarative::RenderingMode::RenderIndirect) { + return; + } + + RenderingMode previousMode = m_renderMode; + + m_renderMode = mode; + + QQuickWindow *win = window(); + + switch (mode) { + case RenderDirectToBackground: + // Intentional flowthrough + case RenderDirectToBackground_NoClear: + m_initialisedSize = QSize(0, 0); + if (previousMode == RenderIndirect) { + update(); + setFlag(ItemHasContents, false); + if (win) { + QObject::connect(win, &QQuickWindow::beforeRenderPassRecording, this, + &AbstractDeclarative::render, Qt::DirectConnection); + checkWindowList(win); + setAntialiasing(m_windowSamples > 0); + if (m_windowSamples != m_samples) + emit msaaSamplesChanged(m_windowSamples); + } + } + break; + case RenderIndirect: + m_initialisedSize = QSize(0, 0); + setFlag(ItemHasContents, !m_runningInDesigner); + update(); + if (win) { + QObject::disconnect(win, &QQuickWindow::beforeRenderPassRecording, this, + &AbstractDeclarative::render); + checkWindowList(win); + } + setAntialiasing(m_samples > 0); + if (m_windowSamples != m_samples) + emit msaaSamplesChanged(m_samples); + break; + } + + updateWindowParameters(); + + emit renderingModeChanged(mode); +} + +AbstractDeclarative::RenderingMode AbstractDeclarative::renderingMode() const +{ + return m_renderMode; +} + +QSGNode *AbstractDeclarative::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + QSize boundingSize = boundingRect().size().toSize() * m_controller->scene()->devicePixelRatio(); + if (m_runningInDesigner || boundingSize.width() <= 0 || boundingSize.height() <= 0 + || m_controller.isNull() || !window()) { + delete oldNode; + return 0; + } + DeclarativeRenderNode *node = static_cast<DeclarativeRenderNode *>(oldNode); + + if (!node) { + node = new DeclarativeRenderNode(this, m_nodeMutex); + node->setController(m_controller.data()); + node->setQuickWindow(window()); + } + + node->setSize(boundingSize); + node->setSamples(m_samples); + node->update(); + node->markDirty(QSGNode::DirtyMaterial); + + return node; +} + +Declarative3DScene* AbstractDeclarative::scene() const +{ + return static_cast<Declarative3DScene *>(m_controller->scene()); +} + +void AbstractDeclarative::setTheme(Q3DTheme *theme) +{ + m_controller->setActiveTheme(theme, isComponentComplete()); +} + +Q3DTheme *AbstractDeclarative::theme() const +{ + return m_controller->activeTheme(); +} + +void AbstractDeclarative::clearSelection() +{ + m_controller->clearSelection(); +} + +bool AbstractDeclarative::hasSeries(QAbstract3DSeries *series) +{ + return m_controller->hasSeries(series); +} + +void AbstractDeclarative::setSelectionMode(SelectionFlags mode) +{ + int intmode = int(mode); + m_controller->setSelectionMode(QAbstract3DGraph::SelectionFlags(intmode)); +} + +AbstractDeclarative::SelectionFlags AbstractDeclarative::selectionMode() const +{ + int intmode = int(m_controller->selectionMode()); + return SelectionFlags(intmode); +} + +void AbstractDeclarative::setShadowQuality(ShadowQuality quality) +{ + m_controller->setShadowQuality(QAbstract3DGraph::ShadowQuality(quality)); +} + +AbstractDeclarative::ShadowQuality AbstractDeclarative::shadowQuality() const +{ + return ShadowQuality(m_controller->shadowQuality()); +} + +bool AbstractDeclarative::shadowsSupported() const +{ + return m_controller->shadowsSupported(); +} + +int AbstractDeclarative::addCustomItem(QCustom3DItem *item) +{ + return m_controller->addCustomItem(item); +} + +void AbstractDeclarative::removeCustomItems() +{ + m_controller->deleteCustomItems(); +} + +void AbstractDeclarative::removeCustomItem(QCustom3DItem *item) +{ + m_controller->deleteCustomItem(item); +} + +void AbstractDeclarative::removeCustomItemAt(const QVector3D &position) +{ + m_controller->deleteCustomItem(position); +} + +void AbstractDeclarative::releaseCustomItem(QCustom3DItem *item) +{ + m_controller->releaseCustomItem(item); +} + +int AbstractDeclarative::selectedLabelIndex() const +{ + return m_controller->selectedLabelIndex(); +} + +QAbstract3DAxis *AbstractDeclarative::selectedAxis() const +{ + return m_controller->selectedAxis(); +} + +int AbstractDeclarative::selectedCustomItemIndex() const +{ + return m_controller->selectedCustomItemIndex(); +} + +QCustom3DItem *AbstractDeclarative::selectedCustomItem() const +{ + return m_controller->selectedCustomItem(); +} + +QQmlListProperty<QCustom3DItem> AbstractDeclarative::customItemList() +{ + return QQmlListProperty<QCustom3DItem>(this, this, + &AbstractDeclarative::appendCustomItemFunc, + &AbstractDeclarative::countCustomItemFunc, + &AbstractDeclarative::atCustomItemFunc, + &AbstractDeclarative::clearCustomItemFunc); +} + +void AbstractDeclarative::appendCustomItemFunc(QQmlListProperty<QCustom3DItem> *list, + QCustom3DItem *item) +{ + AbstractDeclarative *decl = reinterpret_cast<AbstractDeclarative *>(list->data); + decl->addCustomItem(item); +} + +qsizetype AbstractDeclarative::countCustomItemFunc(QQmlListProperty<QCustom3DItem> *list) +{ + return reinterpret_cast<AbstractDeclarative *>(list->data)->m_controller->m_customItems.size(); +} + +QCustom3DItem *AbstractDeclarative::atCustomItemFunc(QQmlListProperty<QCustom3DItem> *list, + qsizetype index) +{ + return reinterpret_cast<AbstractDeclarative *>(list->data)->m_controller->m_customItems.at(index); +} + +void AbstractDeclarative::clearCustomItemFunc(QQmlListProperty<QCustom3DItem> *list) +{ + AbstractDeclarative *decl = reinterpret_cast<AbstractDeclarative *>(list->data); + decl->removeCustomItems(); +} + +void AbstractDeclarative::setSharedController(Abstract3DController *controller) +{ + Q_ASSERT(controller); + m_controller = controller; + m_controller->m_qml = this; + + if (!m_controller->isOpenGLES()) + m_samples = 4; + setAntialiasing(m_samples > 0); + + // Reset default theme, as the default C++ theme is Q3DTheme, not DeclarativeTheme3D. + DeclarativeTheme3D *defaultTheme = new DeclarativeTheme3D; + defaultTheme->d_ptr->setDefaultTheme(true); + defaultTheme->setType(Q3DTheme::ThemeQt); + m_controller->setActiveTheme(defaultTheme); + + QObject::connect(m_controller.data(), &Abstract3DController::shadowQualityChanged, this, + &AbstractDeclarative::handleShadowQualityChange); + QObject::connect(m_controller.data(), &Abstract3DController::activeInputHandlerChanged, this, + &AbstractDeclarative::inputHandlerChanged); + QObject::connect(m_controller.data(), &Abstract3DController::activeThemeChanged, this, + &AbstractDeclarative::themeChanged); + QObject::connect(m_controller.data(), &Abstract3DController::selectionModeChanged, this, + &AbstractDeclarative::handleSelectionModeChange); + QObject::connect(m_controller.data(), &Abstract3DController::elementSelected, this, + &AbstractDeclarative::handleSelectedElementChange); + + QObject::connect(m_controller.data(), &Abstract3DController::axisXChanged, this, + &AbstractDeclarative::handleAxisXChanged); + QObject::connect(m_controller.data(), &Abstract3DController::axisYChanged, this, + &AbstractDeclarative::handleAxisYChanged); + QObject::connect(m_controller.data(), &Abstract3DController::axisZChanged, this, + &AbstractDeclarative::handleAxisZChanged); + + QObject::connect(m_controller.data(), &Abstract3DController::measureFpsChanged, this, + &AbstractDeclarative::measureFpsChanged); + QObject::connect(m_controller.data(), &Abstract3DController::currentFpsChanged, this, + &AbstractDeclarative::currentFpsChanged); + + QObject::connect(m_controller.data(), &Abstract3DController::orthoProjectionChanged, this, + &AbstractDeclarative::orthoProjectionChanged); + + QObject::connect(m_controller.data(), &Abstract3DController::aspectRatioChanged, this, + &AbstractDeclarative::aspectRatioChanged); + QObject::connect(m_controller.data(), &Abstract3DController::optimizationHintsChanged, this, + &AbstractDeclarative::handleOptimizationHintChange); + QObject::connect(m_controller.data(), &Abstract3DController::polarChanged, this, + &AbstractDeclarative::polarChanged); + QObject::connect(m_controller.data(), &Abstract3DController::radialLabelOffsetChanged, this, + &AbstractDeclarative::radialLabelOffsetChanged); + QObject::connect(m_controller.data(), &Abstract3DController::horizontalAspectRatioChanged, this, + &AbstractDeclarative::horizontalAspectRatioChanged); + QObject::connect(m_controller.data(), &Abstract3DController::reflectionChanged, this, + &AbstractDeclarative::reflectionChanged); + QObject::connect(m_controller.data(), &Abstract3DController::reflectivityChanged, this, + &AbstractDeclarative::reflectivityChanged); + QObject::connect(m_controller.data(), &Abstract3DController::localeChanged, this, + &AbstractDeclarative::localeChanged); + QObject::connect(m_controller.data(), &Abstract3DController::queriedGraphPositionChanged, this, + &AbstractDeclarative::queriedGraphPositionChanged); + QObject::connect(m_controller.data(), &Abstract3DController::marginChanged, this, + &AbstractDeclarative::marginChanged); +} + +void AbstractDeclarative::activateOpenGLContext(QQuickWindow *window) +{ + // We can assume we are not in middle of AbstractDeclarative destructor when we are here, + // since m_context creation is always done when this function is called from + // synchDataToRenderer(), which blocks main thread -> no need to mutex. + if (!m_contextOrStateStore || !m_qtContext || m_contextWindow != window) { + QOpenGLContext *currentContext = QOpenGLContext::currentContext(); + + // Note: Changing graph to different window when using multithreaded renderer will break! + + delete m_contextOrStateStore; + + m_contextThread = QThread::currentThread(); + m_contextWindow = window; + m_qtContext = currentContext; + +#ifdef USE_SHARED_CONTEXT + m_context = new QOpenGLContext(); + m_context->setFormat(m_qtContext->format()); + m_context->setShareContext(m_qtContext); + m_context->create(); + m_context->makeCurrent(window); +#else + // Shared contexts don't work properly in some platforms, so just store the + // context state on those + m_stateStore = new GLStateStore(QOpenGLContext::currentContext()); + m_stateStore->storeGLState(); +#endif + m_controller->initializeOpenGL(); + + // Make sure context / state store gets deleted. + QObject::connect(m_contextThread, &QThread::finished, this, + &AbstractDeclarative::destroyContext, Qt::DirectConnection); + } else { +#ifdef USE_SHARED_CONTEXT + m_context->makeCurrent(window); +#else + m_stateStore->storeGLState(); +#endif + } +} + +void AbstractDeclarative::doneOpenGLContext(QQuickWindow *window) +{ +#ifdef USE_SHARED_CONTEXT + m_qtContext->makeCurrent(window); +#else + Q_UNUSED(window); + m_stateStore->restoreGLState(); +#endif +} + +void AbstractDeclarative::synchDataToRenderer() +{ + QQuickWindow *win = window(); + activateOpenGLContext(win); + m_controller->synchDataToRenderer(); + doneOpenGLContext(win); +} + +int AbstractDeclarative::msaaSamples() const +{ + if (m_renderMode == RenderIndirect) + return m_samples; + else + return m_windowSamples; +} + +void AbstractDeclarative::setMsaaSamples(int samples) +{ + if (m_renderMode != RenderIndirect) { + qWarning("Multisampling cannot be adjusted in this render mode"); + } else { + if (m_controller->isOpenGLES()) { + if (samples > 0) + qWarning("Multisampling is not supported in OpenGL ES2"); + } else if (m_samples != samples) { + m_samples = samples; + setAntialiasing(m_samples > 0); + emit msaaSamplesChanged(samples); + update(); + } + } +} + +void AbstractDeclarative::handleWindowChanged(QQuickWindow *window) +{ + checkWindowList(window); + if (!window) + return; + +#if defined(Q_OS_MACOS) + bool previousVisibility = window->isVisible(); + // Enable touch events for Mac touchpads + window->setVisible(true); + typedef void * (*EnableTouch)(QWindow*, bool); + EnableTouch enableTouch = + (EnableTouch)QGuiApplication::platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow"); + if (enableTouch) + enableTouch(window, true); + window->setVisible(previousVisibility); +#endif + + connect(window, &QObject::destroyed, this, &AbstractDeclarative::windowDestroyed); + + int oldWindowSamples = m_windowSamples; + m_windowSamples = window->format().samples(); + if (m_windowSamples < 0) + m_windowSamples = 0; + + connect(window, &QQuickWindow::beforeSynchronizing, + this, &AbstractDeclarative::synchDataToRenderer, + Qt::DirectConnection); + + if (m_renderMode == RenderDirectToBackground_NoClear + || m_renderMode == RenderDirectToBackground) { + connect(window, &QQuickWindow::beforeRenderPassRecording, this, &AbstractDeclarative::render, + Qt::DirectConnection); + setAntialiasing(m_windowSamples > 0); + if (m_windowSamples != oldWindowSamples) + emit msaaSamplesChanged(m_windowSamples); + } + + connect(m_controller.data(), &Abstract3DController::needRender, window, &QQuickWindow::update); + + updateWindowParameters(); + +#if defined(Q_OS_IOS) + // Scenegraph render cycle in iOS sometimes misses update after beforeSynchronizing signal. + // This ensures we don't end up displaying the graph without any data, in case update is + // skipped after synchDataToRenderer. + QTimer::singleShot(0, window, SLOT(update())); +#endif +} + +void AbstractDeclarative::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + QQuickItem::geometryChange(newGeometry, oldGeometry); + + m_cachedGeometry = newGeometry; + + updateWindowParameters(); +} + +void AbstractDeclarative::itemChange(ItemChange change, const ItemChangeData & value) +{ + QQuickItem::itemChange(change, value); + updateWindowParameters(); +} + +void AbstractDeclarative::updateWindowParameters() +{ + const QMutexLocker locker(&m_mutex); + + // Update the device pixel ratio, window size and bounding box + QQuickWindow *win = window(); + if (win && !m_controller.isNull()) { + Q3DScene *scene = m_controller->scene(); + if (win->devicePixelRatio() != scene->devicePixelRatio()) { + scene->setDevicePixelRatio(win->devicePixelRatio()); + win->update(); + } + + bool directRender = m_renderMode == RenderDirectToBackground + || m_renderMode == RenderDirectToBackground_NoClear; + QSize windowSize; + + if (directRender) + windowSize = win->size(); + else + windowSize = m_cachedGeometry.size().toSize(); + + if (windowSize != scene->d_ptr->windowSize()) { + scene->d_ptr->setWindowSize(windowSize); + win->update(); + } + + if (directRender) { + // Origin mapping is needed when rendering directly to background + QPointF point = QQuickItem::mapToScene(QPointF(0.0, 0.0)); + scene->d_ptr->setViewport(QRect(point.x() + 0.5f, point.y() + 0.5f, + m_cachedGeometry.width() + 0.5f, + m_cachedGeometry.height() + 0.5f)); + } else { + // No translation needed when rendering to FBO + scene->d_ptr->setViewport(QRect(0.0, 0.0, m_cachedGeometry.width() + 0.5f, + m_cachedGeometry.height() + 0.5f)); + } + } +} + +void AbstractDeclarative::handleSelectionModeChange(QAbstract3DGraph::SelectionFlags mode) +{ + int intmode = int(mode); + emit selectionModeChanged(SelectionFlags(intmode)); +} + +void AbstractDeclarative::handleShadowQualityChange(QAbstract3DGraph::ShadowQuality quality) +{ + emit shadowQualityChanged(ShadowQuality(quality)); +} + +void AbstractDeclarative::handleSelectedElementChange(QAbstract3DGraph::ElementType type) +{ + emit selectedElementChanged(ElementType(type)); +} + +void AbstractDeclarative::handleOptimizationHintChange(QAbstract3DGraph::OptimizationHints hints) +{ + int intHints = int(hints); + emit optimizationHintsChanged(OptimizationHints(intHints)); +} + +void AbstractDeclarative::render() +{ + updateWindowParameters(); + + // If we're not rendering directly to the background, return + if (m_renderMode != RenderDirectToBackground && m_renderMode != RenderDirectToBackground_NoClear) + return; + + // Clear the background once per window as that is not done by default + QQuickWindow *win = window(); + win->beginExternalCommands(); + activateOpenGLContext(win); + + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + + if (funcs && isVisible()) { + funcs->glDepthMask(GL_TRUE); + funcs->glEnable(GL_DEPTH_TEST); + funcs->glDepthFunc(GL_LESS); + funcs->glEnable(GL_CULL_FACE); + funcs->glCullFace(GL_BACK); + funcs->glDisable(GL_BLEND); + + m_controller->render(); + + funcs->glEnable(GL_BLEND); + } + + doneOpenGLContext(win); + win->endExternalCommands(); +} + +QAbstract3DInputHandler* AbstractDeclarative::inputHandler() const +{ + return m_controller->activeInputHandler(); +} + +void AbstractDeclarative::setInputHandler(QAbstract3DInputHandler *inputHandler) +{ + m_controller->setActiveInputHandler(inputHandler); +} + +void AbstractDeclarative::mouseDoubleClickEvent(QMouseEvent *event) +{ + m_controller->mouseDoubleClickEvent(event); +} + +void AbstractDeclarative::touchEvent(QTouchEvent *event) +{ + m_controller->touchEvent(event); + window()->update(); +} + +void AbstractDeclarative::mousePressEvent(QMouseEvent *event) +{ + QPoint mousePos = event->pos(); + m_controller->mousePressEvent(event, mousePos); +} + +void AbstractDeclarative::mouseReleaseEvent(QMouseEvent *event) +{ + QPoint mousePos = event->pos(); + m_controller->mouseReleaseEvent(event, mousePos); +} + +void AbstractDeclarative::mouseMoveEvent(QMouseEvent *event) +{ + QPoint mousePos = event->pos(); + m_controller->mouseMoveEvent(event, mousePos); +} + +#if QT_CONFIG(wheelevent) +void AbstractDeclarative::wheelEvent(QWheelEvent *event) +{ + m_controller->wheelEvent(event); +} +#endif + +void AbstractDeclarative::checkWindowList(QQuickWindow *window) +{ + QQuickWindow *oldWindow = graphWindowList.value(this); + graphWindowList[this] = window; + + if (oldWindow != window && oldWindow) { + QObject::disconnect(oldWindow, &QObject::destroyed, this, + &AbstractDeclarative::windowDestroyed); + QObject::disconnect(oldWindow, &QQuickWindow::beforeSynchronizing, this, + &AbstractDeclarative::synchDataToRenderer); + QObject::disconnect(oldWindow, &QQuickWindow::beforeRenderPassRecording, this, + &AbstractDeclarative::render); + if (!m_controller.isNull()) { + QObject::disconnect(m_controller.data(), &Abstract3DController::needRender, + oldWindow, &QQuickWindow::update); + } + } + + QList<QQuickWindow *> windowList; + const auto graphs = graphWindowList.keys(); + for (AbstractDeclarative *graph : graphs) { + if (graph->m_renderMode == RenderDirectToBackground + || graph->m_renderMode == RenderDirectToBackground_NoClear) { + windowList.append(graphWindowList.value(graph)); + } + } + + if (!window) { + graphWindowList.remove(this); + return; + } +} + +void AbstractDeclarative::setMeasureFps(bool enable) +{ + m_controller->setMeasureFps(enable); +} + +bool AbstractDeclarative::measureFps() const +{ + return m_controller->measureFps(); +} + +qreal AbstractDeclarative::currentFps() const +{ + return m_controller->currentFps(); +} + +void AbstractDeclarative::setOrthoProjection(bool enable) +{ + m_controller->setOrthoProjection(enable); +} + +bool AbstractDeclarative::isOrthoProjection() const +{ + return m_controller->isOrthoProjection(); +} + +AbstractDeclarative::ElementType AbstractDeclarative::selectedElement() const +{ + return ElementType(m_controller->selectedElement()); +} + +void AbstractDeclarative::setAspectRatio(qreal ratio) +{ + m_controller->setAspectRatio(ratio); +} + +qreal AbstractDeclarative::aspectRatio() const +{ + return m_controller->aspectRatio(); +} + +void AbstractDeclarative::setOptimizationHints(OptimizationHints hints) +{ + int intmode = int(hints); + m_controller->setOptimizationHints(QAbstract3DGraph::OptimizationHints(intmode)); +} + +AbstractDeclarative::OptimizationHints AbstractDeclarative::optimizationHints() const +{ + int intmode = int(m_controller->optimizationHints()); + return OptimizationHints(intmode); +} + +void AbstractDeclarative::setPolar(bool enable) +{ + m_controller->setPolar(enable); +} + +bool AbstractDeclarative::isPolar() const +{ + return m_controller->isPolar(); +} + +void AbstractDeclarative::setRadialLabelOffset(float offset) +{ + m_controller->setRadialLabelOffset(offset); +} + +float AbstractDeclarative::radialLabelOffset() const +{ + return m_controller->radialLabelOffset(); +} + +void AbstractDeclarative::setHorizontalAspectRatio(qreal ratio) +{ + m_controller->setHorizontalAspectRatio(ratio); +} + +qreal AbstractDeclarative::horizontalAspectRatio() const +{ + return m_controller->horizontalAspectRatio(); +} + +void AbstractDeclarative::setReflection(bool enable) +{ + m_controller->setReflection(enable); +} + +bool AbstractDeclarative::isReflection() const +{ + return m_controller->reflection(); +} + +void AbstractDeclarative::setReflectivity(qreal reflectivity) +{ + m_controller->setReflectivity(reflectivity); +} + +qreal AbstractDeclarative::reflectivity() const +{ + return m_controller->reflectivity(); +} + +void AbstractDeclarative::setLocale(const QLocale &locale) +{ + m_controller->setLocale(locale); +} + +QLocale AbstractDeclarative::locale() const +{ + return m_controller->locale(); +} + +QVector3D AbstractDeclarative::queriedGraphPosition() const +{ + return m_controller->queriedGraphPosition(); +} + +void AbstractDeclarative::setMargin(qreal margin) +{ + m_controller->setMargin(margin); +} + +qreal AbstractDeclarative::margin() const +{ + return m_controller->margin(); +} + +void AbstractDeclarative::windowDestroyed(QObject *obj) +{ + // Remove destroyed window from window lists + QQuickWindow *win = static_cast<QQuickWindow *>(obj); + QQuickWindow *oldWindow = graphWindowList.value(this); + + if (win == oldWindow) + graphWindowList.remove(this); +} + +void AbstractDeclarative::destroyContext() +{ + if (m_contextThread && m_contextThread != m_mainThread) { + if (m_contextOrStateStore) + m_contextOrStateStore->deleteLater(); + } else { + delete m_contextOrStateStore; + } + m_contextOrStateStore = 0; + + if (m_contextThread) { + QObject::disconnect(m_contextThread, &QThread::finished, this, + &AbstractDeclarative::destroyContext); + m_contextThread = 0; + } +} + +QT_END_NAMESPACE |