diff options
Diffstat (limited to 'src/datavisualizationqml')
39 files changed, 5606 insertions, 0 deletions
diff --git a/src/datavisualizationqml/CMakeLists.txt b/src/datavisualizationqml/CMakeLists.txt new file mode 100644 index 00000000..110a5ef0 --- /dev/null +++ b/src/datavisualizationqml/CMakeLists.txt @@ -0,0 +1,66 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +set(qml_files + "designer/Bars3DSpecifics.qml" + "designer/Scatter3DSpecifics.qml" + "designer/Surface3DSpecifics.qml" + "designer/default/Bars3D.qml" + "designer/default/Scatter3D.qml" + "designer/default/Surface3D.qml" +) + +set(resources + "designer/qtdatavisualization.metainfo" + "designer/images/bars3d-icon.png" + "designer/images/bars3d-icon16.png" + "designer/images/scatter3d-icon.png" + "designer/images/scatter3d-icon16.png" + "designer/images/surface3d-icon.png" + "designer/images/surface3d-icon16.png" +) + +set_source_files_properties(${qml_files} PROPERTIES + QT_QML_SKIP_QMLDIR_ENTRY TRUE +) + +qt_internal_add_qml_module(DataVisualizationQml + URI "QtDataVisualization" + VERSION "${PROJECT_VERSION}" + PAST_MAJOR_VERSIONS 1 + DEPENDENCIES + QtQuick + SOURCES + abstractdeclarative.cpp abstractdeclarative_p.h + colorgradient.cpp colorgradient_p.h + declarativebars.cpp declarativebars_p.h + declarativecolor.cpp declarativecolor_p.h + declarativerendernode.cpp declarativerendernode_p.h + declarativescatter.cpp declarativescatter_p.h + declarativescene.cpp declarativescene_p.h + declarativeseries.cpp declarativeseries_p.h + declarativesurface.cpp declarativesurface_p.h + declarativetheme.cpp declarativetheme_p.h + enumtostringmap.cpp enumtostringmap_p.h + foreigntypes_p.h + glstatestore.cpp glstatestore_p.h + NO_PCH_SOURCES + declarativetheme.cpp # undef QT_NO_FOREACH + QML_FILES + ${qml_files} + RESOURCES + ${resources} + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::OpenGL + Qt::Qml + Qt::Quick + Qt::DataVisualizationPrivate + NO_GENERATE_CPP_EXPORTS +) + +qt_internal_extend_target(DataVisualizationQml CONDITION MACOS + PUBLIC_LIBRARIES + Qt::GuiPrivate +) 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 diff --git a/src/datavisualizationqml/abstractdeclarative_p.h b/src/datavisualizationqml/abstractdeclarative_p.h new file mode 100644 index 00000000..090738c5 --- /dev/null +++ b/src/datavisualizationqml/abstractdeclarative_p.h @@ -0,0 +1,297 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef ABSTRACTDECLARATIVE_P_H +#define ABSTRACTDECLARATIVE_P_H + +#include "declarativescene_p.h" + +#include <private/datavisualizationglobal_p.h> +#include <private/abstract3dcontroller_p.h> +#include <QtDataVisualization/private/abstractdeclarativeinterface_p.h> + +#include <QtQuick/QQuickItem> +#include <QtCore/QPointer> +#include <QtCore/QThread> +#include <QtCore/QMutex> +#include <QtCore/QSharedPointer> + +class GLStateStore; + +QT_BEGIN_NAMESPACE + +class AbstractDeclarative : public QQuickItem, public AbstractDeclarativeInterface +{ + Q_OBJECT + Q_PROPERTY(SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged) + Q_PROPERTY(ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged) + Q_PROPERTY(bool shadowsSupported READ shadowsSupported NOTIFY shadowsSupportedChanged) + Q_PROPERTY(int msaaSamples READ msaaSamples WRITE setMsaaSamples NOTIFY msaaSamplesChanged) + Q_PROPERTY(Declarative3DScene* scene READ scene NOTIFY sceneChanged) + Q_PROPERTY(QAbstract3DInputHandler* inputHandler READ inputHandler WRITE setInputHandler NOTIFY inputHandlerChanged) + Q_PROPERTY(Q3DTheme* theme READ theme WRITE setTheme NOTIFY themeChanged) + Q_PROPERTY(RenderingMode renderingMode READ renderingMode WRITE setRenderingMode NOTIFY renderingModeChanged) + Q_PROPERTY(bool measureFps READ measureFps WRITE setMeasureFps NOTIFY measureFpsChanged REVISION(1, 1)) + Q_PROPERTY(qreal currentFps READ currentFps NOTIFY currentFpsChanged REVISION(1, 1)) + Q_PROPERTY(QQmlListProperty<QCustom3DItem> customItemList READ customItemList REVISION(1, 1)) + Q_PROPERTY(bool orthoProjection READ isOrthoProjection WRITE setOrthoProjection NOTIFY orthoProjectionChanged REVISION(1, 1)) + Q_PROPERTY(ElementType selectedElement READ selectedElement NOTIFY selectedElementChanged REVISION(1, 1)) + Q_PROPERTY(qreal aspectRatio READ aspectRatio WRITE setAspectRatio NOTIFY aspectRatioChanged REVISION(1, 1)) + Q_PROPERTY(OptimizationHints optimizationHints READ optimizationHints WRITE setOptimizationHints NOTIFY optimizationHintsChanged REVISION(1, 1)) + Q_PROPERTY(bool polar READ isPolar WRITE setPolar NOTIFY polarChanged REVISION(1, 2)) + Q_PROPERTY(float radialLabelOffset READ radialLabelOffset WRITE setRadialLabelOffset NOTIFY radialLabelOffsetChanged REVISION(1, 2)) + Q_PROPERTY(qreal horizontalAspectRatio READ horizontalAspectRatio WRITE setHorizontalAspectRatio NOTIFY horizontalAspectRatioChanged REVISION(1, 2)) + Q_PROPERTY(bool reflection READ isReflection WRITE setReflection NOTIFY reflectionChanged REVISION(1, 2)) + Q_PROPERTY(qreal reflectivity READ reflectivity WRITE setReflectivity NOTIFY reflectivityChanged REVISION(1, 2)) + Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged REVISION(1, 2)) + Q_PROPERTY(QVector3D queriedGraphPosition READ queriedGraphPosition NOTIFY queriedGraphPositionChanged REVISION(1, 2)) + Q_PROPERTY(qreal margin READ margin WRITE setMargin NOTIFY marginChanged REVISION(1, 2)) + + QML_NAMED_ELEMENT(AbstractGraph3D) + QML_ADDED_IN_VERSION(1, 0) + QML_UNCREATABLE("Trying to create uncreatable: AbstractGraph3D.") + +public: + enum SelectionFlag { + SelectionNone = 0, + SelectionItem = 1, + SelectionRow = 2, + SelectionItemAndRow = SelectionItem | SelectionRow, + SelectionColumn = 4, + SelectionItemAndColumn = SelectionItem | SelectionColumn, + SelectionRowAndColumn = SelectionRow | SelectionColumn, + SelectionItemRowAndColumn = SelectionItem | SelectionRow | SelectionColumn, + SelectionSlice = 8, + SelectionMultiSeries = 16 + }; + Q_DECLARE_FLAGS(SelectionFlags, SelectionFlag) + + enum ShadowQuality { + ShadowQualityNone = 0, + ShadowQualityLow, + ShadowQualityMedium, + ShadowQualityHigh, + ShadowQualitySoftLow, + ShadowQualitySoftMedium, + ShadowQualitySoftHigh + }; + + enum ElementType { + ElementNone = 0, + ElementSeries, + ElementAxisXLabel, + ElementAxisYLabel, + ElementAxisZLabel, + ElementCustomItem + }; + + enum RenderingMode { + RenderDirectToBackground = 0, + RenderDirectToBackground_NoClear, + RenderIndirect + }; + + enum OptimizationHint { + OptimizationDefault = 0, + OptimizationStatic = 1 + }; + Q_DECLARE_FLAGS(OptimizationHints, OptimizationHint) + + Q_ENUM(ShadowQuality) + Q_ENUM(RenderingMode) + Q_ENUM(ElementType) + Q_ENUM(SelectionFlag) + Q_ENUM(OptimizationHint) + Q_FLAGS(SelectionFlag SelectionFlags) + Q_FLAGS(OptimizationHint OptimizationHints) + +public: + explicit AbstractDeclarative(QQuickItem *parent = 0); + virtual ~AbstractDeclarative(); + + virtual void setRenderingMode(RenderingMode mode); + virtual AbstractDeclarative::RenderingMode renderingMode() const; + + virtual void setSelectionMode(SelectionFlags mode); + virtual AbstractDeclarative::SelectionFlags selectionMode() const; + + virtual void setShadowQuality(ShadowQuality quality); + virtual AbstractDeclarative::ShadowQuality shadowQuality() const; + + virtual AbstractDeclarative::ElementType selectedElement() const; + + virtual bool shadowsSupported() const; + + virtual void setMsaaSamples(int samples); + virtual int msaaSamples() const; + + virtual Declarative3DScene *scene() const; + + virtual QAbstract3DInputHandler *inputHandler() const; + virtual void setInputHandler(QAbstract3DInputHandler *inputHandler); + + virtual void setTheme(Q3DTheme *theme); + virtual Q3DTheme *theme() const; + + Q_INVOKABLE virtual void clearSelection(); + + Q_REVISION(6, 3) Q_INVOKABLE virtual bool hasSeries(QAbstract3DSeries *series); + + Q_REVISION(1, 1) Q_INVOKABLE virtual int addCustomItem(QCustom3DItem *item); + Q_REVISION(1, 1) Q_INVOKABLE virtual void removeCustomItems(); + Q_REVISION(1, 1) Q_INVOKABLE virtual void removeCustomItem(QCustom3DItem *item); + Q_REVISION(1, 1) Q_INVOKABLE virtual void removeCustomItemAt(const QVector3D &position); + Q_REVISION(1, 1) Q_INVOKABLE virtual void releaseCustomItem(QCustom3DItem *item); + + Q_REVISION(1, 1) Q_INVOKABLE virtual int selectedLabelIndex() const; + Q_REVISION(1, 1) Q_INVOKABLE virtual QAbstract3DAxis *selectedAxis() const; + + Q_REVISION(1, 1) Q_INVOKABLE virtual int selectedCustomItemIndex() const; + Q_REVISION(1, 1) Q_INVOKABLE virtual QCustom3DItem *selectedCustomItem() const; + + QQmlListProperty<QCustom3DItem> customItemList(); + static void appendCustomItemFunc(QQmlListProperty<QCustom3DItem> *list, + QCustom3DItem *item); + static qsizetype countCustomItemFunc(QQmlListProperty<QCustom3DItem> *list); + static QCustom3DItem *atCustomItemFunc(QQmlListProperty<QCustom3DItem> *list, qsizetype index); + static void clearCustomItemFunc(QQmlListProperty<QCustom3DItem> *list); + + void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; + + void setSharedController(Abstract3DController *controller); + // Used to synch up data model from controller to renderer while main thread is locked + void synchDataToRenderer(); + void render(); + + void activateOpenGLContext(QQuickWindow *window); + void doneOpenGLContext(QQuickWindow *window); + + void checkWindowList(QQuickWindow *window); + + void setMeasureFps(bool enable); + bool measureFps() const; + qreal currentFps() const; + + void setOrthoProjection(bool enable); + bool isOrthoProjection() const; + + void setAspectRatio(qreal ratio); + qreal aspectRatio() const; + + void setOptimizationHints(OptimizationHints hints); + OptimizationHints optimizationHints() const; + + void setPolar(bool enable); + bool isPolar() const; + + void setRadialLabelOffset(float offset); + float radialLabelOffset() const; + + void setHorizontalAspectRatio(qreal ratio); + qreal horizontalAspectRatio() const; + + void setReflection(bool enable); + bool isReflection() const; + + void setReflectivity(qreal reflectivity); + qreal reflectivity() const; + + void setLocale(const QLocale &locale); + QLocale locale() const; + + QVector3D queriedGraphPosition() const; + + void setMargin(qreal margin); + qreal margin() const; + + QMutex *mutex() { return &m_mutex; } + + bool isReady() const override { return isComponentComplete(); } + +public Q_SLOTS: + virtual void handleAxisXChanged(QAbstract3DAxis *axis) = 0; + virtual void handleAxisYChanged(QAbstract3DAxis *axis) = 0; + virtual void handleAxisZChanged(QAbstract3DAxis *axis) = 0; + void windowDestroyed(QObject *obj); + void destroyContext(); + +protected: + void mouseDoubleClickEvent(QMouseEvent *event) override; + void touchEvent(QTouchEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; +#if QT_CONFIG(wheelevent) + void wheelEvent(QWheelEvent *event) override; +#endif + virtual void handleWindowChanged(QQuickWindow *win); + void itemChange(ItemChange change, const ItemChangeData &value) override; + virtual void updateWindowParameters(); + virtual void handleSelectionModeChange(QAbstract3DGraph::SelectionFlags mode); + virtual void handleShadowQualityChange(QAbstract3DGraph::ShadowQuality quality); + virtual void handleSelectedElementChange(QAbstract3DGraph::ElementType type); + virtual void handleOptimizationHintChange(QAbstract3DGraph::OptimizationHints hints); + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override; + +Q_SIGNALS: + void selectionModeChanged(AbstractDeclarative::SelectionFlags mode); + void shadowQualityChanged(AbstractDeclarative::ShadowQuality quality); + void shadowsSupportedChanged(bool supported); + void msaaSamplesChanged(int samples); + void sceneChanged(Q3DScene *scene); + void inputHandlerChanged(QAbstract3DInputHandler *inputHandler); + void themeChanged(Q3DTheme *theme); + void renderingModeChanged(AbstractDeclarative::RenderingMode mode); + Q_REVISION(1, 1) void measureFpsChanged(bool enabled); + Q_REVISION(1, 1) void currentFpsChanged(qreal fps); + Q_REVISION(1, 1) void selectedElementChanged(AbstractDeclarative::ElementType type); + Q_REVISION(1, 1) void orthoProjectionChanged(bool enabled); + Q_REVISION(1, 1) void aspectRatioChanged(qreal ratio); + Q_REVISION(1, 1) void optimizationHintsChanged(AbstractDeclarative::OptimizationHints hints); + Q_REVISION(1, 2) void polarChanged(bool enabled); + Q_REVISION(1, 2) void radialLabelOffsetChanged(float offset); + Q_REVISION(1, 2) void horizontalAspectRatioChanged(qreal ratio); + Q_REVISION(1, 2) void reflectionChanged(bool enabled); + Q_REVISION(1, 2) void reflectivityChanged(qreal reflectivity); + Q_REVISION(1, 2) void localeChanged(const QLocale &locale); + Q_REVISION(1, 2) void queriedGraphPositionChanged(const QVector3D &data); + Q_REVISION(1, 2) void marginChanged(qreal margin); + +protected: + QSharedPointer<QMutex> m_nodeMutex; + +private: + QPointer<Abstract3DController> m_controller; + QRectF m_cachedGeometry; + QPointer<QQuickWindow> m_contextWindow; + AbstractDeclarative::RenderingMode m_renderMode; + int m_samples; + int m_windowSamples; + QSize m_initialisedSize; + union { + QObject *m_contextOrStateStore; + QOpenGLContext *m_context; + GLStateStore *m_stateStore; + }; + QPointer<QOpenGLContext> m_qtContext; + QThread *m_mainThread; + QThread *m_contextThread; + bool m_runningInDesigner; + QMutex m_mutex; +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractDeclarative::SelectionFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractDeclarative::OptimizationHints) + +QT_END_NAMESPACE + +#endif diff --git a/src/datavisualizationqml/colorgradient.cpp b/src/datavisualizationqml/colorgradient.cpp new file mode 100644 index 00000000..c00c43aa --- /dev/null +++ b/src/datavisualizationqml/colorgradient.cpp @@ -0,0 +1,62 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "colorgradient_p.h" + +QT_BEGIN_NAMESPACE + +ColorGradientStop::ColorGradientStop(QObject *parent) + : QObject(parent) +{ +} + +qreal ColorGradientStop::position() const +{ + return m_position; +} + +void ColorGradientStop::setPosition(qreal position) +{ + m_position = position; + updateGradient(); + emit positionChanged(position); +} + +QColor ColorGradientStop::color() const +{ + return m_color; +} + +void ColorGradientStop::setColor(const QColor &color) +{ + m_color = color; + updateGradient(); + emit colorChanged(color); +} + +void ColorGradientStop::updateGradient() +{ + if (ColorGradient *grad = qobject_cast<ColorGradient*>(parent())) + grad->doUpdate(); +} + +ColorGradient::ColorGradient(QObject *parent) +: QObject(parent) +{ +} + +ColorGradient::~ColorGradient() +{ +} + +QQmlListProperty<ColorGradientStop> ColorGradient::stops() +{ + return QQmlListProperty<ColorGradientStop>(this, &m_stops); +} + +void ColorGradient::doUpdate() +{ + emit updated(); +} + +QT_END_NAMESPACE diff --git a/src/datavisualizationqml/colorgradient_p.h b/src/datavisualizationqml/colorgradient_p.h new file mode 100644 index 00000000..5e5d0e51 --- /dev/null +++ b/src/datavisualizationqml/colorgradient_p.h @@ -0,0 +1,79 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef COLORGRADIENT_P_H +#define COLORGRADIENT_P_H + +#include <private/datavisualizationglobal_p.h> +#include <QtGui/QColor> +#include <QtQml/qqml.h> + +QT_BEGIN_NAMESPACE + +class ColorGradientStop : public QObject +{ + Q_OBJECT + + Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) + + QML_ELEMENT + QML_ADDED_IN_VERSION(1, 0) + +public: + ColorGradientStop(QObject *parent = 0); + + qreal position() const; + void setPosition(qreal position); + + QColor color() const; + void setColor(const QColor &color); + +Q_SIGNALS: + void positionChanged(qreal position); + void colorChanged(const QColor &color); + +private: + void updateGradient(); + +private: + qreal m_position; + QColor m_color; +}; + +class ColorGradient : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QQmlListProperty<ColorGradientStop> stops READ stops) + Q_CLASSINFO("DefaultProperty", "stops") + + QML_ELEMENT + QML_ADDED_IN_VERSION(1, 0) + +public: + ColorGradient(QObject *parent = 0); + ~ColorGradient(); + + QQmlListProperty<ColorGradientStop> stops(); + + void doUpdate(); + QList<ColorGradientStop *> m_stops; + +Q_SIGNALS: + void updated(); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/datavisualizationqml/declarativebars.cpp b/src/datavisualizationqml/declarativebars.cpp new file mode 100644 index 00000000..1cba987a --- /dev/null +++ b/src/datavisualizationqml/declarativebars.cpp @@ -0,0 +1,220 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "declarativebars_p.h" +#include <QtCore/QMutexLocker> + +QT_BEGIN_NAMESPACE + +DeclarativeBars::DeclarativeBars(QQuickItem *parent) + : AbstractDeclarative(parent), + m_barsController(0) +{ + setAcceptedMouseButtons(Qt::AllButtons); + + // Create the shared component on the main GUI thread. + m_barsController = new Bars3DController(boundingRect().toRect(), new Declarative3DScene); + AbstractDeclarative::setSharedController(m_barsController); + + QObject::connect(m_barsController, &Bars3DController::primarySeriesChanged, + this, &DeclarativeBars::primarySeriesChanged); + QObject::connect(m_barsController, &Bars3DController::selectedSeriesChanged, + this, &DeclarativeBars::selectedSeriesChanged); +} + +DeclarativeBars::~DeclarativeBars() +{ + QMutexLocker locker(m_nodeMutex.data()); + const QMutexLocker locker2(mutex()); + delete m_barsController; +} + +QCategory3DAxis *DeclarativeBars::rowAxis() const +{ + return static_cast<QCategory3DAxis *>(m_barsController->axisZ()); +} + +void DeclarativeBars::setRowAxis(QCategory3DAxis *axis) +{ + m_barsController->setAxisZ(axis); +} + +QValue3DAxis *DeclarativeBars::valueAxis() const +{ + return static_cast<QValue3DAxis *>(m_barsController->axisY()); +} + +void DeclarativeBars::setValueAxis(QValue3DAxis *axis) +{ + m_barsController->setAxisY(axis); +} + +QCategory3DAxis *DeclarativeBars::columnAxis() const +{ + return static_cast<QCategory3DAxis *>(m_barsController->axisX()); +} + +void DeclarativeBars::setColumnAxis(QCategory3DAxis *axis) +{ + m_barsController->setAxisX(axis); +} + +void DeclarativeBars::setMultiSeriesUniform(bool uniform) +{ + if (uniform != isMultiSeriesUniform()) { + m_barsController->setMultiSeriesScaling(uniform); + emit multiSeriesUniformChanged(uniform); + } +} + +bool DeclarativeBars::isMultiSeriesUniform() const +{ + return m_barsController->multiSeriesScaling(); +} + +void DeclarativeBars::setBarThickness(float thicknessRatio) +{ + if (thicknessRatio != barThickness()) { + m_barsController->setBarSpecs(GLfloat(thicknessRatio), barSpacing(), + isBarSpacingRelative()); + emit barThicknessChanged(thicknessRatio); + } +} + +float DeclarativeBars::barThickness() const +{ + return m_barsController->barThickness(); +} + +void DeclarativeBars::setBarSpacing(const QSizeF &spacing) +{ + if (spacing != barSpacing()) { + m_barsController->setBarSpecs(GLfloat(barThickness()), spacing, isBarSpacingRelative()); + emit barSpacingChanged(spacing); + } +} + +QSizeF DeclarativeBars::barSpacing() const +{ + return m_barsController->barSpacing(); +} + +void DeclarativeBars::setBarSpacingRelative(bool relative) +{ + if (relative != isBarSpacingRelative()) { + m_barsController->setBarSpecs(GLfloat(barThickness()), barSpacing(), relative); + emit barSpacingRelativeChanged(relative); + } +} + +bool DeclarativeBars::isBarSpacingRelative() const +{ + return m_barsController->isBarSpecRelative(); +} + +void DeclarativeBars::setBarSeriesMargin(const QSizeF &margin) +{ + if (margin != barSeriesMargin()) { + m_barsController->setBarSeriesMargin(margin); + emit barSeriesMarginChanged(barSeriesMargin()); + } +} + +QSizeF DeclarativeBars::barSeriesMargin() const +{ + return m_barsController->barSeriesMargin(); +} + +QBar3DSeries *DeclarativeBars::selectedSeries() const +{ + return m_barsController->selectedSeries(); +} + +void DeclarativeBars::setFloorLevel(float level) +{ + if (level != floorLevel()) { + m_barsController->setFloorLevel(level); + emit floorLevelChanged(level); + } +} + +float DeclarativeBars::floorLevel() const +{ + return m_barsController->floorLevel(); +} + +QQmlListProperty<QBar3DSeries> DeclarativeBars::seriesList() +{ + return QQmlListProperty<QBar3DSeries>(this, this, + &DeclarativeBars::appendSeriesFunc, + &DeclarativeBars::countSeriesFunc, + &DeclarativeBars::atSeriesFunc, + &DeclarativeBars::clearSeriesFunc); +} + +void DeclarativeBars::appendSeriesFunc(QQmlListProperty<QBar3DSeries> *list, QBar3DSeries *series) +{ + reinterpret_cast<DeclarativeBars *>(list->data)->addSeries(series); +} + +qsizetype DeclarativeBars::countSeriesFunc(QQmlListProperty<QBar3DSeries> *list) +{ + return reinterpret_cast<DeclarativeBars *>(list->data)->m_barsController->barSeriesList().size(); +} + +QBar3DSeries *DeclarativeBars::atSeriesFunc(QQmlListProperty<QBar3DSeries> *list, qsizetype index) +{ + return reinterpret_cast<DeclarativeBars *>(list->data)->m_barsController->barSeriesList().at(index); +} + +void DeclarativeBars::clearSeriesFunc(QQmlListProperty<QBar3DSeries> *list) +{ + DeclarativeBars *declBars = reinterpret_cast<DeclarativeBars *>(list->data); + QList<QBar3DSeries *> realList = declBars->m_barsController->barSeriesList(); + int count = realList.size(); + for (int i = 0; i < count; i++) + declBars->removeSeries(realList.at(i)); +} + +void DeclarativeBars::addSeries(QBar3DSeries *series) +{ + m_barsController->addSeries(series); +} + +void DeclarativeBars::removeSeries(QBar3DSeries *series) +{ + m_barsController->removeSeries(series); + series->setParent(this); // Reparent as removing will leave series parentless +} + +void DeclarativeBars::insertSeries(int index, QBar3DSeries *series) +{ + m_barsController->insertSeries(index, series); +} + +void DeclarativeBars::setPrimarySeries(QBar3DSeries *series) +{ + m_barsController->setPrimarySeries(series); +} + +QBar3DSeries *DeclarativeBars::primarySeries() const +{ + return m_barsController->primarySeries(); +} + +void DeclarativeBars::handleAxisXChanged(QAbstract3DAxis *axis) +{ + emit columnAxisChanged(static_cast<QCategory3DAxis *>(axis)); +} + +void DeclarativeBars::handleAxisYChanged(QAbstract3DAxis *axis) +{ + emit valueAxisChanged(static_cast<QValue3DAxis *>(axis)); +} + +void DeclarativeBars::handleAxisZChanged(QAbstract3DAxis *axis) +{ + emit rowAxisChanged(static_cast<QCategory3DAxis *>(axis)); +} + +QT_END_NAMESPACE diff --git a/src/datavisualizationqml/declarativebars_p.h b/src/datavisualizationqml/declarativebars_p.h new file mode 100644 index 00000000..82653ab2 --- /dev/null +++ b/src/datavisualizationqml/declarativebars_p.h @@ -0,0 +1,109 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef DECLARATIVEBARS_P_H +#define DECLARATIVEBARS_P_H + +#include "abstractdeclarative_p.h" + +#include <private/datavisualizationglobal_p.h> +#include <private/bars3dcontroller_p.h> + +QT_BEGIN_NAMESPACE +class DeclarativeBars : public AbstractDeclarative +{ + Q_OBJECT + Q_PROPERTY(QCategory3DAxis *rowAxis READ rowAxis WRITE setRowAxis NOTIFY rowAxisChanged) + Q_PROPERTY(QValue3DAxis *valueAxis READ valueAxis WRITE setValueAxis NOTIFY valueAxisChanged) + Q_PROPERTY(QCategory3DAxis *columnAxis READ columnAxis WRITE setColumnAxis NOTIFY columnAxisChanged) + Q_PROPERTY(bool multiSeriesUniform READ isMultiSeriesUniform WRITE setMultiSeriesUniform NOTIFY multiSeriesUniformChanged) + Q_PROPERTY(float barThickness READ barThickness WRITE setBarThickness NOTIFY barThicknessChanged) + Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing NOTIFY barSpacingChanged) + Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative NOTIFY barSpacingRelativeChanged) + Q_PROPERTY(QSizeF barSeriesMargin READ barSeriesMargin WRITE setBarSeriesMargin NOTIFY barSeriesMarginChanged REVISION(6, 3)) + Q_PROPERTY(QQmlListProperty<QBar3DSeries> seriesList READ seriesList) + Q_PROPERTY(QBar3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged) + Q_PROPERTY(QBar3DSeries *primarySeries READ primarySeries WRITE setPrimarySeries NOTIFY primarySeriesChanged) + Q_PROPERTY(float floorLevel READ floorLevel WRITE setFloorLevel NOTIFY floorLevelChanged REVISION(1, 2)) + Q_CLASSINFO("DefaultProperty", "seriesList") + + QML_NAMED_ELEMENT(Bars3D) + QML_ADDED_IN_VERSION(1, 0) + +public: + explicit DeclarativeBars(QQuickItem *parent = 0); + ~DeclarativeBars(); + + QCategory3DAxis *rowAxis() const; + void setRowAxis(QCategory3DAxis *axis); + QValue3DAxis *valueAxis() const; + void setValueAxis(QValue3DAxis *axis); + QCategory3DAxis *columnAxis() const; + void setColumnAxis(QCategory3DAxis *axis); + + void setMultiSeriesUniform(bool uniform); + bool isMultiSeriesUniform() const; + + void setBarThickness(float thicknessRatio); + float barThickness() const; + + void setBarSpacing(const QSizeF &spacing); + QSizeF barSpacing() const; + + void setBarSpacingRelative(bool relative); + bool isBarSpacingRelative() const; + + void setBarSeriesMargin(const QSizeF &margin); + QSizeF barSeriesMargin() const; + + QQmlListProperty<QBar3DSeries> seriesList(); + static void appendSeriesFunc(QQmlListProperty<QBar3DSeries> *list, QBar3DSeries *series); + static qsizetype countSeriesFunc(QQmlListProperty<QBar3DSeries> *list); + static QBar3DSeries *atSeriesFunc(QQmlListProperty<QBar3DSeries> *list, qsizetype index); + static void clearSeriesFunc(QQmlListProperty<QBar3DSeries> *list); + Q_INVOKABLE void addSeries(QBar3DSeries *series); + Q_INVOKABLE void removeSeries(QBar3DSeries *series); + Q_INVOKABLE void insertSeries(int index, QBar3DSeries *series); + void setPrimarySeries(QBar3DSeries *series); + QBar3DSeries *primarySeries() const; + QBar3DSeries *selectedSeries() const; + + void setFloorLevel(float level); + float floorLevel() const; + +public Q_SLOTS: + void handleAxisXChanged(QAbstract3DAxis *axis) override; + void handleAxisYChanged(QAbstract3DAxis *axis) override; + void handleAxisZChanged(QAbstract3DAxis *axis) override; + +Q_SIGNALS: + void rowAxisChanged(QCategory3DAxis *axis); + void valueAxisChanged(QValue3DAxis *axis); + void columnAxisChanged(QCategory3DAxis *axis); + void multiSeriesUniformChanged(bool uniform); + void barThicknessChanged(float thicknessRatio); + void barSpacingChanged(const QSizeF &spacing); + void barSpacingRelativeChanged(bool relative); + Q_REVISION(6, 3) void barSeriesMarginChanged(const QSizeF &margin); + void meshFileNameChanged(const QString &filename); + void primarySeriesChanged(QBar3DSeries *series); + void selectedSeriesChanged(QBar3DSeries *series); + Q_REVISION(1, 2) void floorLevelChanged(float level); + +private: + Bars3DController *m_barsController; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/datavisualizationqml/declarativecolor.cpp b/src/datavisualizationqml/declarativecolor.cpp new file mode 100644 index 00000000..979c3f1e --- /dev/null +++ b/src/datavisualizationqml/declarativecolor.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "declarativecolor_p.h" + +QT_BEGIN_NAMESPACE + +DeclarativeColor::DeclarativeColor(QObject *parent) + : QObject(parent) +{ +} + +void DeclarativeColor::setColor(const QColor &color) +{ + if (m_color != color) { + m_color = color; + emit colorChanged(color); + } +} + +QColor DeclarativeColor::color() const +{ + return m_color; +} + +QT_END_NAMESPACE diff --git a/src/datavisualizationqml/declarativecolor_p.h b/src/datavisualizationqml/declarativecolor_p.h new file mode 100644 index 00000000..426d674d --- /dev/null +++ b/src/datavisualizationqml/declarativecolor_p.h @@ -0,0 +1,46 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef DECLARATIVECOLOR_P_H +#define DECLARATIVECOLOR_P_H + +#include <private/datavisualizationglobal_p.h> +#include <QtGui/QColor> +#include <QtQml/qqml.h> + +QT_BEGIN_NAMESPACE + +class DeclarativeColor : public QObject +{ + Q_OBJECT + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) + + QML_NAMED_ELEMENT(ThemeColor) + QML_ADDED_IN_VERSION(1, 0) + +public: + DeclarativeColor(QObject *parent = 0); + + void setColor(const QColor &color); + QColor color() const; + +Q_SIGNALS: + void colorChanged(const QColor &color); + +private: + QColor m_color; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/datavisualizationqml/declarativerendernode.cpp b/src/datavisualizationqml/declarativerendernode.cpp new file mode 100644 index 00000000..5a9f466c --- /dev/null +++ b/src/datavisualizationqml/declarativerendernode.cpp @@ -0,0 +1,157 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "declarativerendernode_p.h" +#include "abstractdeclarative_p.h" +#include <QtOpenGL/QOpenGLFramebufferObject> +#include <QtCore/QMutexLocker> + +QT_BEGIN_NAMESPACE + +DeclarativeRenderNode::DeclarativeRenderNode(AbstractDeclarative *declarative, + const QSharedPointer<QMutex> &nodeMutex) + : QSGGeometryNode(), + m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4), + m_texture(0), + m_declarative(declarative), + m_controller(0), + m_fbo(0), + m_multisampledFBO(0), + m_window(0), + m_samples(0), + m_dirtyFBO(false) +{ + m_nodeMutex = nodeMutex; + setMaterial(&m_material); + setOpaqueMaterial(&m_materialO); + setGeometry(&m_geometry); + setFlag(UsePreprocess); +} + +DeclarativeRenderNode::~DeclarativeRenderNode() +{ + delete m_fbo; + delete m_multisampledFBO; + delete m_texture; + + m_nodeMutex.clear(); +} + +void DeclarativeRenderNode::setSize(const QSize &size) +{ + if (size == m_size) + return; + + m_size = size; + m_dirtyFBO = true; + markDirty(DirtyGeometry); +} + +void DeclarativeRenderNode::update() +{ + if (m_dirtyFBO) { + updateFBO(); + m_dirtyFBO = false; + } +} + +void DeclarativeRenderNode::updateFBO() +{ + m_declarative->activateOpenGLContext(m_window); + + if (m_fbo) + delete m_fbo; + + m_fbo = new QOpenGLFramebufferObject(m_size); + m_fbo->setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + + // Multisampled + if (m_multisampledFBO) { + delete m_multisampledFBO; + m_multisampledFBO = 0; + } + if (m_samples > 0) { + QOpenGLFramebufferObjectFormat multisampledFrambufferFormat; + multisampledFrambufferFormat.setSamples(m_samples); + multisampledFrambufferFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + + m_multisampledFBO = new QOpenGLFramebufferObject(m_size, multisampledFrambufferFormat); + } + + QSGGeometry::updateTexturedRectGeometry(&m_geometry, + QRectF(0, 0, + m_size.width() + / m_controller->scene()->devicePixelRatio(), + m_size.height() + / m_controller->scene()->devicePixelRatio()), + QRectF(0, 1, 1, -1)); + + delete m_texture; + const uint id = m_fbo->texture(); + m_texture = QNativeInterface::QSGOpenGLTexture::fromNative(id, m_window, m_size); + m_material.setTexture(m_texture); + m_materialO.setTexture(m_texture); + + m_declarative->doneOpenGLContext(m_window); +} + +void DeclarativeRenderNode::setQuickWindow(QQuickWindow *window) +{ + Q_ASSERT(window); + + m_window = window; +} + +void DeclarativeRenderNode::setController(Abstract3DController *controller) +{ + QMutexLocker locker(m_nodeMutex.data()); + m_controller = controller; + if (m_controller) { + connect(m_controller, &QObject::destroyed, + this, &DeclarativeRenderNode::handleControllerDestroyed, Qt::DirectConnection); + } +} + +void DeclarativeRenderNode::setSamples(int samples) +{ + if (m_samples == samples) + return; + + m_samples = samples; + m_dirtyFBO = true; +} + +void DeclarativeRenderNode::preprocess() +{ + QMutexLocker locker(m_nodeMutex.data()); + + if (!m_controller) + return; + + QOpenGLFramebufferObject *targetFBO; + if (m_samples > 0) + targetFBO = m_multisampledFBO; + else + targetFBO = m_fbo; + + m_declarative->activateOpenGLContext(m_window); + + targetFBO->bind(); + // Render scene here + m_controller->render(targetFBO->handle()); + + targetFBO->release(); + + if (m_samples > 0) + QOpenGLFramebufferObject::blitFramebuffer(m_fbo, m_multisampledFBO); + + m_declarative->doneOpenGLContext(m_window); +} + +// This function is called within m_nodeMutex lock +void DeclarativeRenderNode::handleControllerDestroyed() +{ + m_controller = 0; +} + +QT_END_NAMESPACE diff --git a/src/datavisualizationqml/declarativerendernode_p.h b/src/datavisualizationqml/declarativerendernode_p.h new file mode 100644 index 00000000..2f6d22ec --- /dev/null +++ b/src/datavisualizationqml/declarativerendernode_p.h @@ -0,0 +1,76 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef DECLARATIVERENDERNODE_P_H +#define DECLARATIVERENDERNODE_P_H + +#include <private/datavisualizationglobal_p.h> + +#include <QtQuick/QSGGeometryNode> +#include <QtQuick/QSGTextureMaterial> +#include <QtQuick/QQuickWindow> +#include <QtCore/QMutex> +#include <QtCore/QSharedPointer> +#include <QtCore/QObject> + +QT_BEGIN_NAMESPACE + +class Abstract3DController; +class AbstractDeclarative; + +class DeclarativeRenderNode : public QObject, public QSGGeometryNode +{ + Q_OBJECT +public: + DeclarativeRenderNode(AbstractDeclarative *declarative, + const QSharedPointer<QMutex> &nodeMutex); + ~DeclarativeRenderNode(); + + void setSize(const QSize &size); + QSize size() const { return m_size; } + + void update(); + void updateFBO(); + + void setController(Abstract3DController *controller); + void setQuickWindow(QQuickWindow *window); + void setSamples(int samples); + + void preprocess() override; + +public Q_SLOTS: + void handleControllerDestroyed(); + +private: + QSGTextureMaterial m_material; + QSGOpaqueTextureMaterial m_materialO; + QSGGeometry m_geometry; + QSGTexture *m_texture; + QSize m_size; + + AbstractDeclarative *m_declarative; + Abstract3DController *m_controller; + QOpenGLFramebufferObject *m_fbo; + QOpenGLFramebufferObject *m_multisampledFBO; + QQuickWindow *m_window; + int m_samples; + + bool m_dirtyFBO; + + QSharedPointer<QMutex> m_nodeMutex; + +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/datavisualizationqml/declarativescatter.cpp b/src/datavisualizationqml/declarativescatter.cpp new file mode 100644 index 00000000..1e3795a0 --- /dev/null +++ b/src/datavisualizationqml/declarativescatter.cpp @@ -0,0 +1,126 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "declarativescatter_p.h" +#include <QtCore/QMutexLocker> + +QT_BEGIN_NAMESPACE + +DeclarativeScatter::DeclarativeScatter(QQuickItem *parent) + : AbstractDeclarative(parent), + m_scatterController(0) +{ + setAcceptedMouseButtons(Qt::AllButtons); + + // Create the shared component on the main GUI thread. + m_scatterController = new Scatter3DController(boundingRect().toRect(), new Declarative3DScene); + setSharedController(m_scatterController); + + QObject::connect(m_scatterController, &Scatter3DController::selectedSeriesChanged, + this, &DeclarativeScatter::selectedSeriesChanged); +} + +DeclarativeScatter::~DeclarativeScatter() +{ + QMutexLocker locker(m_nodeMutex.data()); + const QMutexLocker locker2(mutex()); + delete m_scatterController; +} + +QValue3DAxis *DeclarativeScatter::axisX() const +{ + return static_cast<QValue3DAxis *>(m_scatterController->axisX()); +} + +void DeclarativeScatter::setAxisX(QValue3DAxis *axis) +{ + m_scatterController->setAxisX(axis); +} + +QValue3DAxis *DeclarativeScatter::axisY() const +{ + return static_cast<QValue3DAxis *>(m_scatterController->axisY()); +} + +void DeclarativeScatter::setAxisY(QValue3DAxis *axis) +{ + m_scatterController->setAxisY(axis); +} + +QValue3DAxis *DeclarativeScatter::axisZ() const +{ + return static_cast<QValue3DAxis *>(m_scatterController->axisZ()); +} + +void DeclarativeScatter::setAxisZ(QValue3DAxis *axis) +{ + m_scatterController->setAxisZ(axis); +} + +QScatter3DSeries *DeclarativeScatter::selectedSeries() const +{ + return m_scatterController->selectedSeries(); +} + +QQmlListProperty<QScatter3DSeries> DeclarativeScatter::seriesList() +{ + return QQmlListProperty<QScatter3DSeries>(this, this, + &DeclarativeScatter::appendSeriesFunc, + &DeclarativeScatter::countSeriesFunc, + &DeclarativeScatter::atSeriesFunc, + &DeclarativeScatter::clearSeriesFunc); +} + +void DeclarativeScatter::appendSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, + QScatter3DSeries *series) +{ + reinterpret_cast<DeclarativeScatter *>(list->data)->addSeries(series); +} + +qsizetype DeclarativeScatter::countSeriesFunc(QQmlListProperty<QScatter3DSeries> *list) +{ + return reinterpret_cast<DeclarativeScatter *>(list->data)->m_scatterController->scatterSeriesList().size(); +} + +QScatter3DSeries *DeclarativeScatter::atSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, + qsizetype index) +{ + return reinterpret_cast<DeclarativeScatter *>(list->data)->m_scatterController->scatterSeriesList().at(index); +} + +void DeclarativeScatter::clearSeriesFunc(QQmlListProperty<QScatter3DSeries> *list) +{ + DeclarativeScatter *declScatter = reinterpret_cast<DeclarativeScatter *>(list->data); + QList<QScatter3DSeries *> realList = declScatter->m_scatterController->scatterSeriesList(); + int count = realList.size(); + for (int i = 0; i < count; i++) + declScatter->removeSeries(realList.at(i)); +} + +void DeclarativeScatter::addSeries(QScatter3DSeries *series) +{ + m_scatterController->addSeries(series); +} + +void DeclarativeScatter::removeSeries(QScatter3DSeries *series) +{ + m_scatterController->removeSeries(series); + series->setParent(this); // Reparent as removing will leave series parentless +} + +void DeclarativeScatter::handleAxisXChanged(QAbstract3DAxis *axis) +{ + emit axisXChanged(static_cast<QValue3DAxis *>(axis)); +} + +void DeclarativeScatter::handleAxisYChanged(QAbstract3DAxis *axis) +{ + emit axisYChanged(static_cast<QValue3DAxis *>(axis)); +} + +void DeclarativeScatter::handleAxisZChanged(QAbstract3DAxis *axis) +{ + emit axisZChanged(static_cast<QValue3DAxis *>(axis)); +} + +QT_END_NAMESPACE diff --git a/src/datavisualizationqml/declarativescatter_p.h b/src/datavisualizationqml/declarativescatter_p.h new file mode 100644 index 00000000..4b020b76 --- /dev/null +++ b/src/datavisualizationqml/declarativescatter_p.h @@ -0,0 +1,76 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef DECLARATIVESCATTER_P_H +#define DECLARATIVESCATTER_P_H + +#include "abstractdeclarative_p.h" +#include "qscatter3dseries.h" + +#include <private/datavisualizationglobal_p.h> +#include <private/scatter3dcontroller_p.h> + +QT_BEGIN_NAMESPACE + +class DeclarativeScatter : public AbstractDeclarative +{ + Q_OBJECT + Q_PROPERTY(QValue3DAxis *axisX READ axisX WRITE setAxisX NOTIFY axisXChanged) + Q_PROPERTY(QValue3DAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged) + Q_PROPERTY(QValue3DAxis *axisZ READ axisZ WRITE setAxisZ NOTIFY axisZChanged) + Q_PROPERTY(QScatter3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged) + Q_PROPERTY(QQmlListProperty<QScatter3DSeries> seriesList READ seriesList) + Q_CLASSINFO("DefaultProperty", "seriesList") + + QML_NAMED_ELEMENT(Scatter3D) + QML_ADDED_IN_VERSION(1, 0) + +public: + explicit DeclarativeScatter(QQuickItem *parent = 0); + ~DeclarativeScatter(); + + QValue3DAxis *axisX() const; + void setAxisX(QValue3DAxis *axis); + QValue3DAxis *axisY() const; + void setAxisY(QValue3DAxis *axis); + QValue3DAxis *axisZ() const; + void setAxisZ(QValue3DAxis *axis); + + QQmlListProperty<QScatter3DSeries> seriesList(); + static void appendSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, QScatter3DSeries *series); + static qsizetype countSeriesFunc(QQmlListProperty<QScatter3DSeries> *list); + static QScatter3DSeries *atSeriesFunc(QQmlListProperty<QScatter3DSeries> *list, qsizetype index); + static void clearSeriesFunc(QQmlListProperty<QScatter3DSeries> *list); + Q_INVOKABLE void addSeries(QScatter3DSeries *series); + Q_INVOKABLE void removeSeries(QScatter3DSeries *series); + + QScatter3DSeries *selectedSeries() const; + +public Q_SLOTS: + void handleAxisXChanged(QAbstract3DAxis *axis) override; + void handleAxisYChanged(QAbstract3DAxis *axis) override; + void handleAxisZChanged(QAbstract3DAxis *axis) override; + +Q_SIGNALS: + void axisXChanged(QValue3DAxis *axis); + void axisYChanged(QValue3DAxis *axis); + void axisZChanged(QValue3DAxis *axis); + void selectedSeriesChanged(QScatter3DSeries *series); + +protected: + Scatter3DController *m_scatterController; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/datavisualizationqml/declarativescene.cpp b/src/datavisualizationqml/declarativescene.cpp new file mode 100644 index 00000000..75508994 --- /dev/null +++ b/src/datavisualizationqml/declarativescene.cpp @@ -0,0 +1,34 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "declarativescene_p.h" + +QT_BEGIN_NAMESPACE + +Declarative3DScene::Declarative3DScene(QObject *parent) + : Q3DScene(parent) +{ + QObject::connect(this, &Q3DScene::selectionQueryPositionChanged, this, + &Declarative3DScene::selectionQueryPositionChanged); +} + +Declarative3DScene::~Declarative3DScene() +{ +} + +void Declarative3DScene::setSelectionQueryPosition(const QPointF &point) +{ + Q3DScene::setSelectionQueryPosition(point.toPoint()); +} + +QPointF Declarative3DScene::selectionQueryPosition() const +{ + return QPointF(Q3DScene::selectionQueryPosition()); +} + +QPoint Declarative3DScene::invalidSelectionPoint() const +{ + return Q3DScene::invalidSelectionPoint(); +} + +QT_END_NAMESPACE diff --git a/src/datavisualizationqml/declarativescene_p.h b/src/datavisualizationqml/declarativescene_p.h new file mode 100644 index 00000000..ba38b5e8 --- /dev/null +++ b/src/datavisualizationqml/declarativescene_p.h @@ -0,0 +1,50 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef DECLARATIVESCENE_P_H +#define DECLARATIVESCENE_P_H + +#include <QtQml/qqml.h> +#include <private/datavisualizationglobal_p.h> +#include <QtDataVisualization/q3dscene.h> + +QT_BEGIN_NAMESPACE + +class Declarative3DScene : public Q3DScene +{ + Q_OBJECT + // This property is overloaded to use QPointF instead of QPoint to work around qml bug + // where Qt.point(0, 0) can't be assigned due to error "Cannot assign QPointF to QPoint". + Q_PROPERTY(QPointF selectionQueryPosition READ selectionQueryPosition WRITE setSelectionQueryPosition NOTIFY selectionQueryPositionChanged) + // This is static method in parent class, overload as constant property for qml. + Q_PROPERTY(QPoint invalidSelectionPoint READ invalidSelectionPoint CONSTANT) + + QML_NAMED_ELEMENT(Scene3D) + QML_ADDED_IN_VERSION(1, 0) + QML_UNCREATABLE("Trying to create uncreatable: Scene3D.") + +public: + Declarative3DScene(QObject *parent = 0); + virtual ~Declarative3DScene(); + + void setSelectionQueryPosition(const QPointF &point); + QPointF selectionQueryPosition() const; + QPoint invalidSelectionPoint() const; + +Q_SIGNALS: + void selectionQueryPositionChanged(const QPointF &position); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/datavisualizationqml/declarativeseries.cpp b/src/datavisualizationqml/declarativeseries.cpp new file mode 100644 index 00000000..65c2cc76 --- /dev/null +++ b/src/datavisualizationqml/declarativeseries.cpp @@ -0,0 +1,435 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "declarativeseries_p.h" +#include <QtCore/QMetaMethod> + +QT_BEGIN_NAMESPACE + +static void setSeriesGradient(QAbstract3DSeries *series, const ColorGradient &gradient, + GradientType type) +{ + QLinearGradient newGradient; + QGradientStops stops; + QList<ColorGradientStop *> qmlstops = gradient.m_stops; + + // Get sorted gradient stops + for (int i = 0; i < qmlstops.size(); i++) { + int j = 0; + while (j < stops.size() && stops.at(j).first < qmlstops[i]->position()) + j++; + stops.insert(j, QGradientStop(qmlstops.at(i)->position(), qmlstops.at(i)->color())); + } + + newGradient.setStops(stops); + switch (type) { + case GradientTypeBase: + series->setBaseGradient(newGradient); + break; + case GradientTypeSingle: + series->setSingleHighlightGradient(newGradient); + break; + case GradientTypeMulti: + series->setMultiHighlightGradient(newGradient); + break; + default: // Never goes here + break; + } +} + +static void connectSeriesGradient(QAbstract3DSeries *series, ColorGradient *newGradient, + GradientType type, ColorGradient **memberGradient) +{ + // connect new / disconnect old + if (newGradient != *memberGradient) { + if (*memberGradient) + QObject::disconnect(*memberGradient, 0, series, 0); + + *memberGradient = newGradient; + + int updatedIndex = newGradient->metaObject()->indexOfSignal("updated()"); + QMetaMethod updateFunction = newGradient->metaObject()->method(updatedIndex); + int handleIndex = -1; + switch (type) { + case GradientTypeBase: + handleIndex = series->metaObject()->indexOfSlot("handleBaseGradientUpdate()"); + break; + case GradientTypeSingle: + handleIndex = series->metaObject()->indexOfSlot("handleSingleHighlightGradientUpdate()"); + break; + case GradientTypeMulti: + handleIndex = series->metaObject()->indexOfSlot("handleMultiHighlightGradientUpdate()"); + break; + default: // Never goes here + break; + } + QMetaMethod handleFunction = series->metaObject()->method(handleIndex); + + if (*memberGradient) + QObject::connect(*memberGradient, updateFunction, series, handleFunction); + } + + if (*memberGradient) + setSeriesGradient(series, **memberGradient, type); +} + +DeclarativeBar3DSeries::DeclarativeBar3DSeries(QObject *parent) + : QBar3DSeries(parent), + m_baseGradient(0), + m_singleHighlightGradient(0), + m_multiHighlightGradient(0), + m_dummyColors(false) +{ + QObject::connect(this, &QBar3DSeries::selectedBarChanged, this, + &DeclarativeBar3DSeries::selectedBarChanged); +} + +DeclarativeBar3DSeries::~DeclarativeBar3DSeries() +{ +} + +QQmlListProperty<QObject> DeclarativeBar3DSeries::seriesChildren() +{ + return QQmlListProperty<QObject>(this, this, &DeclarativeBar3DSeries::appendSeriesChildren + , 0, 0, 0); +} + +void DeclarativeBar3DSeries::appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element) +{ + QBarDataProxy *proxy = qobject_cast<QBarDataProxy *>(element); + if (proxy) + reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->setDataProxy(proxy); +} + +void DeclarativeBar3DSeries::setSelectedBar(const QPointF &position) +{ + QBar3DSeries::setSelectedBar(position.toPoint()); +} + +QPointF DeclarativeBar3DSeries::selectedBar() const +{ + return QPointF(QBar3DSeries::selectedBar()); +} + +QPointF DeclarativeBar3DSeries::invalidSelectionPosition() const +{ + return QPointF(QBar3DSeries::invalidSelectionPosition()); +} + +void DeclarativeBar3DSeries::setBaseGradient(ColorGradient *gradient) +{ + connectSeriesGradient(this, gradient, GradientTypeBase, &m_baseGradient); +} + +ColorGradient *DeclarativeBar3DSeries::baseGradient() const +{ + return m_baseGradient; +} + +void DeclarativeBar3DSeries::setSingleHighlightGradient(ColorGradient *gradient) +{ + connectSeriesGradient(this, gradient, GradientTypeSingle, &m_singleHighlightGradient); +} + +ColorGradient *DeclarativeBar3DSeries::singleHighlightGradient() const +{ + return m_singleHighlightGradient; +} + +void DeclarativeBar3DSeries::setMultiHighlightGradient(ColorGradient *gradient) +{ + connectSeriesGradient(this, gradient, GradientTypeMulti, &m_multiHighlightGradient); +} + +ColorGradient *DeclarativeBar3DSeries::multiHighlightGradient() const +{ + return m_multiHighlightGradient; +} + +QQmlListProperty<DeclarativeColor> DeclarativeBar3DSeries::rowColors() +{ + return QQmlListProperty<DeclarativeColor>(this, this, + &DeclarativeBar3DSeries::appendRowColorsFunc, + &DeclarativeBar3DSeries::countRowColorsFunc, + &DeclarativeBar3DSeries::atRowColorsFunc, + &DeclarativeBar3DSeries::clearRowColorsFunc); +} + +void DeclarativeBar3DSeries::appendRowColorsFunc(QQmlListProperty<DeclarativeColor> *list, + DeclarativeColor *color) +{ + reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->addColor(color); +} + +qsizetype DeclarativeBar3DSeries::countRowColorsFunc(QQmlListProperty<DeclarativeColor> *list) +{ + return reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->colorList().size(); +} + +DeclarativeColor *DeclarativeBar3DSeries::atRowColorsFunc(QQmlListProperty<DeclarativeColor> *list, + qsizetype index) +{ + return reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->colorList().at(index); +} + +void DeclarativeBar3DSeries::clearRowColorsFunc(QQmlListProperty<DeclarativeColor> *list) +{ + reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->clearColors(); +} + +void DeclarativeBar3DSeries::handleBaseGradientUpdate() +{ + if (m_baseGradient) + setSeriesGradient(this, *m_baseGradient, GradientTypeBase); +} + +void DeclarativeBar3DSeries::handleSingleHighlightGradientUpdate() +{ + if (m_singleHighlightGradient) + setSeriesGradient(this, *m_singleHighlightGradient, GradientTypeSingle); +} + +void DeclarativeBar3DSeries::handleMultiHighlightGradientUpdate() +{ + if (m_multiHighlightGradient) + setSeriesGradient(this, *m_multiHighlightGradient, GradientTypeMulti); +} + +void DeclarativeBar3DSeries::handleRowColorUpdate() +{ + int colorCount = m_rowColors.size(); + int changed = 0; + + DeclarativeColor *color = qobject_cast<DeclarativeColor*>(QObject::sender()); + for (int i = 0; i < colorCount; i++) { + if (color == m_rowColors.at(i)) { + changed = i; + break; + } + } + QList<QColor> list = QBar3DSeries::rowColors(); + list[changed] = m_rowColors.at(changed)->color(); + QBar3DSeries::setRowColors(list); +} + +void DeclarativeBar3DSeries::addColor(DeclarativeColor *color) +{ + if (!color) { + qWarning("Color is invalid, use ThemeColor"); + return; + } + clearDummyColors(); + m_rowColors.append(color); + connect(color, &DeclarativeColor::colorChanged, this, + &DeclarativeBar3DSeries::handleRowColorUpdate); + QList<QColor> list = QBar3DSeries::rowColors(); + list.append(color->color()); + QBar3DSeries::setRowColors(list); +} + +QList<DeclarativeColor *> DeclarativeBar3DSeries::colorList() +{ + if (m_rowColors.isEmpty()) { + m_dummyColors = true; + const QList<QColor> list = QBar3DSeries::rowColors(); + for (const QColor &item : list) { + DeclarativeColor *color = new DeclarativeColor(this); + color->setColor(item); + m_rowColors.append(color); + connect(color, &DeclarativeColor::colorChanged, this, + &DeclarativeBar3DSeries::handleRowColorUpdate); + } + } + return m_rowColors; +} + +void DeclarativeBar3DSeries::clearColors() +{ + clearDummyColors(); + for (const auto color : std::as_const(m_rowColors)) + disconnect(color, 0, this, 0); + + m_rowColors.clear(); + QBar3DSeries::setRowColors(QList<QColor>()); +} + +void DeclarativeBar3DSeries::clearDummyColors() +{ + if (m_dummyColors) { + qDeleteAll(m_rowColors); + m_rowColors.clear(); + m_dummyColors = false; + } +} + +DeclarativeScatter3DSeries::DeclarativeScatter3DSeries(QObject *parent) + : QScatter3DSeries(parent), + m_baseGradient(0), + m_singleHighlightGradient(0), + m_multiHighlightGradient(0) +{ +} + +DeclarativeScatter3DSeries::~DeclarativeScatter3DSeries() +{ +} + +QQmlListProperty<QObject> DeclarativeScatter3DSeries::seriesChildren() +{ + return QQmlListProperty<QObject>(this, this, &DeclarativeScatter3DSeries::appendSeriesChildren + , 0, 0, 0); +} + +void DeclarativeScatter3DSeries::appendSeriesChildren(QQmlListProperty<QObject> *list, + QObject *element) +{ + QScatterDataProxy *proxy = qobject_cast<QScatterDataProxy *>(element); + if (proxy) + reinterpret_cast<DeclarativeScatter3DSeries *>(list->data)->setDataProxy(proxy); +} + +void DeclarativeScatter3DSeries::setBaseGradient(ColorGradient *gradient) +{ + connectSeriesGradient(this, gradient, GradientTypeBase, &m_baseGradient); +} + +ColorGradient *DeclarativeScatter3DSeries::baseGradient() const +{ + return m_baseGradient; +} + +void DeclarativeScatter3DSeries::setSingleHighlightGradient(ColorGradient *gradient) +{ + connectSeriesGradient(this, gradient, GradientTypeSingle, &m_singleHighlightGradient); +} + +ColorGradient *DeclarativeScatter3DSeries::singleHighlightGradient() const +{ + return m_singleHighlightGradient; +} + +void DeclarativeScatter3DSeries::setMultiHighlightGradient(ColorGradient *gradient) +{ + connectSeriesGradient(this, gradient, GradientTypeMulti, &m_multiHighlightGradient); +} + +ColorGradient *DeclarativeScatter3DSeries::multiHighlightGradient() const +{ + return m_multiHighlightGradient; +} + +int DeclarativeScatter3DSeries::invalidSelectionIndex() const +{ + return QScatter3DSeries::invalidSelectionIndex(); +} + +void DeclarativeScatter3DSeries::handleBaseGradientUpdate() +{ + if (m_baseGradient) + setSeriesGradient(this, *m_baseGradient, GradientTypeBase); +} + +void DeclarativeScatter3DSeries::handleSingleHighlightGradientUpdate() +{ + if (m_singleHighlightGradient) + setSeriesGradient(this, *m_singleHighlightGradient, GradientTypeSingle); +} + +void DeclarativeScatter3DSeries::handleMultiHighlightGradientUpdate() +{ + if (m_multiHighlightGradient) + setSeriesGradient(this, *m_multiHighlightGradient, GradientTypeMulti); +} + +DeclarativeSurface3DSeries::DeclarativeSurface3DSeries(QObject *parent) + : QSurface3DSeries(parent), + m_baseGradient(0), + m_singleHighlightGradient(0), + m_multiHighlightGradient(0) +{ + QObject::connect(this, &QSurface3DSeries::selectedPointChanged, this, + &DeclarativeSurface3DSeries::selectedPointChanged); +} + +DeclarativeSurface3DSeries::~DeclarativeSurface3DSeries() +{ +} + +void DeclarativeSurface3DSeries::setSelectedPoint(const QPointF &position) +{ + QSurface3DSeries::setSelectedPoint(position.toPoint()); +} + +QPointF DeclarativeSurface3DSeries::selectedPoint() const +{ + return QPointF(QSurface3DSeries::selectedPoint()); +} + +QPointF DeclarativeSurface3DSeries::invalidSelectionPosition() const +{ + return QPointF(QSurface3DSeries::invalidSelectionPosition()); +} + +QQmlListProperty<QObject> DeclarativeSurface3DSeries::seriesChildren() +{ + return QQmlListProperty<QObject>(this, this, &DeclarativeSurface3DSeries::appendSeriesChildren + , 0, 0, 0); +} + +void DeclarativeSurface3DSeries::appendSeriesChildren(QQmlListProperty<QObject> *list, + QObject *element) +{ + QSurfaceDataProxy *proxy = qobject_cast<QSurfaceDataProxy *>(element); + if (proxy) + reinterpret_cast<DeclarativeSurface3DSeries *>(list->data)->setDataProxy(proxy); +} + +void DeclarativeSurface3DSeries::setBaseGradient(ColorGradient *gradient) +{ + connectSeriesGradient(this, gradient, GradientTypeBase, &m_baseGradient); +} + +ColorGradient *DeclarativeSurface3DSeries::baseGradient() const +{ + return m_baseGradient; +} + +void DeclarativeSurface3DSeries::setSingleHighlightGradient(ColorGradient *gradient) +{ + connectSeriesGradient(this, gradient, GradientTypeSingle, &m_singleHighlightGradient); +} + +ColorGradient *DeclarativeSurface3DSeries::singleHighlightGradient() const +{ + return m_singleHighlightGradient; +} + +void DeclarativeSurface3DSeries::setMultiHighlightGradient(ColorGradient *gradient) +{ + connectSeriesGradient(this, gradient, GradientTypeMulti, &m_multiHighlightGradient); +} + +ColorGradient *DeclarativeSurface3DSeries::multiHighlightGradient() const +{ + return m_multiHighlightGradient; +} + +void DeclarativeSurface3DSeries::handleBaseGradientUpdate() +{ + if (m_baseGradient) + setSeriesGradient(this, *m_baseGradient, GradientTypeBase); +} + +void DeclarativeSurface3DSeries::handleSingleHighlightGradientUpdate() +{ + if (m_singleHighlightGradient) + setSeriesGradient(this, *m_singleHighlightGradient, GradientTypeSingle); +} + +void DeclarativeSurface3DSeries::handleMultiHighlightGradientUpdate() +{ + if (m_multiHighlightGradient) + setSeriesGradient(this, *m_multiHighlightGradient, GradientTypeMulti); +} + +QT_END_NAMESPACE diff --git a/src/datavisualizationqml/declarativeseries_p.h b/src/datavisualizationqml/declarativeseries_p.h new file mode 100644 index 00000000..13b1eda3 --- /dev/null +++ b/src/datavisualizationqml/declarativeseries_p.h @@ -0,0 +1,204 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef DECLARATIVESERIES_P_H +#define DECLARATIVESERIES_P_H + +#include "qbar3dseries.h" +#include "qscatter3dseries.h" +#include "qsurface3dseries.h" +#include "colorgradient_p.h" +#include "declarativecolor_p.h" + +#include <private/datavisualizationglobal_p.h> +#include <QtQml/qqml.h> + +QT_BEGIN_NAMESPACE + +enum GradientType { + GradientTypeBase, + GradientTypeSingle, + GradientTypeMulti +}; + +class DeclarativeBar3DSeries : public QBar3DSeries +{ + Q_OBJECT + Q_PROPERTY(QQmlListProperty<QObject> seriesChildren READ seriesChildren) + // This property is overloaded to use QPointF instead of QPoint to work around qml bug + // where Qt.point(0, 0) can't be assigned due to error "Cannot assign QPointF to QPoint". + Q_PROPERTY(QPointF selectedBar READ selectedBar WRITE setSelectedBar NOTIFY selectedBarChanged) + // This is static method in parent class, overload as constant property for qml. + Q_PROPERTY(QPointF invalidSelectionPosition READ invalidSelectionPosition CONSTANT) + Q_PROPERTY(ColorGradient *baseGradient READ baseGradient WRITE setBaseGradient NOTIFY baseGradientChanged) + Q_PROPERTY(ColorGradient *singleHighlightGradient READ singleHighlightGradient WRITE setSingleHighlightGradient NOTIFY singleHighlightGradientChanged) + Q_PROPERTY(ColorGradient *multiHighlightGradient READ multiHighlightGradient WRITE setMultiHighlightGradient NOTIFY multiHighlightGradientChanged) + Q_PROPERTY(QQmlListProperty<DeclarativeColor> rowColors READ rowColors REVISION(6, 3)) + Q_CLASSINFO("DefaultProperty", "seriesChildren") + + QML_NAMED_ELEMENT(Bar3DSeries) + QML_ADDED_IN_VERSION(1, 0) + +public: + DeclarativeBar3DSeries(QObject *parent = 0); + virtual ~DeclarativeBar3DSeries(); + + QQmlListProperty<QObject> seriesChildren(); + static void appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element); + + void setSelectedBar(const QPointF &position); + QPointF selectedBar() const; + QPointF invalidSelectionPosition() const; + + void setBaseGradient(ColorGradient *gradient); + ColorGradient *baseGradient() const; + void setSingleHighlightGradient(ColorGradient *gradient); + ColorGradient *singleHighlightGradient() const; + void setMultiHighlightGradient(ColorGradient *gradient); + ColorGradient *multiHighlightGradient() const; + + QQmlListProperty<DeclarativeColor> rowColors(); + static void appendRowColorsFunc(QQmlListProperty<DeclarativeColor> *list, + DeclarativeColor *color); + static qsizetype countRowColorsFunc(QQmlListProperty<DeclarativeColor> *list); + static DeclarativeColor *atRowColorsFunc(QQmlListProperty<DeclarativeColor> *list, + qsizetype index); + static void clearRowColorsFunc(QQmlListProperty<DeclarativeColor> *list); + +public Q_SLOTS: + void handleBaseGradientUpdate(); + void handleSingleHighlightGradientUpdate(); + void handleMultiHighlightGradientUpdate(); + void handleRowColorUpdate(); + +Q_SIGNALS: + void selectedBarChanged(const QPointF &position); + void baseGradientChanged(ColorGradient *gradient); + void singleHighlightGradientChanged(ColorGradient *gradient); + void multiHighlightGradientChanged(ColorGradient *gradient); + +private: + ColorGradient *m_baseGradient; // Not owned + ColorGradient *m_singleHighlightGradient; // Not owned + ColorGradient *m_multiHighlightGradient; // Not owned + + QList<DeclarativeColor *> m_rowColors; + bool m_dummyColors; + + void addColor(DeclarativeColor *color); + QList<DeclarativeColor *> colorList(); + void clearColors(); + void clearDummyColors(); +}; + +class DeclarativeScatter3DSeries : public QScatter3DSeries +{ + Q_OBJECT + Q_PROPERTY(QQmlListProperty<QObject> seriesChildren READ seriesChildren) + Q_PROPERTY(ColorGradient *baseGradient READ baseGradient WRITE setBaseGradient NOTIFY baseGradientChanged) + Q_PROPERTY(ColorGradient *singleHighlightGradient READ singleHighlightGradient WRITE setSingleHighlightGradient NOTIFY singleHighlightGradientChanged) + Q_PROPERTY(ColorGradient *multiHighlightGradient READ multiHighlightGradient WRITE setMultiHighlightGradient NOTIFY multiHighlightGradientChanged) + // This is static method in parent class, overload as constant property for qml. + Q_PROPERTY(int invalidSelectionIndex READ invalidSelectionIndex CONSTANT) + Q_CLASSINFO("DefaultProperty", "seriesChildren") + + QML_NAMED_ELEMENT(Scatter3DSeries) + QML_ADDED_IN_VERSION(1, 0) + +public: + DeclarativeScatter3DSeries(QObject *parent = 0); + virtual ~DeclarativeScatter3DSeries(); + + QQmlListProperty<QObject> seriesChildren(); + static void appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element); + + void setBaseGradient(ColorGradient *gradient); + ColorGradient *baseGradient() const; + void setSingleHighlightGradient(ColorGradient *gradient); + ColorGradient *singleHighlightGradient() const; + void setMultiHighlightGradient(ColorGradient *gradient); + ColorGradient *multiHighlightGradient() const; + + int invalidSelectionIndex() const; + +public Q_SLOTS: + void handleBaseGradientUpdate(); + void handleSingleHighlightGradientUpdate(); + void handleMultiHighlightGradientUpdate(); + +Q_SIGNALS: + void baseGradientChanged(ColorGradient *gradient); + void singleHighlightGradientChanged(ColorGradient *gradient); + void multiHighlightGradientChanged(ColorGradient *gradient); + +private: + ColorGradient *m_baseGradient; // Not owned + ColorGradient *m_singleHighlightGradient; // Not owned + ColorGradient *m_multiHighlightGradient; // Not owned +}; + +class DeclarativeSurface3DSeries : public QSurface3DSeries +{ + Q_OBJECT + Q_PROPERTY(QQmlListProperty<QObject> seriesChildren READ seriesChildren) + // This property is overloaded to use QPointF instead of QPoint to work around qml bug + // where Qt.point(0, 0) can't be assigned due to error "Cannot assign QPointF to QPoint". + Q_PROPERTY(QPointF selectedPoint READ selectedPoint WRITE setSelectedPoint NOTIFY selectedPointChanged) + // This is static method in parent class, overload as constant property for qml. + Q_PROPERTY(QPointF invalidSelectionPosition READ invalidSelectionPosition CONSTANT) + Q_PROPERTY(ColorGradient *baseGradient READ baseGradient WRITE setBaseGradient NOTIFY baseGradientChanged) + Q_PROPERTY(ColorGradient *singleHighlightGradient READ singleHighlightGradient WRITE setSingleHighlightGradient NOTIFY singleHighlightGradientChanged) + Q_PROPERTY(ColorGradient *multiHighlightGradient READ multiHighlightGradient WRITE setMultiHighlightGradient NOTIFY multiHighlightGradientChanged) + Q_CLASSINFO("DefaultProperty", "seriesChildren") + + QML_NAMED_ELEMENT(Surface3DSeries) + QML_ADDED_IN_VERSION(1, 0) + +public: + DeclarativeSurface3DSeries(QObject *parent = 0); + virtual ~DeclarativeSurface3DSeries(); + + void setSelectedPoint(const QPointF &position); + QPointF selectedPoint() const; + QPointF invalidSelectionPosition() const; + + QQmlListProperty<QObject> seriesChildren(); + static void appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element); + + void setBaseGradient(ColorGradient *gradient); + ColorGradient *baseGradient() const; + void setSingleHighlightGradient(ColorGradient *gradient); + ColorGradient *singleHighlightGradient() const; + void setMultiHighlightGradient(ColorGradient *gradient); + ColorGradient *multiHighlightGradient() const; + +public Q_SLOTS: + void handleBaseGradientUpdate(); + void handleSingleHighlightGradientUpdate(); + void handleMultiHighlightGradientUpdate(); + +Q_SIGNALS: + void selectedPointChanged(const QPointF &position); + void baseGradientChanged(ColorGradient *gradient); + void singleHighlightGradientChanged(ColorGradient *gradient); + void multiHighlightGradientChanged(ColorGradient *gradient); + +private: + ColorGradient *m_baseGradient; // Not owned + ColorGradient *m_singleHighlightGradient; // Not owned + ColorGradient *m_multiHighlightGradient; // Not owned +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/datavisualizationqml/declarativesurface.cpp b/src/datavisualizationqml/declarativesurface.cpp new file mode 100644 index 00000000..cff80e98 --- /dev/null +++ b/src/datavisualizationqml/declarativesurface.cpp @@ -0,0 +1,138 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "declarativesurface_p.h" +#include <QtCore/QMutexLocker> + +QT_BEGIN_NAMESPACE + +DeclarativeSurface::DeclarativeSurface(QQuickItem *parent) + : AbstractDeclarative(parent), + m_surfaceController(0) +{ + setAcceptedMouseButtons(Qt::AllButtons); + + // Create the shared component on the main GUI thread. + m_surfaceController = new Surface3DController(boundingRect().toRect(), new Declarative3DScene); + setSharedController(m_surfaceController); + + QObject::connect(m_surfaceController, &Surface3DController::selectedSeriesChanged, + this, &DeclarativeSurface::selectedSeriesChanged); + QObject::connect(m_surfaceController, &Surface3DController::flipHorizontalGridChanged, + this, &DeclarativeSurface::flipHorizontalGridChanged); +} + +DeclarativeSurface::~DeclarativeSurface() +{ + QMutexLocker locker(m_nodeMutex.data()); + const QMutexLocker locker2(mutex()); + delete m_surfaceController; +} + +QValue3DAxis *DeclarativeSurface::axisX() const +{ + return static_cast<QValue3DAxis *>(m_surfaceController->axisX()); +} + +void DeclarativeSurface::setAxisX(QValue3DAxis *axis) +{ + m_surfaceController->setAxisX(axis); +} + +QValue3DAxis *DeclarativeSurface::axisY() const +{ + return static_cast<QValue3DAxis *>(m_surfaceController->axisY()); +} + +void DeclarativeSurface::setAxisY(QValue3DAxis *axis) +{ + m_surfaceController->setAxisY(axis); +} + +QValue3DAxis *DeclarativeSurface::axisZ() const +{ + return static_cast<QValue3DAxis *>(m_surfaceController->axisZ()); +} + +void DeclarativeSurface::setAxisZ(QValue3DAxis *axis) +{ + m_surfaceController->setAxisZ(axis); +} + +QSurface3DSeries *DeclarativeSurface::selectedSeries() const +{ + return m_surfaceController->selectedSeries(); +} + +void DeclarativeSurface::setFlipHorizontalGrid(bool flip) +{ + m_surfaceController->setFlipHorizontalGrid(flip); +} + +bool DeclarativeSurface::flipHorizontalGrid() const +{ + return m_surfaceController->flipHorizontalGrid(); +} + +QQmlListProperty<QSurface3DSeries> DeclarativeSurface::seriesList() +{ + return QQmlListProperty<QSurface3DSeries>(this, this, + &DeclarativeSurface::appendSeriesFunc, + &DeclarativeSurface::countSeriesFunc, + &DeclarativeSurface::atSeriesFunc, + &DeclarativeSurface::clearSeriesFunc); +} + +void DeclarativeSurface::appendSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, + QSurface3DSeries *series) +{ + reinterpret_cast<DeclarativeSurface *>(list->data)->addSeries(series); +} + +qsizetype DeclarativeSurface::countSeriesFunc(QQmlListProperty<QSurface3DSeries> *list) +{ + return reinterpret_cast<DeclarativeSurface *>(list->data)->m_surfaceController->surfaceSeriesList().size(); +} + +QSurface3DSeries *DeclarativeSurface::atSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, + qsizetype index) +{ + return reinterpret_cast<DeclarativeSurface *>(list->data)->m_surfaceController->surfaceSeriesList().at(index); +} + +void DeclarativeSurface::clearSeriesFunc(QQmlListProperty<QSurface3DSeries> *list) +{ + DeclarativeSurface *declSurface = reinterpret_cast<DeclarativeSurface *>(list->data); + QList<QSurface3DSeries *> realList = declSurface->m_surfaceController->surfaceSeriesList(); + int count = realList.size(); + for (int i = 0; i < count; i++) + declSurface->removeSeries(realList.at(i)); +} + +void DeclarativeSurface::addSeries(QSurface3DSeries *series) +{ + m_surfaceController->addSeries(series); +} + +void DeclarativeSurface::removeSeries(QSurface3DSeries *series) +{ + m_surfaceController->removeSeries(series); + series->setParent(this); // Reparent as removing will leave series parentless +} + +void DeclarativeSurface::handleAxisXChanged(QAbstract3DAxis *axis) +{ + emit axisXChanged(static_cast<QValue3DAxis *>(axis)); +} + +void DeclarativeSurface::handleAxisYChanged(QAbstract3DAxis *axis) +{ + emit axisYChanged(static_cast<QValue3DAxis *>(axis)); +} + +void DeclarativeSurface::handleAxisZChanged(QAbstract3DAxis *axis) +{ + emit axisZChanged(static_cast<QValue3DAxis *>(axis)); +} + +QT_END_NAMESPACE diff --git a/src/datavisualizationqml/declarativesurface_p.h b/src/datavisualizationqml/declarativesurface_p.h new file mode 100644 index 00000000..4634834a --- /dev/null +++ b/src/datavisualizationqml/declarativesurface_p.h @@ -0,0 +1,80 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef DECLARATIVESURFACE_P_H +#define DECLARATIVESURFACE_P_H + +#include "abstractdeclarative_p.h" +#include "qsurface3dseries.h" + +#include <private/datavisualizationglobal_p.h> +#include <private/surface3dcontroller_p.h> + +QT_BEGIN_NAMESPACE + +class DeclarativeSurface : public AbstractDeclarative +{ + Q_OBJECT + Q_PROPERTY(QValue3DAxis *axisX READ axisX WRITE setAxisX NOTIFY axisXChanged) + Q_PROPERTY(QValue3DAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged) + Q_PROPERTY(QValue3DAxis *axisZ READ axisZ WRITE setAxisZ NOTIFY axisZChanged) + Q_PROPERTY(QSurface3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged) + Q_PROPERTY(QQmlListProperty<QSurface3DSeries> seriesList READ seriesList) + Q_PROPERTY(bool flipHorizontalGrid READ flipHorizontalGrid WRITE setFlipHorizontalGrid NOTIFY flipHorizontalGridChanged REVISION(1, 2)) + Q_CLASSINFO("DefaultProperty", "seriesList") + + QML_NAMED_ELEMENT(Surface3D) + QML_ADDED_IN_VERSION(1, 0) + +public: + explicit DeclarativeSurface(QQuickItem *parent = 0); + ~DeclarativeSurface(); + + QValue3DAxis *axisX() const; + void setAxisX(QValue3DAxis *axis); + QValue3DAxis *axisY() const; + void setAxisY(QValue3DAxis *axis); + QValue3DAxis *axisZ() const; + void setAxisZ(QValue3DAxis *axis); + + QQmlListProperty<QSurface3DSeries> seriesList(); + static void appendSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, QSurface3DSeries *series); + static qsizetype countSeriesFunc(QQmlListProperty<QSurface3DSeries> *list); + static QSurface3DSeries *atSeriesFunc(QQmlListProperty<QSurface3DSeries> *list, qsizetype index); + static void clearSeriesFunc(QQmlListProperty<QSurface3DSeries> *list); + Q_INVOKABLE void addSeries(QSurface3DSeries *series); + Q_INVOKABLE void removeSeries(QSurface3DSeries *series); + + QSurface3DSeries *selectedSeries() const; + void setFlipHorizontalGrid(bool flip); + bool flipHorizontalGrid() const; + +public Q_SLOTS: + void handleAxisXChanged(QAbstract3DAxis *axis) override; + void handleAxisYChanged(QAbstract3DAxis *axis) override; + void handleAxisZChanged(QAbstract3DAxis *axis) override; + +Q_SIGNALS: + void axisXChanged(QValue3DAxis *axis); + void axisYChanged(QValue3DAxis *axis); + void axisZChanged(QValue3DAxis *axis); + void selectedSeriesChanged(QSurface3DSeries *series); + Q_REVISION(1, 2) void flipHorizontalGridChanged(bool flip); + +private: + Surface3DController *m_surfaceController; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/datavisualizationqml/declarativetheme.cpp b/src/datavisualizationqml/declarativetheme.cpp new file mode 100644 index 00000000..02f3becc --- /dev/null +++ b/src/datavisualizationqml/declarativetheme.cpp @@ -0,0 +1,388 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses + +#include "declarativetheme_p.h" + +QT_BEGIN_NAMESPACE + +DeclarativeTheme3D::DeclarativeTheme3D(QObject *parent) + : Q3DTheme(parent), + m_colors(QList<DeclarativeColor *>()), + m_gradients(QList<ColorGradient *>()), + m_singleHLGradient(0), + m_multiHLGradient(0), + m_dummyGradients(false), + m_dummyColors(false) +{ + connect(this, &Q3DTheme::typeChanged, this, &DeclarativeTheme3D::handleTypeChange); +} + +DeclarativeTheme3D::~DeclarativeTheme3D() +{ +} + +QQmlListProperty<QObject> DeclarativeTheme3D::themeChildren() +{ + return QQmlListProperty<QObject>(this, this, &DeclarativeTheme3D::appendThemeChildren, + 0, 0, 0); +} + +void DeclarativeTheme3D::appendThemeChildren(QQmlListProperty<QObject> *list, QObject *element) +{ + Q_UNUSED(list); + Q_UNUSED(element); + // Nothing to do, themeChildren is there only to enable scoping gradient items in Theme3D item. +} + +void DeclarativeTheme3D::handleTypeChange(Theme themeType) +{ + Q_UNUSED(themeType); + + // Theme changed, disconnect base color/gradient connections + if (!m_colors.isEmpty()) { + foreach (DeclarativeColor *item, m_colors) + disconnect(item, 0, this, 0); + m_colors.clear(); + } + if (!m_gradients.isEmpty()) { + foreach (ColorGradient *item, m_gradients) + disconnect(item, 0, this, 0); + m_gradients.clear(); + } +} + +void DeclarativeTheme3D::handleBaseColorUpdate() +{ + int colorCount = m_colors.size(); + int changed = 0; + // Check which one changed + DeclarativeColor *color = qobject_cast<DeclarativeColor *>(QObject::sender()); + for (int i = 0; i < colorCount; i++) { + if (color == m_colors.at(i)) { + changed = i; + break; + } + } + // Update the changed one from the list + QList<QColor> list = Q3DTheme::baseColors(); + list[changed] = m_colors.at(changed)->color(); + // Set the changed list + Q3DTheme::setBaseColors(list); +} + +void DeclarativeTheme3D::handleBaseGradientUpdate() +{ + int gradientCount = m_gradients.size(); + int changed = 0; + // Check which one changed + ColorGradient *gradient = qobject_cast<ColorGradient *>(QObject::sender()); + for (int i = 0; i < gradientCount; i++) { + if (gradient == m_gradients.at(i)) { + changed = i; + break; + } + } + // Update the changed one from the list + QList<QLinearGradient> list = Q3DTheme::baseGradients(); + list[changed] = convertGradient(gradient); + // Set the changed list + Q3DTheme::setBaseGradients(list); +} + +void DeclarativeTheme3D::handleSingleHLGradientUpdate() +{ + if (m_singleHLGradient) + setThemeGradient(m_singleHLGradient, GradientTypeSingleHL); +} + +void DeclarativeTheme3D::handleMultiHLGradientUpdate() +{ + if (m_multiHLGradient) + setThemeGradient(m_multiHLGradient, GradientTypeMultiHL); +} + +void DeclarativeTheme3D::setSingleHighlightGradient(ColorGradient *gradient) +{ + // connect new / disconnect old + if (gradient != m_singleHLGradient) { + if (m_singleHLGradient) + QObject::disconnect(m_singleHLGradient, 0, this, 0); + + m_singleHLGradient = gradient; + + if (m_singleHLGradient) { + QObject::connect(m_singleHLGradient, &ColorGradient::updated, this, + &DeclarativeTheme3D::handleSingleHLGradientUpdate); + } + + emit singleHighlightGradientChanged(m_singleHLGradient); + } + + if (m_singleHLGradient) + setThemeGradient(m_singleHLGradient, GradientTypeSingleHL); +} + +ColorGradient *DeclarativeTheme3D::singleHighlightGradient() const +{ + return m_singleHLGradient; +} + +void DeclarativeTheme3D::setMultiHighlightGradient(ColorGradient *gradient) +{ + // connect new / disconnect old + if (gradient != m_multiHLGradient) { + if (m_multiHLGradient) + QObject::disconnect(m_multiHLGradient, 0, this, 0); + + m_multiHLGradient = gradient; + + if (m_multiHLGradient) { + QObject::connect(m_multiHLGradient, &ColorGradient::updated, this, + &DeclarativeTheme3D::handleMultiHLGradientUpdate); + } + + emit multiHighlightGradientChanged(m_multiHLGradient); + } + + if (m_multiHLGradient) + setThemeGradient(m_multiHLGradient, GradientTypeMultiHL); +} + +ColorGradient *DeclarativeTheme3D::multiHighlightGradient() const +{ + return m_multiHLGradient; +} + +void DeclarativeTheme3D::classBegin() +{ + // Turn off predefined type forcing for the duration of initial class construction + // so that predefined type customization can be done. + d_ptr->setForcePredefinedType(false); +} + +void DeclarativeTheme3D::componentComplete() +{ + d_ptr->setForcePredefinedType(true); +} + + +void DeclarativeTheme3D::setThemeGradient(ColorGradient *gradient, GradientType type) +{ + QLinearGradient newGradient = convertGradient(gradient); + + switch (type) { + case GradientTypeSingleHL: + Q3DTheme::setSingleHighlightGradient(newGradient); + break; + case GradientTypeMultiHL: + Q3DTheme::setMultiHighlightGradient(newGradient); + break; + default: + qWarning("Incorrect usage. Type may be GradientTypeSingleHL or GradientTypeMultiHL."); + break; + } +} + +QLinearGradient DeclarativeTheme3D::convertGradient(ColorGradient *gradient) +{ + QLinearGradient newGradient; + QGradientStops stops; + QList<ColorGradientStop *> qmlstops = gradient->m_stops; + + // Get sorted gradient stops + for (int i = 0; i < qmlstops.size(); i++) { + int j = 0; + while (j < stops.size() && stops.at(j).first < qmlstops[i]->position()) + j++; + stops.insert(j, QGradientStop(qmlstops.at(i)->position(), qmlstops.at(i)->color())); + } + + newGradient.setStops(stops); + + return newGradient; +} + +ColorGradient *DeclarativeTheme3D::convertGradient(const QLinearGradient &gradient) +{ + ColorGradient *newGradient = new ColorGradient(this); + QGradientStops stops = gradient.stops(); + ColorGradientStop *qmlstop; + + // Convert stops + for (int i = 0; i < stops.size(); i++) { + qmlstop = new ColorGradientStop(newGradient); + qmlstop->setColor(stops.at(i).second); + qmlstop->setPosition(stops.at(i).first); + newGradient->m_stops.append(qmlstop); + } + + return newGradient; +} + +void DeclarativeTheme3D::addColor(DeclarativeColor *color) +{ + if (!color) { + qWarning("Color is invalid, use ThemeColor"); + return; + } + clearDummyColors(); + m_colors.append(color); + connect(color, &DeclarativeColor::colorChanged, + this, &DeclarativeTheme3D::handleBaseColorUpdate); + QList<QColor> list = Q3DTheme::baseColors(); + list.append(color->color()); + Q3DTheme::setBaseColors(list); +} + +QList<DeclarativeColor *> DeclarativeTheme3D::colorList() +{ + if (m_colors.isEmpty()) { + // Create dummy ThemeColors from theme's colors + m_dummyColors = true; + QList<QColor> list = Q3DTheme::baseColors(); + foreach (QColor item, list) { + DeclarativeColor *color = new DeclarativeColor(this); + color->setColor(item); + m_colors.append(color); + connect(color, &DeclarativeColor::colorChanged, + this, &DeclarativeTheme3D::handleBaseColorUpdate); + } + } + return m_colors; +} + +void DeclarativeTheme3D::clearColors() +{ + clearDummyColors(); + foreach (DeclarativeColor *item, m_colors) + disconnect(item, 0, this, 0); + m_colors.clear(); + Q3DTheme::setBaseColors(QList<QColor>()); +} + +void DeclarativeTheme3D::clearDummyColors() +{ + if (m_dummyColors) { + foreach (DeclarativeColor *item, m_colors) + delete item; + m_colors.clear(); + m_dummyColors = false; + } +} + +void DeclarativeTheme3D::addGradient(ColorGradient *gradient) +{ + if (!gradient) { + qWarning("Gradient is invalid, use ColorGradient"); + return; + } + clearDummyGradients(); + m_gradients.append(gradient); + connect(gradient, &ColorGradient::updated, + this, &DeclarativeTheme3D::handleBaseGradientUpdate); + QList<QLinearGradient> list = Q3DTheme::baseGradients(); + list.append(convertGradient(gradient)); + Q3DTheme::setBaseGradients(list); +} + +QList<ColorGradient *> DeclarativeTheme3D::gradientList() +{ + if (m_gradients.isEmpty()) { + // Create dummy ColorGradients from theme's gradients + m_dummyGradients = true; + QList<QLinearGradient> list = Q3DTheme::baseGradients(); + foreach (QLinearGradient item, list) { + ColorGradient *gradient = convertGradient(item); + m_gradients.append(gradient); + connect(gradient, &ColorGradient::updated, + this, &DeclarativeTheme3D::handleBaseGradientUpdate); + } + } + + return m_gradients; +} + +void DeclarativeTheme3D::clearGradients() +{ + clearDummyGradients(); + foreach (ColorGradient *item, m_gradients) + disconnect(item, 0, this, 0); + m_gradients.clear(); + Q3DTheme::setBaseGradients(QList<QLinearGradient>()); +} + +void DeclarativeTheme3D::clearDummyGradients() +{ + if (m_dummyGradients) { + foreach (ColorGradient *item, m_gradients) + delete item; + m_gradients.clear(); + m_dummyGradients = false; + } +} + +QQmlListProperty<DeclarativeColor> DeclarativeTheme3D::baseColors() +{ + return QQmlListProperty<DeclarativeColor>(this, this, + &DeclarativeTheme3D::appendBaseColorsFunc, + &DeclarativeTheme3D::countBaseColorsFunc, + &DeclarativeTheme3D::atBaseColorsFunc, + &DeclarativeTheme3D::clearBaseColorsFunc); +} + +void DeclarativeTheme3D::appendBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list, + DeclarativeColor *color) +{ + reinterpret_cast<DeclarativeTheme3D *>(list->data)->addColor(color); +} + +qsizetype DeclarativeTheme3D::countBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list) +{ + return reinterpret_cast<DeclarativeTheme3D *>(list->data)->colorList().size(); +} + +DeclarativeColor *DeclarativeTheme3D::atBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list, + qsizetype index) +{ + return reinterpret_cast<DeclarativeTheme3D *>(list->data)->colorList().at(index); +} + +void DeclarativeTheme3D::clearBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list) +{ + reinterpret_cast<DeclarativeTheme3D *>(list->data)->clearColors(); +} + +QQmlListProperty<ColorGradient> DeclarativeTheme3D::baseGradients() +{ + return QQmlListProperty<ColorGradient>(this, this, + &DeclarativeTheme3D::appendBaseGradientsFunc, + &DeclarativeTheme3D::countBaseGradientsFunc, + &DeclarativeTheme3D::atBaseGradientsFunc, + &DeclarativeTheme3D::clearBaseGradientsFunc); +} + +void DeclarativeTheme3D::appendBaseGradientsFunc(QQmlListProperty<ColorGradient> *list, + ColorGradient *gradient) +{ + reinterpret_cast<DeclarativeTheme3D *>(list->data)->addGradient(gradient); +} + +qsizetype DeclarativeTheme3D::countBaseGradientsFunc(QQmlListProperty<ColorGradient> *list) +{ + return reinterpret_cast<DeclarativeTheme3D *>(list->data)->gradientList().size(); +} + +ColorGradient *DeclarativeTheme3D::atBaseGradientsFunc(QQmlListProperty<ColorGradient> *list, + qsizetype index) +{ + return reinterpret_cast<DeclarativeTheme3D *>(list->data)->gradientList().at(index); +} + +void DeclarativeTheme3D::clearBaseGradientsFunc(QQmlListProperty<ColorGradient> *list) +{ + reinterpret_cast<DeclarativeTheme3D *>(list->data)->clearGradients(); +} + +QT_END_NAMESPACE diff --git a/src/datavisualizationqml/declarativetheme_p.h b/src/datavisualizationqml/declarativetheme_p.h new file mode 100644 index 00000000..8bc2f049 --- /dev/null +++ b/src/datavisualizationqml/declarativetheme_p.h @@ -0,0 +1,117 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef DECLARATIVETHEME_P_H +#define DECLARATIVETHEME_P_H + +#include <private/datavisualizationglobal_p.h> +#include <private/q3dtheme_p.h> + +#include "declarativecolor_p.h" +#include "colorgradient_p.h" + +#include <QtQml/qqml.h> +#include <QtQml/qqmlparserstatus.h> + +QT_BEGIN_NAMESPACE + +class DeclarativeTheme3D : public Q3DTheme, public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + Q_PROPERTY(QQmlListProperty<QObject> themeChildren READ themeChildren) + Q_PROPERTY(QQmlListProperty<DeclarativeColor> baseColors READ baseColors) + Q_PROPERTY(QQmlListProperty<ColorGradient> baseGradients READ baseGradients) + Q_PROPERTY(ColorGradient *singleHighlightGradient READ singleHighlightGradient WRITE setSingleHighlightGradient NOTIFY singleHighlightGradientChanged) + Q_PROPERTY(ColorGradient *multiHighlightGradient READ multiHighlightGradient WRITE setMultiHighlightGradient NOTIFY multiHighlightGradientChanged) + Q_CLASSINFO("DefaultProperty", "themeChildren") + QML_NAMED_ELEMENT(Theme3D) + QML_ADDED_IN_VERSION(1, 0) + +public: + DeclarativeTheme3D(QObject *parent = 0); + virtual ~DeclarativeTheme3D(); + + QQmlListProperty<QObject> themeChildren(); + static void appendThemeChildren(QQmlListProperty<QObject> *list, QObject *element); + + QQmlListProperty<DeclarativeColor> baseColors(); + static void appendBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list, + DeclarativeColor *color); + static qsizetype countBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list); + static DeclarativeColor *atBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list, + qsizetype index); + static void clearBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list); + + QQmlListProperty<ColorGradient> baseGradients(); + static void appendBaseGradientsFunc(QQmlListProperty<ColorGradient> *list, + ColorGradient *gradient); + static qsizetype countBaseGradientsFunc(QQmlListProperty<ColorGradient> *list); + static ColorGradient *atBaseGradientsFunc(QQmlListProperty<ColorGradient> *list, + qsizetype index); + static void clearBaseGradientsFunc(QQmlListProperty<ColorGradient> *list); + + void setSingleHighlightGradient(ColorGradient *gradient); + ColorGradient *singleHighlightGradient() const; + + void setMultiHighlightGradient(ColorGradient *gradient); + ColorGradient *multiHighlightGradient() const; + + // From QQmlParserStatus + void classBegin() override; + void componentComplete() override; + +Q_SIGNALS: + void singleHighlightGradientChanged(ColorGradient *gradient); + void multiHighlightGradientChanged(ColorGradient *gradient); + +protected: + void handleTypeChange(Theme themeType); + void handleBaseColorUpdate(); + void handleBaseGradientUpdate(); + void handleSingleHLGradientUpdate(); + void handleMultiHLGradientUpdate(); + + enum GradientType { + GradientTypeBase = 0, + GradientTypeSingleHL, + GradientTypeMultiHL + }; + +private: + void addColor(DeclarativeColor *color); + QList<DeclarativeColor *> colorList(); + void clearColors(); + void clearDummyColors(); + + void addGradient(ColorGradient *gradient); + QList<ColorGradient *> gradientList(); + void clearGradients(); + void clearDummyGradients(); + + void setThemeGradient(ColorGradient *gradient, GradientType type); + QLinearGradient convertGradient(ColorGradient *gradient); + ColorGradient *convertGradient(const QLinearGradient &gradient); + + QList<DeclarativeColor *> m_colors; // Not owned + QList<ColorGradient *> m_gradients; // Not owned + ColorGradient *m_singleHLGradient; // Not owned + ColorGradient *m_multiHLGradient; // Not owned + + bool m_dummyGradients; + bool m_dummyColors; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/datavisualizationqml/designer/Bars3DSpecifics.qml b/src/datavisualizationqml/designer/Bars3DSpecifics.qml new file mode 100644 index 00000000..d509fd84 --- /dev/null +++ b/src/datavisualizationqml/designer/Bars3DSpecifics.qml @@ -0,0 +1,387 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick 2.0 +import HelperWidgets 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.Controls 1.1 as Controls + +Column { + anchors.left: parent.left + anchors.right: parent.right + + Section { + anchors.left: parent.left + anchors.right: parent.right + caption: qsTr("Bars3D") + + SectionLayout { + Label { + text: qsTr("multiSeriesUniform") + tooltip: qsTr("Multiseries Uniform") + Layout.fillWidth: true + } + SecondColumnLayout { + CheckBox { + backendValue: backendValues.multiSeriesUniform + Layout.fillWidth: true + } + } + Label { + text: qsTr("barThickness") + tooltip: qsTr("Bar Thickness Ratio") + Layout.fillWidth: true + } + SecondColumnLayout { + SpinBox { + backendValue: backendValues.barThickness + minimumValue: 0.01 + maximumValue: 100.0 + stepSize: 0.01 + decimals: 2 + Layout.fillWidth: true + } + } + Label { + text: qsTr("barSpacing") + tooltip: qsTr("Bar Spacing") + Layout.fillWidth: true + } + SecondColumnLayout { + SpinBox { + prefix: "col: " + backendValue: backendValues.barSpacing_width + minimumValue: 0.0 + maximumValue: 10.0 + stepSize: 0.01 + decimals: 2 + Layout.fillWidth: true + } + SpinBox { + prefix: "row: " + backendValue: backendValues.barSpacing_height + minimumValue: 0.0 + maximumValue: 10.0 + stepSize: 0.01 + decimals: 2 + Layout.fillWidth: true + } + } + Label { + text: qsTr("barSpacingRelative") + tooltip: qsTr("Bar Spacing Relative") + Layout.fillWidth: true + } + SecondColumnLayout { + CheckBox { + backendValue: backendValues.barSpacingRelative + Layout.fillWidth: true + } + } + Label { + text: qsTr("renderingMode") + tooltip: qsTr("Rendering Mode") + Layout.fillWidth: true + } + SecondColumnLayout { + ComboBox { + backendValue: backendValues.renderingMode + model: ["RenderIndirect", "RenderDirectToBackground", + "RenderDirectToBackground_NoClear"] + Layout.fillWidth: true + scope: "AbstractGraph3D" + } + } + Label { + text: qsTr("msaaSamples") + tooltip: qsTr("MSAA Sample Count") + Layout.fillWidth: true + } + SpinBox { + suffix: " x MSAA" + backendValue: backendValues.msaaSamples + minimumValue: 0 + maximumValue: 16 + Layout.fillWidth: true + } + Label { + text: qsTr("shadowQuality") + tooltip: qsTr("Shadow Quality") + Layout.fillWidth: true + } + SecondColumnLayout { + ComboBox { + backendValue: backendValues.shadowQuality + model: ["ShadowQualityNone", "ShadowQualityLow", "ShadowQualityMedium", + "ShadowQualityHigh", "ShadowQualitySoftLow", "ShadowQualitySoftMedium", + "ShadowQualitySoftHigh"] + Layout.fillWidth: true + scope: "AbstractGraph3D" + } + } + Label { + text: qsTr("selectionMode") + tooltip: qsTr("Selection Mode") + Layout.fillWidth: true + } + SecondColumnLayout { + id: selectionLayout + property bool isInModel: backendValue.isInModel; + property bool isInSubState: backendValue.isInSubState; + property bool selectionChangedFlag: selectionChanged + property variant backendValue: backendValues.selectionMode + property variant valueFromBackend: backendValue.value + property string enumScope: "AbstractGraph3D" + property string enumSeparator: " | " + property int checkedCount: 0 + property bool selectionItem: false + property bool selectionRow: false + property bool selectionColumn: false + property bool selectionSlice: false + property bool selectionMulti: false + + function checkValue(checkedVariable, variableText, expressionBase) { + var expressionStr = expressionBase + if (checkedVariable) { + if (expressionStr !== "") { + expressionStr += enumSeparator + } + expressionStr += enumScope + expressionStr += "." + expressionStr += variableText + checkedCount++ + } + return expressionStr + } + + function composeSelectionMode() { + var expressionStr = "" + checkedCount = 0 + expressionStr = checkValue(selectionItem, "SelectionItem", expressionStr) + expressionStr = checkValue(selectionRow, "SelectionRow", expressionStr) + expressionStr = checkValue(selectionColumn, "SelectionColumn", expressionStr) + expressionStr = checkValue(selectionSlice, "SelectionSlice", expressionStr) + expressionStr = checkValue(selectionMulti, "SelectionMultiSeries", expressionStr) + + if (checkedCount === 0) + backendValue.expression = enumScope + ".SelectionNone" + else + backendValue.expression = expressionStr + } + + function evaluate() { + if (backendValue.value === undefined) + return + + selectionItem = (backendValue.expression.indexOf("SelectionItem") !== -1) + selectionRow = (backendValue.expression.indexOf("SelectionRow") !== -1) + selectionColumn = (backendValue.expression.indexOf("SelectionColumn") !== -1) + selectionSlice = (backendValue.expression.indexOf("SelectionSlice") !== -1) + selectionMulti = (backendValue.expression.indexOf("SelectionMultiSeries") !== -1) + + selectionItemBox.checked = selectionItem + selectionRowBox.checked = selectionRow + selectionColumnBox.checked = selectionColumn + selectionSliceBox.checked = selectionSlice + selectionMultiSeriesBox.checked = selectionMulti + } + + onSelectionChangedFlagChanged: evaluate() + + onIsInModelChanged: evaluate() + + onIsInSubStateChanged: evaluate() + + onBackendValueChanged: evaluate() + + onValueFromBackendChanged: evaluate() + + ColumnLayout { + anchors.fill: parent + + Controls.CheckBox { + id: selectionItemBox + style: checkBox.style + text: "SelectionItem" + Layout.fillWidth: true + onClicked: { + selectionLayout.selectionItem = checked + selectionLayout.composeSelectionMode() + } + } + Controls.CheckBox { + id: selectionRowBox + style: checkBox.style + text: "SelectionRow" + Layout.fillWidth: true + onClicked: { + selectionLayout.selectionRow = checked + selectionLayout.composeSelectionMode() + } + } + Controls.CheckBox { + id: selectionColumnBox + style: checkBox.style + text: "SelectionColumn" + Layout.fillWidth: true + onClicked: { + selectionLayout.selectionColumn = checked + selectionLayout.composeSelectionMode() + } + } + Controls.CheckBox { + id: selectionSliceBox + style: checkBox.style + text: "SelectionSlice" + Layout.fillWidth: true + onClicked: { + selectionLayout.selectionSlice = checked + selectionLayout.composeSelectionMode() + } + } + Controls.CheckBox { + id: selectionMultiSeriesBox + style: checkBox.style + text: "SelectionMultiSeries" + Layout.fillWidth: true + onClicked: { + selectionLayout.selectionMulti = checked + selectionLayout.composeSelectionMode() + } + } + } + } + Label { + text: qsTr("measureFps") + tooltip: qsTr("Measure Frames Per Second") + Layout.fillWidth: true + } + SecondColumnLayout { + CheckBox { + backendValue: backendValues.measureFps + Layout.fillWidth: true + } + } + Label { + text: qsTr("orthoProjection") + tooltip: qsTr("Use Orthographic Projection") + Layout.fillWidth: true + } + SecondColumnLayout { + CheckBox { + backendValue: backendValues.orthoProjection + Layout.fillWidth: true + } + } + Label { + text: qsTr("aspectRatio") + tooltip: qsTr("Aspect Ratio") + Layout.fillWidth: true + } + SecondColumnLayout { + SpinBox { + backendValue: backendValues.aspectRatio + minimumValue: 0.01 + maximumValue: 100.0 + stepSize: 0.01 + decimals: 2 + Layout.fillWidth: true + } + } + Label { + text: qsTr("floorLevel") + tooltip: qsTr("Floor Level") + Layout.fillWidth: true + } + SecondColumnLayout { + LineEdit { + backendValue: backendValues.floorLevel + inputMethodHints: Qt.ImhFormattedNumbersOnly + Layout.fillWidth: true + } + } + Label { + text: qsTr("horizontalAspectRatio") + tooltip: qsTr("Horizontal Aspect Ratio") + Layout.fillWidth: true + } + SecondColumnLayout { + SpinBox { + backendValue: backendValues.horizontalAspectRatio + minimumValue: 0.0 + maximumValue: 100.0 + stepSize: 0.01 + decimals: 2 + Layout.fillWidth: true + } + } + Label { + text: qsTr("reflection") + tooltip: qsTr("Reflection") + Layout.fillWidth: true + } + SecondColumnLayout { + CheckBox { + id: reflectionCheckbox + backendValue: backendValues.reflection + Layout.fillWidth: true + } + } + Label { + text: qsTr("reflectivity") + tooltip: qsTr("Reflectivity") + Layout.fillWidth: true + visible: reflectionCheckbox.checked + } + SecondColumnLayout { + visible: reflectionCheckbox.checked + SpinBox { + backendValue: backendValues.reflectivity + minimumValue: 0.0 + maximumValue: 1.0 + stepSize: 0.01 + decimals: 1 + Layout.fillWidth: true + } + } + Label { + text: qsTr("margin") + tooltip: qsTr("Graph Margin") + Layout.fillWidth: true + } + SecondColumnLayout { + SpinBox { + backendValue: backendValues.margin + minimumValue: -1.0 + maximumValue: 100.0 + stepSize: 0.1 + decimals: 1 + Layout.fillWidth: true + } + } + + // Kept for debugging + Label { } + SecondColumnLayout { + TextEdit { + id: debugLabel + Layout.fillWidth: true + wrapMode: TextEdit.WordWrap + textFormat: TextEdit.RichText + width: 400 + visible: false + } + } + Controls.CheckBox { + property color textColor: colorLogic.textColor + id: checkBox + style: CustomCheckBoxStyle {} + visible: false + ColorLogic { + id: colorLogic + backendValue: backendValues.selectionMode + } + } + } + } +} diff --git a/src/datavisualizationqml/designer/Scatter3DSpecifics.qml b/src/datavisualizationqml/designer/Scatter3DSpecifics.qml new file mode 100644 index 00000000..ffc79d44 --- /dev/null +++ b/src/datavisualizationqml/designer/Scatter3DSpecifics.qml @@ -0,0 +1,183 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick 2.0 +import HelperWidgets 2.0 +import QtQuick.Layouts 1.0 + +Column { + anchors.left: parent.left + anchors.right: parent.right + + Section { + anchors.left: parent.left + anchors.right: parent.right + caption: qsTr("Scatter3D") + + SectionLayout { + Label { + text: qsTr("renderingMode") + tooltip: qsTr("Rendering Mode") + Layout.fillWidth: true + } + SecondColumnLayout { + ComboBox { + backendValue: backendValues.renderingMode + model: ["RenderIndirect", "RenderDirectToBackground", + "RenderDirectToBackground_NoClear"] + Layout.fillWidth: true + scope: "AbstractGraph3D" + } + } + Label { + text: qsTr("msaaSamples") + tooltip: qsTr("MSAA Sample Count") + Layout.fillWidth: true + } + SpinBox { + suffix: " x MSAA" + backendValue: backendValues.msaaSamples + minimumValue: 0 + maximumValue: 16 + Layout.fillWidth: true + } + Label { + text: qsTr("shadowQuality") + tooltip: qsTr("Shadow Quality") + Layout.fillWidth: true + } + SecondColumnLayout { + ComboBox { + backendValue: backendValues.shadowQuality + model: ["ShadowQualityNone", "ShadowQualityLow", "ShadowQualityMedium", + "ShadowQualityHigh", "ShadowQualitySoftLow", "ShadowQualitySoftMedium", + "ShadowQualitySoftHigh"] + Layout.fillWidth: true + scope: "AbstractGraph3D" + } + } + Label { + text: qsTr("selectionMode") + tooltip: qsTr("Selection Mode") + Layout.fillWidth: true + } + SecondColumnLayout { + ComboBox { + backendValue: backendValues.selectionMode + model: ["SelectionNone", "SelectionItem"] + Layout.fillWidth: true + scope: "AbstractGraph3D" + } + } + Label { + text: qsTr("measureFps") + tooltip: qsTr("Measure Frames Per Second") + Layout.fillWidth: true + } + SecondColumnLayout { + CheckBox { + backendValue: backendValues.measureFps + Layout.fillWidth: true + } + } + Label { + text: qsTr("orthoProjection") + tooltip: qsTr("Use Orthographic Projection") + Layout.fillWidth: true + } + SecondColumnLayout { + CheckBox { + backendValue: backendValues.orthoProjection + Layout.fillWidth: true + } + } + Label { + text: qsTr("aspectRatio") + tooltip: qsTr("Horizontal to Vertical Aspect Ratio") + Layout.fillWidth: true + } + SecondColumnLayout { + SpinBox { + backendValue: backendValues.aspectRatio + minimumValue: 0.1 + maximumValue: 10.0 + stepSize: 0.1 + decimals: 1 + Layout.fillWidth: true + } + } + Label { + text: qsTr("optimizationHints") + tooltip: qsTr("Optimization Hints") + Layout.fillWidth: true + } + SecondColumnLayout { + ComboBox { + backendValue: backendValues.optimizationHints + model: ["OptimizationDefault", "OptimizationStatic"] + Layout.fillWidth: true + scope: "AbstractGraph3D" + } + } + Label { + text: qsTr("polar") + tooltip: qsTr("Use Polar Coordinates") + Layout.fillWidth: true + } + SecondColumnLayout { + CheckBox { + id: polarCheckbox + backendValue: backendValues.polar + Layout.fillWidth: true + } + } + Label { + text: qsTr("radialLabelOffset") + tooltip: qsTr("Radial Label Offset") + Layout.fillWidth: true + visible: polarCheckbox.checked + } + SecondColumnLayout { + visible: polarCheckbox.checked + SpinBox { + backendValue: backendValues.radialLabelOffset + minimumValue: 0.0 + maximumValue: 1.0 + stepSize: 0.01 + decimals: 2 + Layout.fillWidth: true + } + } + Label { + text: qsTr("horizontalAspectRatio") + tooltip: qsTr("Horizontal Aspect Ratio") + Layout.fillWidth: true + } + SecondColumnLayout { + SpinBox { + backendValue: backendValues.horizontalAspectRatio + minimumValue: 0.0 + maximumValue: 100.0 + stepSize: 0.01 + decimals: 2 + Layout.fillWidth: true + } + } + Label { + text: qsTr("margin") + tooltip: qsTr("Graph Margin") + Layout.fillWidth: true + } + SecondColumnLayout { + SpinBox { + backendValue: backendValues.margin + minimumValue: -1.0 + maximumValue: 100.0 + stepSize: 0.1 + decimals: 1 + Layout.fillWidth: true + } + } + } + } +} diff --git a/src/datavisualizationqml/designer/Surface3DSpecifics.qml b/src/datavisualizationqml/designer/Surface3DSpecifics.qml new file mode 100644 index 00000000..33ca7d75 --- /dev/null +++ b/src/datavisualizationqml/designer/Surface3DSpecifics.qml @@ -0,0 +1,324 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick 2.0 +import HelperWidgets 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.Controls 1.1 as Controls + +Column { + anchors.left: parent.left + anchors.right: parent.right + + Section { + anchors.left: parent.left + anchors.right: parent.right + caption: qsTr("Surface3D") + + SectionLayout { + Label { + text: qsTr("renderingMode") + tooltip: qsTr("Rendering Mode") + Layout.fillWidth: true + } + SecondColumnLayout { + ComboBox { + backendValue: backendValues.renderingMode + model: ["RenderIndirect", "RenderDirectToBackground", + "RenderDirectToBackground_NoClear"] + Layout.fillWidth: true + scope: "AbstractGraph3D" + } + } + Label { + text: qsTr("msaaSamples") + tooltip: qsTr("MSAA Sample Count") + Layout.fillWidth: true + } + SpinBox { + suffix: " x MSAA" + backendValue: backendValues.msaaSamples + minimumValue: 0 + maximumValue: 16 + Layout.fillWidth: true + } + Label { + text: qsTr("shadowQuality") + tooltip: qsTr("Shadow Quality") + Layout.fillWidth: true + } + SecondColumnLayout { + ComboBox { + backendValue: backendValues.shadowQuality + model: ["ShadowQualityNone", "ShadowQualityLow", "ShadowQualityMedium", + "ShadowQualityHigh", "ShadowQualitySoftLow", "ShadowQualitySoftMedium", + "ShadowQualitySoftHigh"] + Layout.fillWidth: true + scope: "AbstractGraph3D" + } + } + Label { + text: qsTr("selectionMode") + tooltip: qsTr("Selection Mode") + Layout.fillWidth: true + } + SecondColumnLayout { + id: selectionLayout + property bool isInModel: backendValue.isInModel; + property bool isInSubState: backendValue.isInSubState; + property bool selectionChangedFlag: selectionChanged + property variant backendValue: backendValues.selectionMode + property variant valueFromBackend: backendValue.value + property string enumScope: "AbstractGraph3D" + property string enumSeparator: " | " + property int checkedCount: 0 + property bool selectionItem: false + property bool selectionRow: false + property bool selectionColumn: false + property bool selectionSlice: false + property bool selectionMulti: false + + function checkValue(checkedVariable, variableText, expressionBase) { + var expressionStr = expressionBase + if (checkedVariable) { + if (expressionStr !== "") { + expressionStr += enumSeparator + } + expressionStr += enumScope + expressionStr += "." + expressionStr += variableText + checkedCount++ + } + return expressionStr + } + + function composeSelectionMode() { + var expressionStr = "" + checkedCount = 0 + expressionStr = checkValue(selectionItem, "SelectionItem", expressionStr) + expressionStr = checkValue(selectionRow, "SelectionRow", expressionStr) + expressionStr = checkValue(selectionColumn, "SelectionColumn", expressionStr) + expressionStr = checkValue(selectionSlice, "SelectionSlice", expressionStr) + expressionStr = checkValue(selectionMulti, "SelectionMultiSeries", expressionStr) + + if (checkedCount === 0) + backendValue.expression = enumScope + ".SelectionNone" + else + backendValue.expression = expressionStr + } + + function evaluate() { + if (backendValue.value === undefined) + return + + selectionItem = (backendValue.expression.indexOf("SelectionItem") !== -1) + selectionRow = (backendValue.expression.indexOf("SelectionRow") !== -1) + selectionColumn = (backendValue.expression.indexOf("SelectionColumn") !== -1) + selectionSlice = (backendValue.expression.indexOf("SelectionSlice") !== -1) + selectionMulti = (backendValue.expression.indexOf("SelectionMultiSeries") !== -1) + + selectionItemBox.checked = selectionItem + selectionRowBox.checked = selectionRow + selectionColumnBox.checked = selectionColumn + selectionSliceBox.checked = selectionSlice + selectionMultiSeriesBox.checked = selectionMulti + } + + onSelectionChangedFlagChanged: evaluate() + + onIsInModelChanged: evaluate() + + onIsInSubStateChanged: evaluate() + + onBackendValueChanged: evaluate() + + onValueFromBackendChanged: evaluate() + + ColumnLayout { + anchors.fill: parent + + Controls.CheckBox { + id: selectionItemBox + style: checkBox.style + text: "SelectionItem" + Layout.fillWidth: true + onClicked: { + selectionLayout.selectionItem = checked + selectionLayout.composeSelectionMode() + } + } + Controls.CheckBox { + id: selectionRowBox + style: checkBox.style + text: "SelectionRow" + Layout.fillWidth: true + onClicked: { + selectionLayout.selectionRow = checked + selectionLayout.composeSelectionMode() + } + } + Controls.CheckBox { + id: selectionColumnBox + style: checkBox.style + text: "SelectionColumn" + Layout.fillWidth: true + onClicked: { + selectionLayout.selectionColumn = checked + selectionLayout.composeSelectionMode() + } + } + Controls.CheckBox { + id: selectionSliceBox + style: checkBox.style + text: "SelectionSlice" + Layout.fillWidth: true + onClicked: { + selectionLayout.selectionSlice = checked + selectionLayout.composeSelectionMode() + } + } + Controls.CheckBox { + id: selectionMultiSeriesBox + style: checkBox.style + text: "SelectionMultiSeries" + Layout.fillWidth: true + onClicked: { + selectionLayout.selectionMulti = checked + selectionLayout.composeSelectionMode() + } + } + } + } + Label { + text: qsTr("measureFps") + tooltip: qsTr("Measure Frames Per Second") + Layout.fillWidth: true + } + SecondColumnLayout { + CheckBox { + backendValue: backendValues.measureFps + Layout.fillWidth: true + } + } + Label { + text: qsTr("orthoProjection") + tooltip: qsTr("Use Orthographic Projection") + Layout.fillWidth: true + } + SecondColumnLayout { + CheckBox { + backendValue: backendValues.orthoProjection + Layout.fillWidth: true + } + } + Label { + text: qsTr("aspectRatio") + tooltip: qsTr("Horizontal to Vertical Aspect Ratio") + Layout.fillWidth: true + } + SecondColumnLayout { + SpinBox { + backendValue: backendValues.aspectRatio + minimumValue: 0.1 + maximumValue: 10.0 + stepSize: 0.1 + decimals: 1 + Layout.fillWidth: true + } + } + Label { + text: qsTr("flipHorizontalGrid") + tooltip: qsTr("Flip Horizontal Grid") + Layout.fillWidth: true + } + SecondColumnLayout { + CheckBox { + backendValue: backendValues.flipHorizontalGrid + Layout.fillWidth: true + } + } + Label { + text: qsTr("polar") + tooltip: qsTr("Use Polar Coordinates") + Layout.fillWidth: true + } + SecondColumnLayout { + CheckBox { + id: polarCheckbox + backendValue: backendValues.polar + Layout.fillWidth: true + } + } + Label { + text: qsTr("radialLabelOffset") + tooltip: qsTr("Radial Label Offset") + Layout.fillWidth: true + visible: polarCheckbox.checked + } + SecondColumnLayout { + visible: polarCheckbox.checked + SpinBox { + backendValue: backendValues.radialLabelOffset + minimumValue: 0.0 + maximumValue: 1.0 + stepSize: 0.01 + decimals: 2 + Layout.fillWidth: true + } + } + Label { + text: qsTr("horizontalAspectRatio") + tooltip: qsTr("Horizontal Aspect Ratio") + Layout.fillWidth: true + } + SecondColumnLayout { + SpinBox { + backendValue: backendValues.horizontalAspectRatio + minimumValue: 0.0 + maximumValue: 100.0 + stepSize: 0.01 + decimals: 2 + Layout.fillWidth: true + } + } + Label { + text: qsTr("margin") + tooltip: qsTr("Graph Margin") + Layout.fillWidth: true + } + SecondColumnLayout { + SpinBox { + backendValue: backendValues.margin + minimumValue: -1.0 + maximumValue: 100.0 + stepSize: 0.1 + decimals: 1 + Layout.fillWidth: true + } + } + + // Kept for debugging + Label { } + SecondColumnLayout { + TextEdit { + id: debugLabel + Layout.fillWidth: true + wrapMode: TextEdit.WordWrap + textFormat: TextEdit.RichText + width: 400 + visible: false + } + } + Controls.CheckBox { + property color textColor: colorLogic.textColor + id: checkBox + style: CustomCheckBoxStyle {} + visible: false + ColorLogic { + id: colorLogic + backendValue: backendValues.selectionMode + } + } + } + } +} diff --git a/src/datavisualizationqml/designer/default/Bars3D.qml b/src/datavisualizationqml/designer/default/Bars3D.qml new file mode 100644 index 00000000..8c56b67c --- /dev/null +++ b/src/datavisualizationqml/designer/default/Bars3D.qml @@ -0,0 +1,23 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick 2.0 +import QtDataVisualization 1.2 + +Bars3D { + width: 300 + height: 300 + Bar3DSeries { + ItemModelBarDataProxy { + itemModel: ListModel { + ListElement{ row: "row 1"; column: "column 1"; value: "1"; } + ListElement{ row: "row 1"; column: "column 2"; value: "2"; } + ListElement{ row: "row 1"; column: "column 3"; value: "3"; } + } + + rowRole: "row" + columnRole: "column" + valueRole: "value" + } + } +} diff --git a/src/datavisualizationqml/designer/default/Scatter3D.qml b/src/datavisualizationqml/designer/default/Scatter3D.qml new file mode 100644 index 00000000..5a6cd261 --- /dev/null +++ b/src/datavisualizationqml/designer/default/Scatter3D.qml @@ -0,0 +1,23 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick 2.0 +import QtDataVisualization 1.2 + +Scatter3D { + width: 300 + height: 300 + Scatter3DSeries { + ItemModelScatterDataProxy { + itemModel: ListModel { + ListElement{ x: "1"; y: "2"; z: "3"; } + ListElement{ x: "2"; y: "3"; z: "4"; } + ListElement{ x: "3"; y: "4"; z: "1"; } + } + + xPosRole: "x" + yPosRole: "y" + zPosRole: "z" + } + } +} diff --git a/src/datavisualizationqml/designer/default/Surface3D.qml b/src/datavisualizationqml/designer/default/Surface3D.qml new file mode 100644 index 00000000..24561890 --- /dev/null +++ b/src/datavisualizationqml/designer/default/Surface3D.qml @@ -0,0 +1,24 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick 2.0 +import QtDataVisualization 1.2 + +Surface3D { + width: 300 + height: 300 + Surface3DSeries { + ItemModelSurfaceDataProxy { + itemModel: ListModel { + ListElement{ row: "1"; column: "1"; y: "1"; } + ListElement{ row: "1"; column: "2"; y: "2"; } + ListElement{ row: "2"; column: "1"; y: "3"; } + ListElement{ row: "2"; column: "2"; y: "4"; } + } + + rowRole: "row" + columnRole: "column" + yPosRole: "y" + } + } +} diff --git a/src/datavisualizationqml/designer/images/bars3d-icon.png b/src/datavisualizationqml/designer/images/bars3d-icon.png Binary files differnew file mode 100644 index 00000000..7f380789 --- /dev/null +++ b/src/datavisualizationqml/designer/images/bars3d-icon.png diff --git a/src/datavisualizationqml/designer/images/bars3d-icon16.png b/src/datavisualizationqml/designer/images/bars3d-icon16.png Binary files differnew file mode 100644 index 00000000..e85ff502 --- /dev/null +++ b/src/datavisualizationqml/designer/images/bars3d-icon16.png diff --git a/src/datavisualizationqml/designer/images/scatter3d-icon.png b/src/datavisualizationqml/designer/images/scatter3d-icon.png Binary files differnew file mode 100644 index 00000000..e1ac5c1f --- /dev/null +++ b/src/datavisualizationqml/designer/images/scatter3d-icon.png diff --git a/src/datavisualizationqml/designer/images/scatter3d-icon16.png b/src/datavisualizationqml/designer/images/scatter3d-icon16.png Binary files differnew file mode 100644 index 00000000..75b2db18 --- /dev/null +++ b/src/datavisualizationqml/designer/images/scatter3d-icon16.png diff --git a/src/datavisualizationqml/designer/images/surface3d-icon.png b/src/datavisualizationqml/designer/images/surface3d-icon.png Binary files differnew file mode 100644 index 00000000..956c675e --- /dev/null +++ b/src/datavisualizationqml/designer/images/surface3d-icon.png diff --git a/src/datavisualizationqml/designer/images/surface3d-icon16.png b/src/datavisualizationqml/designer/images/surface3d-icon16.png Binary files differnew file mode 100644 index 00000000..6caa643e --- /dev/null +++ b/src/datavisualizationqml/designer/images/surface3d-icon16.png diff --git a/src/datavisualizationqml/designer/qtdatavisualization.metainfo b/src/datavisualizationqml/designer/qtdatavisualization.metainfo new file mode 100644 index 00000000..60b2b2c2 --- /dev/null +++ b/src/datavisualizationqml/designer/qtdatavisualization.metainfo @@ -0,0 +1,44 @@ +MetaInfo { + Type { + name: "QtDataVisualization.Bars3D" + icon: "images/bars3d-icon16.png" + + ItemLibraryEntry { + name: "Bars3D" + category: "Qt Data Visualization" + libraryIcon: "images/bars3d-icon.png" + version: "1.0" + requiredImport: "QtDataVisualization" + + QmlSource { source: "default/Bars3D.qml" } + } + } + Type { + name: "QtDataVisualization.Scatter3D" + icon: "images/scatter3d-icon16.png" + + ItemLibraryEntry { + name: "Scatter3D" + category: "Qt Data Visualization" + libraryIcon: "images/scatter3d-icon.png" + version: "1.0" + requiredImport: "QtDataVisualization" + + QmlSource { source: "default/Scatter3D.qml" } + } + } + Type { + name: "QtDataVisualization.Surface3D" + icon: "images/surface3d-icon16.png" + + ItemLibraryEntry { + name: "Surface3D" + category: "Qt Data Visualization" + libraryIcon: "images/surface3d-icon.png" + version: "1.0" + requiredImport: "QtDataVisualization" + + QmlSource { source: "default/Surface3D.qml" } + } + } +} diff --git a/src/datavisualizationqml/enumtostringmap.cpp b/src/datavisualizationqml/enumtostringmap.cpp new file mode 100644 index 00000000..c411f7a9 --- /dev/null +++ b/src/datavisualizationqml/enumtostringmap.cpp @@ -0,0 +1,387 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "enumtostringmap_p.h" + +#ifdef VERBOSE_STATE_STORE + +#include <QDebug> + +static EnumToStringMap *theInstance = 0; +static unsigned int theInstanceCount = 0; + +EnumToStringMap *EnumToStringMap::newInstance() +{ + if (theInstance) { + theInstanceCount++; + return theInstance; + } + + theInstance = new EnumToStringMap(); + theInstanceCount++; + return theInstance; +} + +void EnumToStringMap::deleteInstance() +{ + theInstanceCount--; + if (theInstanceCount <= 0) { + delete theInstance; + theInstance = 0; + } +} + +EnumToStringMap::EnumToStringMap() : + m_unknown("<unknown>") +{ + m_map[GL_ZERO] = "ZERO/null"; + + m_map[GL_DEPTH_BUFFER_BIT] = "DEPTH_BUFFER_BIT"; + m_map[GL_STENCIL_BUFFER_BIT] = "STENCIL_BUFFER_BIT"; + m_map[GL_COLOR_BUFFER_BIT] = "COLOR_BUFFER_BIT"; + + m_map[GL_STENCIL_BUFFER_BIT] = "STENCIL_BUFFER_BIT"; + m_map[GL_COLOR_BUFFER_BIT] = "COLOR_BUFFER_BIT"; + + m_map[GL_POINTS] = "POINTS"; + m_map[GL_LINES] = "LINES"; + m_map[GL_LINE_LOOP] = "LINE_LOOP"; + m_map[GL_LINE_STRIP] = "LINE_STRIP"; + m_map[GL_TRIANGLES] = "TRIANGLES"; + m_map[GL_TRIANGLE_STRIP] = "TRIANGLE_STRIP"; + m_map[GL_TRIANGLE_FAN] = "TRIANGLE_FAN"; + + m_map[GL_SRC_COLOR] = "SRC_COLOR"; + m_map[GL_ONE_MINUS_SRC_COLOR] = "ONE_MINUS_SRC_COLOR"; + m_map[GL_SRC_ALPHA] = "SRC_ALPHA"; + m_map[GL_ONE_MINUS_SRC_ALPHA] = "ONE_MINUS_SRC_ALPHA"; + m_map[GL_DST_ALPHA] = "DST_ALPHA"; + m_map[GL_ONE_MINUS_DST_ALPHA] = "ONE_MINUS_DST_ALPHA"; + + m_map[GL_DST_COLOR] = "DST_COLOR"; + m_map[GL_ONE_MINUS_DST_COLOR] = "ONE_MINUS_DST_COLOR"; + m_map[GL_SRC_ALPHA_SATURATE] = "SRC_ALPHA_SATURATE"; + + m_map[GL_FUNC_ADD] = "FUNC_ADD"; + m_map[GL_BLEND_EQUATION] = "BLEND_EQUATION"; + m_map[GL_BLEND_EQUATION_RGB] = "BLEND_EQUATION_RGB"; + m_map[GL_BLEND_EQUATION_ALPHA] = "BLEND_EQUATION_ALPHA"; + + m_map[GL_FUNC_SUBTRACT] = "FUNC_SUBTRACT"; + m_map[GL_FUNC_REVERSE_SUBTRACT] = "FUNC_REVERSE_SUBTRACT"; + + m_map[GL_BLEND_DST_RGB] = "BLEND_DST_RGB"; + m_map[GL_BLEND_SRC_RGB] = "BLEND_SRC_RGB"; + m_map[GL_BLEND_DST_ALPHA] = "BLEND_DST_ALPHA"; + m_map[GL_BLEND_SRC_ALPHA] = "BLEND_SRC_ALPHA"; + m_map[GL_CONSTANT_COLOR] = "CONSTANT_COLOR"; + m_map[GL_ONE_MINUS_CONSTANT_COLOR] = "ONE_MINUS_CONSTANT_COLOR"; + m_map[GL_CONSTANT_ALPHA] = "CONSTANT_ALPHA"; + m_map[GL_ONE_MINUS_CONSTANT_ALPHA] = "ONE_MINUS_CONSTANT_ALPHA"; + m_map[GL_BLEND_COLOR] = "BLEND_COLOR"; + + m_map[GL_ARRAY_BUFFER] = "ARRAY_BUFFER"; + m_map[GL_ELEMENT_ARRAY_BUFFER] = "ELEMENT_ARRAY_BUFFER"; + m_map[GL_ARRAY_BUFFER_BINDING] = "ARRAY_BUFFER_BINDING"; + m_map[GL_ELEMENT_ARRAY_BUFFER_BINDING] = "ELEMENT_ARRAY_BUFFER_BINDING"; + + m_map[GL_STREAM_DRAW] = "STREAM_DRAW"; + m_map[GL_STATIC_DRAW] = "STATIC_DRAW"; + m_map[GL_DYNAMIC_DRAW] = "DYNAMIC_DRAW"; + + m_map[GL_BUFFER_SIZE] = "BUFFER_SIZE"; + m_map[GL_BUFFER_USAGE] = "BUFFER_USAGE"; + + m_map[GL_CURRENT_VERTEX_ATTRIB] = "CURRENT_VERTEX_ATTRIB"; + + m_map[GL_FRONT] = "FRONT"; + m_map[GL_BACK] = "BACK"; + m_map[GL_FRONT_AND_BACK] = "FRONT_AND_BACK"; + + m_map[GL_CULL_FACE] = "CULL_FACE"; + m_map[GL_BLEND] = "BLEND"; + m_map[GL_DITHER] = "DITHER"; + m_map[GL_STENCIL_TEST] = "STENCIL_TEST"; + m_map[GL_DEPTH_TEST] = "DEPTH_TEST"; + m_map[GL_SCISSOR_TEST] = "SCISSOR_TEST"; + m_map[GL_POLYGON_OFFSET_FILL] = "POLYGON_OFFSET_FILL"; + m_map[GL_SAMPLE_ALPHA_TO_COVERAGE] = "SAMPLE_ALPHA_TO_COVERAGE"; + m_map[GL_SAMPLE_COVERAGE] = "SAMPLE_COVERAGE"; + + m_map[GL_NO_ERROR] = "NO_ERROR"; + m_map[GL_INVALID_ENUM] = "INVALID_ENUM"; + m_map[GL_INVALID_VALUE] = "INVALID_VALUE"; + m_map[GL_INVALID_OPERATION] = "INVALID_OPERATION"; + m_map[GL_OUT_OF_MEMORY] = "OUT_OF_MEMORY"; + + m_map[GL_CW] = "CW"; + m_map[GL_CCW] = "CCW"; + + m_map[GL_LINE_WIDTH] = "LINE_WIDTH"; + m_map[GL_ALIASED_POINT_SIZE_RANGE] = "ALIASED_POINT_SIZE_RANGE"; + m_map[GL_ALIASED_LINE_WIDTH_RANGE] = "ALIASED_LINE_WIDTH_RANGE"; + m_map[GL_CULL_FACE_MODE] = "CULL_FACE_MODE"; + m_map[GL_FRONT_FACE] = "FRONT_FACE"; + m_map[GL_DEPTH_RANGE] = "DEPTH_RANGE"; + m_map[GL_DEPTH_WRITEMASK] = "DEPTH_WRITEMASK"; + m_map[GL_DEPTH_CLEAR_VALUE] = "DEPTH_CLEAR_VALUE"; + m_map[GL_DEPTH_FUNC] = "DEPTH_FUNC"; + m_map[GL_STENCIL_CLEAR_VALUE] = "STENCIL_CLEAR_VALUE"; + m_map[GL_STENCIL_FUNC] = "STENCIL_FUNC"; + m_map[GL_STENCIL_FAIL] = "STENCIL_FAIL"; + m_map[GL_STENCIL_PASS_DEPTH_FAIL] = "STENCIL_PASS_DEPTH_FAIL"; + m_map[GL_STENCIL_PASS_DEPTH_PASS] = "STENCIL_PASS_DEPTH_PASS"; + m_map[GL_STENCIL_REF] = "STENCIL_REF"; + m_map[GL_STENCIL_VALUE_MASK] = "STENCIL_VALUE_MASK"; + m_map[GL_STENCIL_WRITEMASK] = "STENCIL_WRITEMASK"; + m_map[GL_STENCIL_BACK_FUNC] = "STENCIL_BACK_FUNC"; + m_map[GL_STENCIL_BACK_FAIL] = "STENCIL_BACK_FAIL"; + m_map[GL_STENCIL_BACK_PASS_DEPTH_FAIL] = "STENCIL_BACK_PASS_DEPTH_FAIL"; + m_map[GL_STENCIL_BACK_PASS_DEPTH_PASS] = "STENCIL_BACK_PASS_DEPTH_PASS"; + m_map[GL_STENCIL_BACK_REF] = "STENCIL_BACK_REF"; + m_map[GL_STENCIL_BACK_VALUE_MASK] = "STENCIL_BACK_VALUE_MASK"; + m_map[GL_STENCIL_BACK_WRITEMASK] = "STENCIL_BACK_WRITEMASK"; + m_map[GL_VIEWPORT] = "VIEWPORT"; + m_map[GL_SCISSOR_BOX] = "SCISSOR_BOX"; + + m_map[GL_COLOR_CLEAR_VALUE] = "COLOR_CLEAR_VALUE"; + m_map[GL_COLOR_WRITEMASK] = "COLOR_WRITEMASK"; + m_map[GL_UNPACK_ALIGNMENT] = "UNPACK_ALIGNMENT"; + m_map[GL_PACK_ALIGNMENT] = "PACK_ALIGNMENT"; + m_map[GL_MAX_TEXTURE_SIZE] = "MAX_TEXTURE_SIZE"; + m_map[GL_MAX_VIEWPORT_DIMS] = "MAX_VIEWPORT_DIMS"; + m_map[GL_SUBPIXEL_BITS] = "SUBPIXEL_BITS"; + m_map[GL_RED_BITS] = "RED_BITS"; + m_map[GL_GREEN_BITS] = "GREEN_BITS"; + m_map[GL_BLUE_BITS] = "BLUE_BITS"; + m_map[GL_ALPHA_BITS] = "ALPHA_BITS"; + m_map[GL_DEPTH_BITS] = "DEPTH_BITS"; + m_map[GL_STENCIL_BITS] = "STENCIL_BITS"; + m_map[GL_POLYGON_OFFSET_UNITS] = "POLYGON_OFFSET_UNITS"; + + m_map[GL_POLYGON_OFFSET_FACTOR] = "POLYGON_OFFSET_FACTOR"; + m_map[GL_TEXTURE_BINDING_2D] = "TEXTURE_BINDING_2D"; + m_map[GL_SAMPLE_BUFFERS] = "SAMPLE_BUFFERS"; + m_map[GL_SAMPLES] = "SAMPLES"; + m_map[GL_SAMPLE_COVERAGE_VALUE] = "SAMPLE_COVERAGE_VALUE"; + m_map[GL_SAMPLE_COVERAGE_INVERT] = "SAMPLE_COVERAGE_INVERT"; + + m_map[GL_COMPRESSED_TEXTURE_FORMATS] = "COMPRESSED_TEXTURE_FORMATS"; + + m_map[GL_DONT_CARE] = "DONT_CARE"; + m_map[GL_FASTEST] = "FASTEST"; + m_map[GL_NICEST] = "NICEST"; + + m_map[GL_GENERATE_MIPMAP_HINT] = "GENERATE_MIPMAP_HINT"; + + m_map[GL_BYTE] = "BYTE"; + m_map[GL_UNSIGNED_BYTE] = "UNSIGNED_BYTE"; + m_map[GL_SHORT] = "SHORT"; + m_map[GL_UNSIGNED_SHORT] = "UNSIGNED_SHORT"; + m_map[GL_INT] = "INT"; + m_map[GL_UNSIGNED_INT] = "UNSIGNED_INT"; + m_map[GL_FLOAT] = "FLOAT"; + + m_map[GL_DEPTH_COMPONENT] = "DEPTH_COMPONENT"; + m_map[GL_ALPHA] = "ALPHA"; + m_map[GL_RGB] = "RGB"; + m_map[GL_RGBA] = "RGBA"; + m_map[GL_LUMINANCE] = "LUMINANCE"; + m_map[GL_LUMINANCE_ALPHA] = "LUMINANCE_ALPHA"; + + m_map[GL_UNSIGNED_SHORT_4_4_4_4] = "UNSIGNED_SHORT_4_4_4_4"; + m_map[GL_UNSIGNED_SHORT_5_5_5_1] = "UNSIGNED_SHORT_5_5_5_1"; + m_map[GL_UNSIGNED_SHORT_5_6_5] = "UNSIGNED_SHORT_5_6_5"; + + m_map[GL_FRAGMENT_SHADER] = "FRAGMENT_SHADER"; + m_map[GL_VERTEX_SHADER] = "VERTEX_SHADER"; + m_map[GL_MAX_VERTEX_ATTRIBS] = "MAX_VERTEX_ATTRIBS"; + m_map[GL_MAX_VERTEX_UNIFORM_VECTORS] = "MAX_VERTEX_UNIFORM_VECTORS"; + m_map[GL_MAX_VARYING_VECTORS] = "MAX_VARYING_VECTORS"; + m_map[GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS] = "MAX_COMBINED_TEXTURE_IMAGE_UNITS"; + m_map[GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS] = "MAX_VERTEX_TEXTURE_IMAGE_UNITS"; + m_map[GL_MAX_TEXTURE_IMAGE_UNITS] = "MAX_TEXTURE_IMAGE_UNITS"; + m_map[GL_MAX_FRAGMENT_UNIFORM_VECTORS] = "MAX_FRAGMENT_UNIFORM_VECTORS"; + m_map[GL_SHADER_TYPE] = "SHADER_TYPE"; + m_map[GL_DELETE_STATUS] = "DELETE_STATUS"; + m_map[GL_LINK_STATUS] = "LINK_STATUS"; + m_map[GL_VALIDATE_STATUS] = "VALIDATE_STATUS"; + m_map[GL_ATTACHED_SHADERS] = "ATTACHED_SHADERS"; + m_map[GL_ACTIVE_UNIFORMS] = "ACTIVE_UNIFORMS"; + m_map[GL_ACTIVE_ATTRIBUTES] = "ACTIVE_ATTRIBUTES"; + m_map[GL_SHADING_LANGUAGE_VERSION] = "SHADING_LANGUAGE_VERSION"; + m_map[GL_CURRENT_PROGRAM] = "CURRENT_PROGRAM"; + + m_map[GL_NEVER] = "NEVER"; + m_map[GL_LESS] = "LESS"; + m_map[GL_EQUAL] = "EQUAL"; + m_map[GL_LEQUAL] = "LEQUAL"; + m_map[GL_GREATER] = "GREATER"; + m_map[GL_NOTEQUAL] = "NOTEQUAL"; + m_map[GL_GEQUAL] = "GEQUAL"; + m_map[GL_ALWAYS] = "ALWAYS"; + + m_map[GL_KEEP] = "KEEP"; + m_map[GL_REPLACE] = "REPLACE"; + m_map[GL_INCR] = "INCR"; + m_map[GL_DECR] = "DECR"; + m_map[GL_INVERT] = "INVERT"; + m_map[GL_INCR_WRAP] = "INCR_WRAP"; + m_map[GL_DECR_WRAP] = "DECR_WRAP"; + + m_map[GL_VENDOR] = "VENDOR"; + m_map[GL_RENDERER] = "RENDERER"; + m_map[GL_VERSION] = "VERSION"; + + m_map[GL_NEAREST] = "NEAREST"; + m_map[GL_LINEAR] = "LINEAR"; + + m_map[GL_NEAREST_MIPMAP_NEAREST] = "NEAREST_MIPMAP_NEAREST"; + m_map[GL_LINEAR_MIPMAP_NEAREST] = "LINEAR_MIPMAP_NEAREST"; + m_map[GL_NEAREST_MIPMAP_LINEAR] = "NEAREST_MIPMAP_LINEAR"; + m_map[GL_LINEAR_MIPMAP_LINEAR] = "LINEAR_MIPMAP_LINEAR"; + + m_map[GL_TEXTURE_MAG_FILTER] = "TEXTURE_MAG_FILTER"; + m_map[GL_TEXTURE_MIN_FILTER] = "TEXTURE_MIN_FILTER"; + m_map[GL_TEXTURE_WRAP_S] = "TEXTURE_WRAP_S"; + m_map[GL_TEXTURE_WRAP_T] = "TEXTURE_WRAP_T"; + + m_map[GL_TEXTURE_2D] = "TEXTURE_2D"; + m_map[GL_TEXTURE] = "TEXTURE"; + + m_map[GL_TEXTURE_CUBE_MAP] = "TEXTURE_CUBE_MAP"; + m_map[GL_TEXTURE_BINDING_CUBE_MAP] = "TEXTURE_BINDING_CUBE_MAP"; + m_map[GL_TEXTURE_CUBE_MAP_POSITIVE_X] = "TEXTURE_CUBE_MAP_POSITIVE_X"; + m_map[GL_TEXTURE_CUBE_MAP_NEGATIVE_X] = "TEXTURE_CUBE_MAP_NEGATIVE_X"; + m_map[GL_TEXTURE_CUBE_MAP_POSITIVE_Y] = "TEXTURE_CUBE_MAP_POSITIVE_Y"; + m_map[GL_TEXTURE_CUBE_MAP_NEGATIVE_Y] = "TEXTURE_CUBE_MAP_NEGATIVE_Y"; + m_map[GL_TEXTURE_CUBE_MAP_POSITIVE_Z] = "TEXTURE_CUBE_MAP_POSITIVE_Z"; + m_map[GL_TEXTURE_CUBE_MAP_NEGATIVE_Z] = "TEXTURE_CUBE_MAP_NEGATIVE_Z"; + m_map[GL_MAX_CUBE_MAP_TEXTURE_SIZE] = "MAX_CUBE_MAP_TEXTURE_SIZE"; + + m_map[GL_TEXTURE0] = "TEXTURE0"; + m_map[GL_TEXTURE1] = "TEXTURE1"; + m_map[GL_TEXTURE2] = "TEXTURE2"; + m_map[GL_TEXTURE3] = "TEXTURE3"; + m_map[GL_TEXTURE4] = "TEXTURE4"; + m_map[GL_TEXTURE5] = "TEXTURE5"; + m_map[GL_TEXTURE6] = "TEXTURE6"; + m_map[GL_TEXTURE7] = "TEXTURE7"; + m_map[GL_TEXTURE8] = "TEXTURE8"; + m_map[GL_TEXTURE9] = "TEXTURE9"; + m_map[GL_TEXTURE10] = "TEXTURE10"; + m_map[GL_TEXTURE11] = "TEXTURE11"; + m_map[GL_TEXTURE12] = "TEXTURE12"; + m_map[GL_TEXTURE13] = "TEXTURE13"; + m_map[GL_TEXTURE14] = "TEXTURE14"; + m_map[GL_TEXTURE15] = "TEXTURE15"; + m_map[GL_TEXTURE16] = "TEXTURE16"; + m_map[GL_TEXTURE17] = "TEXTURE17"; + m_map[GL_TEXTURE18] = "TEXTURE18"; + m_map[GL_TEXTURE19] = "TEXTURE19"; + m_map[GL_TEXTURE20] = "TEXTURE20"; + m_map[GL_TEXTURE21] = "TEXTURE21"; + m_map[GL_TEXTURE22] = "TEXTURE22"; + m_map[GL_TEXTURE23] = "TEXTURE23"; + m_map[GL_TEXTURE24] = "TEXTURE24"; + m_map[GL_TEXTURE25] = "TEXTURE25"; + m_map[GL_TEXTURE26] = "TEXTURE26"; + m_map[GL_TEXTURE27] = "TEXTURE27"; + m_map[GL_TEXTURE28] = "TEXTURE28"; + m_map[GL_TEXTURE29] = "TEXTURE29"; + m_map[GL_TEXTURE30] = "TEXTURE30"; + m_map[GL_TEXTURE31] = "TEXTURE31"; + m_map[GL_ACTIVE_TEXTURE] = "ACTIVE_TEXTURE"; + + m_map[GL_REPEAT] = "REPEAT"; + m_map[GL_CLAMP_TO_EDGE] = "CLAMP_TO_EDGE"; + m_map[GL_MIRRORED_REPEAT] = "MIRRORED_REPEAT"; + + m_map[GL_FLOAT_VEC2] = "FLOAT_VEC2"; + m_map[GL_FLOAT_VEC3] = "FLOAT_VEC3"; + m_map[GL_FLOAT_VEC4] = "FLOAT_VEC4"; + m_map[GL_INT_VEC2] = "INT_VEC2"; + m_map[GL_INT_VEC3] = "INT_VEC3"; + m_map[GL_INT_VEC4] = "INT_VEC4"; + m_map[GL_BOOL] = "BOOL"; + m_map[GL_BOOL_VEC2] = "BOOL_VEC2"; + m_map[GL_BOOL_VEC3] = "BOOL_VEC3"; + m_map[GL_BOOL_VEC4] = "BOOL_VEC4"; + m_map[GL_FLOAT_MAT2] = "FLOAT_MAT2"; + m_map[GL_FLOAT_MAT3] = "FLOAT_MAT3"; + m_map[GL_FLOAT_MAT4] = "FLOAT_MAT4"; + m_map[GL_SAMPLER_2D] = "SAMPLER_2D"; + m_map[GL_SAMPLER_CUBE] = "SAMPLER_CUBE"; + + m_map[GL_VERTEX_ATTRIB_ARRAY_ENABLED] = "VERTEX_ATTRIB_ARRAY_ENABLED"; + m_map[GL_VERTEX_ATTRIB_ARRAY_SIZE] = "VERTEX_ATTRIB_ARRAY_SIZE"; + m_map[GL_VERTEX_ATTRIB_ARRAY_STRIDE] = "VERTEX_ATTRIB_ARRAY_STRIDE"; + m_map[GL_VERTEX_ATTRIB_ARRAY_TYPE] = "VERTEX_ATTRIB_ARRAY_TYPE"; + m_map[GL_VERTEX_ATTRIB_ARRAY_NORMALIZED] = "VERTEX_ATTRIB_ARRAY_NORMALIZED"; + m_map[GL_VERTEX_ATTRIB_ARRAY_POINTER] = "VERTEX_ATTRIB_ARRAY_POINTER"; + m_map[GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING] = "VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"; + + m_map[GL_COMPILE_STATUS] = "COMPILE_STATUS"; + + m_map[GL_LOW_FLOAT] = "LOW_FLOAT"; + m_map[GL_MEDIUM_FLOAT] = "MEDIUM_FLOAT"; + m_map[GL_HIGH_FLOAT] = "HIGH_FLOAT"; + m_map[GL_LOW_INT] = "LOW_INT"; + m_map[GL_MEDIUM_INT] = "MEDIUM_INT"; + m_map[GL_HIGH_INT] = "HIGH_INT"; + + m_map[GL_FRAMEBUFFER] = "FRAMEBUFFER"; + m_map[GL_RENDERBUFFER] = "RENDERBUFFER"; + + m_map[GL_RGBA4] = "RGBA4"; + m_map[GL_RGB5_A1] = "RGB5_A1"; + m_map[GL_RGB565] = "RGB565"; + m_map[GL_DEPTH_COMPONENT16] = "DEPTH_COMPONENT16"; + m_map[GL_STENCIL_INDEX] = "STENCIL_INDEX"; + m_map[GL_STENCIL_INDEX8] = "STENCIL_INDEX8"; + + m_map[GL_RENDERBUFFER_WIDTH] = "RENDERBUFFER_WIDTH"; + m_map[GL_RENDERBUFFER_HEIGHT] = "RENDERBUFFER_HEIGHT"; + m_map[GL_RENDERBUFFER_INTERNAL_FORMAT] = "RENDERBUFFER_INTERNAL_FORMAT"; + m_map[GL_RENDERBUFFER_RED_SIZE] = "RENDERBUFFER_RED_SIZE"; + m_map[GL_RENDERBUFFER_GREEN_SIZE] = "RENDERBUFFER_GREEN_SIZE"; + m_map[GL_RENDERBUFFER_BLUE_SIZE] = "RENDERBUFFER_BLUE_SIZE"; + m_map[GL_RENDERBUFFER_ALPHA_SIZE] = "RENDERBUFFER_ALPHA_SIZE"; + m_map[GL_RENDERBUFFER_DEPTH_SIZE] = "RENDERBUFFER_DEPTH_SIZE"; + m_map[GL_RENDERBUFFER_STENCIL_SIZE] = "RENDERBUFFER_STENCIL_SIZE"; + + m_map[GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE] = "FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE"; + m_map[GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME] = "FRAMEBUFFER_ATTACHMENT_OBJECT_NAME"; + m_map[GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL] = "FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL"; + m_map[GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE] = + "FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE"; + + m_map[GL_COLOR_ATTACHMENT0] = "COLOR_ATTACHMENT0"; + m_map[GL_DEPTH_ATTACHMENT] = "DEPTH_ATTACHMENT"; + m_map[GL_STENCIL_ATTACHMENT] = "STENCIL_ATTACHMENT"; + + m_map[GL_FRAMEBUFFER_COMPLETE] = "FRAMEBUFFER_COMPLETE"; + m_map[GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT] = "FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; + m_map[GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT] = + "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; + m_map[GL_FRAMEBUFFER_UNSUPPORTED] = "FRAMEBUFFER_UNSUPPORTED"; + + m_map[GL_FRAMEBUFFER_BINDING] = "FRAMEBUFFER_BINDING"; +#if !QT_CONFIG(opengles2) + m_map[GL_RENDERBUFFER_BINDING] = "RENDERBUFFER_BINDING"; +#else + m_map[GL_RENDERBUFFER] = "RENDERBUFFER_BINDING"; +#endif + m_map[GL_MAX_RENDERBUFFER_SIZE] = "MAX_RENDERBUFFER_SIZE"; + + m_map[GL_INVALID_FRAMEBUFFER_OPERATION] = "INVALID_FRAMEBUFFER_OPERATION"; +} + +QString EnumToStringMap::lookUp(const GLuint value) const +{ + if (m_map.contains(value)) + return m_map[value]; + + return QString("0x0%1").arg(value, 0, 16); +} +#endif diff --git a/src/datavisualizationqml/enumtostringmap_p.h b/src/datavisualizationqml/enumtostringmap_p.h new file mode 100644 index 00000000..b8be3f18 --- /dev/null +++ b/src/datavisualizationqml/enumtostringmap_p.h @@ -0,0 +1,39 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef ENUMTOSTRINGMAP_P_H +#define ENUMTOSTRINGMAP_P_H + +//#define VERBOSE_STATE_STORE + +#ifdef VERBOSE_STATE_STORE + +#include <QtGui/qopengl.h> +#include <QMap> +#include <QString> +#include <private/qglobal_p.h> + +class EnumToStringMap +{ +public: + static EnumToStringMap *newInstance(); + static void deleteInstance(); + QString lookUp(const GLuint value) const; + +private: + EnumToStringMap(); + QMap<int, QString> m_map; + QString m_unknown; +}; +#endif +#endif diff --git a/src/datavisualizationqml/foreigntypes_p.h b/src/datavisualizationqml/foreigntypes_p.h new file mode 100644 index 00000000..0b92d862 --- /dev/null +++ b/src/datavisualizationqml/foreigntypes_p.h @@ -0,0 +1,122 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef FOREIGNTYPES_P_H +#define FOREIGNTYPES_P_H + +#include <QtQml/qqml.h> + +#include <QtCore/qabstractitemmodel.h> + +#include <QtDataVisualization/q3dcamera.h> +#include <QtDataVisualization/q3dinputhandler.h> +#include <QtDataVisualization/q3dlight.h> +#include <QtDataVisualization/q3dobject.h> +#include <QtDataVisualization/q3dscene.h> +#include <QtDataVisualization/q3dtheme.h> +#include <QtDataVisualization/qabstract3daxis.h> +#include <QtDataVisualization/qabstract3dinputhandler.h> +#include <QtDataVisualization/qabstract3dseries.h> +#include <QtDataVisualization/qabstractdataproxy.h> +#include <QtDataVisualization/qbar3dseries.h> +#include <QtDataVisualization/qbardataproxy.h> +#include <QtDataVisualization/qcategory3daxis.h> +#include <QtDataVisualization/qcustom3ditem.h> +#include <QtDataVisualization/qcustom3dlabel.h> +#include <QtDataVisualization/qcustom3dvolume.h> +#include <QtDataVisualization/qheightmapsurfacedataproxy.h> +#include <QtDataVisualization/qitemmodelbardataproxy.h> +#include <QtDataVisualization/qitemmodelscatterdataproxy.h> +#include <QtDataVisualization/qitemmodelsurfacedataproxy.h> +#include <QtDataVisualization/qlogvalue3daxisformatter.h> +#include <QtDataVisualization/qscatter3dseries.h> +#include <QtDataVisualization/qscatterdataproxy.h> +#include <QtDataVisualization/qsurface3dseries.h> +#include <QtDataVisualization/qsurfacedataproxy.h> +#include <QtDataVisualization/qtouch3dinputhandler.h> +#include <QtDataVisualization/qvalue3daxis.h> +#include <QtDataVisualization/qvalue3daxisformatter.h> +#include <QtCore/private/qglobal_p.h> + +QT_BEGIN_NAMESPACE + +#define DEFINE_FOREIGN_BASE_ATTRIBUTES(type, name, minor) \ + Q_GADGET \ + QML_NAMED_ELEMENT(name) \ + QML_FOREIGN(type) \ + QML_ADDED_IN_VERSION(1, minor) \ + +#define DEFINE_FOREIGN_UNCREATABLE_TYPE(type, name) \ + struct type##DataVisForeign \ + { \ + DEFINE_FOREIGN_BASE_ATTRIBUTES(type, name, 0) \ + QML_UNCREATABLE("Trying to create uncreatable: " #name ".") \ + }; + +#define DEFINE_FOREIGN_CREATABLE_TYPE(type, name, minor) \ + struct type##DataVisForeign \ + { \ + DEFINE_FOREIGN_BASE_ATTRIBUTES(type, name, minor) \ + }; + +#define DEFINE_FOREIGN_REPLACED_TYPE(type, name, better) \ + struct type##DataVisForeign \ + { \ + DEFINE_FOREIGN_BASE_ATTRIBUTES(type, name, 0) \ + QML_UNCREATABLE("Trying to create uncreatable: " #name ", use " #better " instead.") \ + }; + +struct Q3DSceneForeign +{ + Q_GADGET + QML_ANONYMOUS + QML_ADDED_IN_VERSION(1, 0) + QML_FOREIGN(Q3DScene) +}; + +DEFINE_FOREIGN_CREATABLE_TYPE(Q3DCamera, Camera3D, 0) +DEFINE_FOREIGN_CREATABLE_TYPE(Q3DLight, Light3D, 0) +DEFINE_FOREIGN_CREATABLE_TYPE(QCategory3DAxis, CategoryAxis3D, 0) +DEFINE_FOREIGN_CREATABLE_TYPE(QHeightMapSurfaceDataProxy, HeightMapSurfaceDataProxy, 0) +DEFINE_FOREIGN_CREATABLE_TYPE(QItemModelBarDataProxy, ItemModelBarDataProxy, 0) +DEFINE_FOREIGN_CREATABLE_TYPE(QItemModelScatterDataProxy, ItemModelScatterDataProxy, 0) +DEFINE_FOREIGN_CREATABLE_TYPE(QItemModelSurfaceDataProxy, ItemModelSurfaceDataProxy, 0) +DEFINE_FOREIGN_CREATABLE_TYPE(QValue3DAxis, ValueAxis3D, 0) + +DEFINE_FOREIGN_CREATABLE_TYPE(QCustom3DItem, Custom3DItem, 1) +DEFINE_FOREIGN_CREATABLE_TYPE(QCustom3DLabel, Custom3DLabel, 1) +DEFINE_FOREIGN_CREATABLE_TYPE(QLogValue3DAxisFormatter, LogValueAxis3DFormatter, 1) +DEFINE_FOREIGN_CREATABLE_TYPE(QValue3DAxisFormatter, ValueAxis3DFormatter, 1) + +DEFINE_FOREIGN_CREATABLE_TYPE(Q3DInputHandler, InputHandler3D, 2) +DEFINE_FOREIGN_CREATABLE_TYPE(QCustom3DVolume, Custom3DVolume, 2) +DEFINE_FOREIGN_CREATABLE_TYPE(QTouch3DInputHandler, TouchInputHandler3D, 2) + +DEFINE_FOREIGN_REPLACED_TYPE(Q3DTheme, Q3DTheme, Theme3D) +DEFINE_FOREIGN_REPLACED_TYPE(QBar3DSeries, QBar3DSeries, Bar3DSeries) +DEFINE_FOREIGN_REPLACED_TYPE(QScatter3DSeries, QScatter3DSeries, Scatter3DSeries) +DEFINE_FOREIGN_REPLACED_TYPE(QSurface3DSeries, QSurface3DSeries, Surface3DSeries) + +DEFINE_FOREIGN_UNCREATABLE_TYPE(Q3DObject, Object3D) +DEFINE_FOREIGN_UNCREATABLE_TYPE(QAbstract3DAxis, AbstractAxis3D) +DEFINE_FOREIGN_UNCREATABLE_TYPE(QAbstract3DInputHandler, AbstractInputHandler3D) +DEFINE_FOREIGN_UNCREATABLE_TYPE(QAbstract3DSeries, Abstract3DSeries) +DEFINE_FOREIGN_UNCREATABLE_TYPE(QAbstractDataProxy, AbstractDataProxy) +DEFINE_FOREIGN_UNCREATABLE_TYPE(QAbstractItemModel, AbstractItemModel) +DEFINE_FOREIGN_UNCREATABLE_TYPE(QBarDataProxy, BarDataProxy) +DEFINE_FOREIGN_UNCREATABLE_TYPE(QScatterDataProxy, ScatterDataProxy) +DEFINE_FOREIGN_UNCREATABLE_TYPE(QSurfaceDataProxy, SurfaceDataProxy) + +QT_END_NAMESPACE + +#endif // FOREIGNTYPES_P_H diff --git a/src/datavisualizationqml/glstatestore.cpp b/src/datavisualizationqml/glstatestore.cpp new file mode 100644 index 00000000..573835a3 --- /dev/null +++ b/src/datavisualizationqml/glstatestore.cpp @@ -0,0 +1,367 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "glstatestore_p.h" +#include <QDebug> +#include <QColor> +#include <QFile> + +#ifdef VERBOSE_STATE_STORE +static QFile *beforeFile = 0; +static QFile *afterFile = 0; +#endif + +GLStateStore::GLStateStore(QOpenGLContext *context, QObject *parent) : + QObject(parent), + QOpenGLFunctions(context) + #ifdef VERBOSE_STATE_STORE + , m_map(EnumToStringMap::newInstance()) + #endif +{ + GLint maxVertexAttribs; + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); + +#ifdef VERBOSE_STATE_STORE + qDebug() << "GL_MAX_VERTEX_ATTRIBS: " << maxVertexAttribs; + if (!beforeFile) { + beforeFile = new QFile(QStringLiteral("state_before.txt")); + afterFile = new QFile(QStringLiteral("state_after.txt")); + beforeFile->open(QIODevice::WriteOnly); + afterFile->open(QIODevice::WriteOnly); + QDebug beforeInit(beforeFile); + QDebug afterInit(afterFile); + beforeInit << "GL states before 'context switch'" << endl; + afterInit << "GL states after 'context switch'" << endl; + } +#endif + + m_maxVertexAttribs = qMin(maxVertexAttribs, 2); // Datavis only uses 2 attribs max + m_vertexAttribArrayEnabledStates.reset(new GLint[maxVertexAttribs]); + m_vertexAttribArrayBoundBuffers.reset(new GLint[maxVertexAttribs]); + m_vertexAttribArraySizes.reset(new GLint[maxVertexAttribs]); + m_vertexAttribArrayTypes.reset(new GLint[maxVertexAttribs]); + m_vertexAttribArrayNormalized.reset(new GLint[maxVertexAttribs]); + m_vertexAttribArrayStrides.reset(new GLint[maxVertexAttribs]); + m_vertexAttribArrayOffsets.reset(new void *[maxVertexAttribs]); + + initGLDefaultState(); +} + +GLStateStore::~GLStateStore() +{ +#ifdef VERBOSE_STATE_STORE + EnumToStringMap::deleteInstance(); + m_map = 0; +#endif +} + +void GLStateStore::storeGLState() +{ +#ifdef VERBOSE_STATE_STORE + printCurrentState(true); +#endif + +#if !QT_CONFIG(opengles2) + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &m_drawFramebuffer); + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &m_readFramebuffer); + glGetIntegerv(GL_RENDERBUFFER_BINDING, &m_renderbuffer); +#endif + glGetFloatv(GL_COLOR_CLEAR_VALUE, m_clearColor); + m_isBlendingEnabled = glIsEnabled(GL_BLEND); + m_isDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST); + glGetBooleanv(GL_DEPTH_WRITEMASK, &m_isDepthWriteEnabled); + glGetFloatv(GL_DEPTH_CLEAR_VALUE, &m_clearDepth); + glGetIntegerv(GL_DEPTH_FUNC, &m_depthFunc); + glGetBooleanv(GL_POLYGON_OFFSET_FILL, &m_polygonOffsetFillEnabled); + glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &m_polygonOffsetFactor); + glGetFloatv(GL_POLYGON_OFFSET_UNITS, &m_polygonOffsetUnits); + + glGetIntegerv(GL_CURRENT_PROGRAM, &m_currentProgram); + glGetIntegerv(GL_ACTIVE_TEXTURE, &m_activeTexture); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &m_texBinding2D); + glGetIntegerv(GL_FRONT_FACE, &m_frontFace); + m_isCullFaceEnabled = glIsEnabled(GL_CULL_FACE); + glGetIntegerv(GL_CULL_FACE_MODE, &m_cullFaceMode); + glGetIntegerv(GL_BLEND_EQUATION_RGB, &m_blendEquationRGB); + glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &m_blendEquationAlpha); + glGetIntegerv(GL_BLEND_DST_ALPHA, &m_blendDestAlpha); + glGetIntegerv(GL_BLEND_DST_RGB, &m_blendDestRGB); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &m_blendSrcAlpha); + glGetIntegerv(GL_BLEND_SRC_RGB, &m_blendSrcRGB); + glGetIntegerv(GL_SCISSOR_BOX, m_scissorBox); + m_isScissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST); + + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &m_boundArrayBuffer); + glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &m_boundElementArrayBuffer); + + for (int i = 0; i < m_maxVertexAttribs;i++) { + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, + &m_vertexAttribArrayEnabledStates[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, + &m_vertexAttribArrayBoundBuffers[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &m_vertexAttribArraySizes[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &m_vertexAttribArrayTypes[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, + &m_vertexAttribArrayNormalized[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &m_vertexAttribArrayStrides[i]); + } +} + +#ifdef VERBOSE_STATE_STORE +void GLStateStore::printCurrentState(bool in) +{ + QFile *file; + if (in) + file = beforeFile; + else + file = afterFile; + + if (file->isOpen()) { + QDebug msg(file); +#if !QT_CONFIG(opengles2) + GLint drawFramebuffer; + GLint readFramebuffer; + GLint renderbuffer; +#endif + GLfloat clearColor[4]; + GLfloat clearDepth; + GLboolean isBlendingEnabled = glIsEnabled(GL_BLEND); + GLboolean isDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST); + GLint depthFunc; + GLboolean isDepthWriteEnabled; + GLint currentProgram; + GLint *vertexAttribArrayEnabledStates = new GLint[m_maxVertexAttribs]; + GLint *vertexAttribArrayBoundBuffers = new GLint[m_maxVertexAttribs]; + GLint *vertexAttribArraySizes = new GLint[m_maxVertexAttribs]; + GLint *vertexAttribArrayTypes = new GLint[m_maxVertexAttribs]; + GLint *vertexAttribArrayNormalized = new GLint[m_maxVertexAttribs]; + GLint *vertexAttribArrayStrides = new GLint[m_maxVertexAttribs]; + GLint activeTexture; + GLint texBinding2D; + GLint arrayBufferBinding; + GLint frontFace; + GLboolean isCullFaceEnabled = glIsEnabled(GL_CULL_FACE); + GLint cullFaceMode; + GLint blendEquationRGB; + GLint blendEquationAlpha; + + GLint blendDestAlpha; + GLint blendDestRGB; + GLint blendSrcAlpha; + GLint blendSrcRGB; + GLint scissorBox[4]; + GLboolean isScissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST); + GLint boundElementArrayBuffer; + GLboolean polygonOffsetFillEnabled; + GLfloat polygonOffsetFactor; + GLfloat polygonOffsetUnits; + + glGetBooleanv(GL_DEPTH_WRITEMASK, &isDepthWriteEnabled); +#if !QT_CONFIG(opengles2) + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFramebuffer); + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &readFramebuffer); + glGetIntegerv(GL_RENDERBUFFER_BINDING, &renderbuffer); +#endif + glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor); + glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth); + glGetIntegerv(GL_DEPTH_FUNC, &depthFunc); + glGetBooleanv(GL_POLYGON_OFFSET_FILL, &polygonOffsetFillEnabled); + glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &polygonOffsetFactor); + glGetFloatv(GL_POLYGON_OFFSET_UNITS, &polygonOffsetUnits); + + glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProgram); + glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &texBinding2D ); + glGetIntegerv(GL_FRONT_FACE, &frontFace); + glGetIntegerv(GL_CULL_FACE_MODE, &cullFaceMode); + glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB); + glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha); + glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha); + glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha); + glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB); + glGetIntegerv(GL_SCISSOR_BOX, scissorBox); + glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &boundElementArrayBuffer); + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &arrayBufferBinding); + + for (int i = 0; i < m_maxVertexAttribs;i++) { + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, + &vertexAttribArrayEnabledStates[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, + &vertexAttribArrayBoundBuffers[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &vertexAttribArraySizes[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &vertexAttribArrayTypes[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, + &vertexAttribArrayNormalized[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &vertexAttribArrayStrides[i]); + } + + QColor color; + color.setRgbF(clearColor[0], clearColor[1], clearColor[2]); + color.setAlphaF(clearColor[3]); + +#if !QT_CONFIG(opengles2) + msg << "---" << endl; + msg << " GL_DRAW_FRAMEBUFFER_BINDING "<< drawFramebuffer << endl; + msg << " GL_READ_FRAMEBUFFER_BINDING "<< readFramebuffer << endl; + msg << " GL_RENDERBUFFER_BINDING " << renderbuffer << endl; +#endif + msg << " GL_SCISSOR_TEST " << bool(isScissorTestEnabled) << endl; + msg << " GL_SCISSOR_BOX " << m_scissorBox[0] << m_scissorBox[1] << m_scissorBox[2] + << m_scissorBox[3] << endl; + msg << " GL_COLOR_CLEAR_VALUE "<< color << endl; + msg << " GL_DEPTH_CLEAR_VALUE "<< clearDepth << endl; + msg << " GL_BLEND "<< bool(isBlendingEnabled) << endl; + msg << " GL_BLEND_EQUATION_RGB" << m_map->lookUp(blendEquationRGB) << endl; + msg << " GL_BLEND_EQUATION_ALPHA" << m_map->lookUp(blendEquationAlpha) << endl; + msg << " GL_BLEND_DST_ALPHA" << m_map->lookUp(blendDestAlpha) << endl; + msg << " GL_BLEND_DST_RGB" << m_map->lookUp(blendDestRGB) << endl; + msg << " GL_BLEND_SRC_ALPHA" << m_map->lookUp(blendSrcAlpha) << endl; + msg << " GL_BLEND_SRC_RGB" << m_map->lookUp(blendSrcRGB) << endl; + msg << " GL_DEPTH_TEST "<< bool(isDepthTestEnabled) << endl; + msg << " GL_DEPTH_WRITEMASK "<< bool(isDepthWriteEnabled) << endl; + msg << " GL_POLYGON_OFFSET_FILL" << bool(polygonOffsetFillEnabled) << endl; + msg << " GL_POLYGON_OFFSET_FACTOR "<< polygonOffsetFactor << endl; + msg << " GL_POLYGON_OFFSET_UNITS "<< polygonOffsetUnits << endl; + msg << " GL_CULL_FACE "<< bool(isCullFaceEnabled) << endl; + msg << " GL_CULL_FACE_MODE "<< m_map->lookUp(cullFaceMode) << endl; + msg << " GL_DEPTH_FUNC "<< m_map->lookUp(depthFunc) << endl; + msg << " GL_FRONT_FACE "<< m_map->lookUp(frontFace) << endl; + msg << " GL_CURRENT_PROGRAM "<< currentProgram << endl; + msg << " GL_ACTIVE_TEXTURE "<< QString("0x%1").arg(activeTexture, 0, 16) << endl; + msg << " GL_TEXTURE_BINDING_2D "<< texBinding2D << endl; + msg << " GL_ELEMENT_ARRAY_BUFFER_BINDING "<< boundElementArrayBuffer << endl; + msg << " GL_ARRAY_BUFFER_BINDING "<< arrayBufferBinding << endl; + for (int i = 0; i < m_maxVertexAttribs;i++) { + msg << " GL_VERTEX_ATTRIB_ARRAY_ENABLED "<< i << " = " + << bool(vertexAttribArrayEnabledStates[i]) << endl; + msg << " GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"<< i << " = " + << vertexAttribArrayBoundBuffers[i] << endl; + msg << " GL_VERTEX_ATTRIB_ARRAY_SIZE"<< i << " = " + << vertexAttribArraySizes[i] << endl; + msg << " GL_VERTEX_ATTRIB_ARRAY_TYPE"<< i << " = " + << vertexAttribArrayTypes[i] << endl; + msg << " GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"<< i << " = " + << vertexAttribArrayNormalized[i] << endl; + msg << " GL_VERTEX_ATTRIB_ARRAY_STRIDE"<< i << " = " + << vertexAttribArrayStrides[i] << endl; + } + } +} +#endif + +void GLStateStore::restoreGLState() +{ +#if !QT_CONFIG(opengles2) + glBindFramebuffer(GL_READ_FRAMEBUFFER, m_readFramebuffer); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_drawFramebuffer); + glBindRenderbuffer(GL_RENDERBUFFER_BINDING, m_renderbuffer); +#endif + + if (m_isScissorTestEnabled) + glEnable(GL_SCISSOR_TEST); + else + glDisable(GL_SCISSOR_TEST); + + glScissor(m_scissorBox[0], m_scissorBox[1], m_scissorBox[2], m_scissorBox[3]); + glClearColor(m_clearColor[0], m_clearColor[1], m_clearColor[2], m_clearColor[3]); + glClearDepthf(m_clearDepth); + if (m_isBlendingEnabled) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + + if (m_isDepthTestEnabled) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); + + if (m_isCullFaceEnabled) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); + + glCullFace(m_cullFaceMode); + + glBlendEquationSeparate(m_blendEquationRGB, m_blendEquationAlpha); + glBlendFuncSeparate(m_blendSrcRGB, m_blendDestRGB, m_blendSrcAlpha, m_blendDestAlpha); + + glDepthMask(m_isDepthWriteEnabled); + glDepthFunc(m_depthFunc); + glFrontFace(m_frontFace); + + if (m_polygonOffsetFillEnabled) + glEnable(GL_POLYGON_OFFSET_FILL); + else + glDisable(GL_POLYGON_OFFSET_FILL); + + glPolygonOffset(m_polygonOffsetFactor, m_polygonOffsetUnits); + + glUseProgram(m_currentProgram); + + glActiveTexture(m_activeTexture); + glBindTexture(GL_TEXTURE_2D, m_texBinding2D); + + // Restore bound element array buffer and array buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_boundElementArrayBuffer); + for (int i = 0; i < m_maxVertexAttribs; i++) { + if (m_vertexAttribArrayEnabledStates[i]) + glEnableVertexAttribArray(i); + else + glDisableVertexAttribArray(i); + + glBindBuffer(GL_ARRAY_BUFFER, m_vertexAttribArrayBoundBuffers[i]); + glVertexAttribPointer(i, m_vertexAttribArraySizes[i], + m_vertexAttribArrayTypes[i], + m_vertexAttribArrayNormalized[i], + m_vertexAttribArrayStrides[i], + m_vertexAttribArrayOffsets[i]); + } + + glBindBuffer(GL_ARRAY_BUFFER, m_boundArrayBuffer); + +#ifdef VERBOSE_STATE_STORE + printCurrentState(false); +#endif +} + +void GLStateStore::initGLDefaultState() +{ +#if !QT_CONFIG(opengles2) + m_drawFramebuffer = 0; + m_readFramebuffer = 0; + m_renderbuffer = 0; +#endif + m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 1.0f; + m_clearDepth = 1.0f; + m_isBlendingEnabled = GL_FALSE; + m_isDepthTestEnabled = GL_FALSE; + m_depthFunc = GL_LESS; + m_isDepthWriteEnabled = GL_TRUE; + m_currentProgram = 0; + m_texBinding2D = 0; + for (int i = 0; i < m_maxVertexAttribs;i++) { + m_vertexAttribArrayEnabledStates[i] = GL_FALSE; + m_vertexAttribArrayBoundBuffers[i] = 0; + m_vertexAttribArraySizes[i] = 4; + m_vertexAttribArrayTypes[i] = GL_FLOAT; + m_vertexAttribArrayNormalized[i] = GL_FALSE; + m_vertexAttribArrayStrides[i] = 0; + m_vertexAttribArrayOffsets[i] = 0; + } + m_activeTexture = GL_TEXTURE0; + m_frontFace = GL_CCW; + m_isCullFaceEnabled = false; + m_cullFaceMode = GL_BACK; + m_blendEquationRGB = GL_FUNC_ADD; + m_blendEquationAlpha = GL_FUNC_ADD; + m_scissorBox[0] = 0; + m_scissorBox[1] = 0; + m_scissorBox[2] = 0; + m_scissorBox[3] = 0; + m_isScissorTestEnabled = GL_FALSE; + + m_polygonOffsetFillEnabled = GL_FALSE; + m_polygonOffsetFactor = 0.0; + m_polygonOffsetUnits = 0.0; +} diff --git a/src/datavisualizationqml/glstatestore_p.h b/src/datavisualizationqml/glstatestore_p.h new file mode 100644 index 00000000..b34a4c0d --- /dev/null +++ b/src/datavisualizationqml/glstatestore_p.h @@ -0,0 +1,79 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef GLSTATESTORE_P_H +#define GLSTATESTORE_P_H + +#include <QtGui/QOpenGLFunctions> +#include <QtCore/QScopedArrayPointer> +#include "enumtostringmap_p.h" + +class GLStateStore : public QObject, protected QOpenGLFunctions +{ + Q_OBJECT +public: + explicit GLStateStore(QOpenGLContext *context, QObject *parent = 0); + ~GLStateStore(); + + void storeGLState(); + void restoreGLState(); + void initGLDefaultState(); + +#ifdef VERBOSE_STATE_STORE + void printCurrentState(bool in); + EnumToStringMap *m_map; +#endif + + GLint m_scissorBox[4]; + GLboolean m_isScissorTestEnabled; + +#if !QT_CONFIG(opengles2) + GLint m_drawFramebuffer; + GLint m_readFramebuffer; + GLint m_renderbuffer; +#endif + GLfloat m_clearColor[4]; + GLfloat m_clearDepth; + GLboolean m_isBlendingEnabled; + GLboolean m_isDepthTestEnabled; + GLint m_depthFunc; + GLboolean m_isDepthWriteEnabled; + GLint m_currentProgram; + GLint m_maxVertexAttribs; + QScopedArrayPointer<GLint> m_vertexAttribArrayEnabledStates; + QScopedArrayPointer<GLint> m_vertexAttribArrayBoundBuffers; + QScopedArrayPointer<GLint> m_vertexAttribArraySizes; + QScopedArrayPointer<GLint> m_vertexAttribArrayTypes; + QScopedArrayPointer<GLint> m_vertexAttribArrayNormalized; + QScopedArrayPointer<GLint> m_vertexAttribArrayStrides; + QScopedArrayPointer<void *> m_vertexAttribArrayOffsets; + + GLint m_activeTexture; + GLint m_texBinding2D; + GLint m_frontFace; + GLboolean m_isCullFaceEnabled; + GLint m_cullFaceMode; + GLint m_blendEquationRGB; + GLint m_blendEquationAlpha; + GLint m_blendDestAlpha; + GLint m_blendDestRGB; + GLint m_blendSrcAlpha; + GLint m_blendSrcRGB; + GLint m_boundArrayBuffer; + GLint m_boundElementArrayBuffer; + GLboolean m_polygonOffsetFillEnabled; + GLfloat m_polygonOffsetFactor; + GLfloat m_polygonOffsetUnits; +}; + +#endif |