diff options
author | Tomi Korpipää <tomi.korpipaa@digia.com> | 2013-08-16 07:14:35 +0300 |
---|---|---|
committer | Tomi Korpipää <tomi.korpipaa@digia.com> | 2013-08-16 07:14:35 +0300 |
commit | 6c0334496d50aaf4e11dcda7ed642fac565d6145 (patch) | |
tree | aa6e7aeef9b00ba46910c30bd85fedbc53df39a0 | |
parent | 3288b23502c195d03e097cb372a22f3a1ac4ba87 (diff) | |
parent | 29f6433606cebe3299e9915ae32bae7dfaed2770 (diff) |
Merge remote-tracking branch 'origin/develop'
Change-Id: I544af544ecd946cdcccfe9c17d03e47f8d0c1151
260 files changed, 25732 insertions, 11454 deletions
@@ -244,3 +244,8 @@ work .obj/ +mkspecs/ +examples/spectrum/*.dll* +examples/spectrum/*.exe* +examples/spectrum/*.lib +examples/spectrum/*.exp
\ No newline at end of file diff --git a/examples/barchart/barchart.pro b/examples/barchart/barchart.pro index 381b3402..12b296c5 100644 --- a/examples/barchart/barchart.pro +++ b/examples/barchart/barchart.pro @@ -3,6 +3,7 @@ } SOURCES += main.cpp -QT += datavis3d INSTALLS += target + +QT += widgets diff --git a/examples/barchart/doc/src/barchart.qdoc b/examples/barchart/doc/src/barchart.qdoc index 498388bb..6c2c8760 100644 --- a/examples/barchart/doc/src/barchart.qdoc +++ b/examples/barchart/doc/src/barchart.qdoc @@ -1,27 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of the QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/barchart/main.cpp b/examples/barchart/main.cpp index 6887bb0b..77230b5d 100644 --- a/examples/barchart/main.cpp +++ b/examples/barchart/main.cpp @@ -1,47 +1,29 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of the QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ -#include "q3dbars.h" -#include "qdataset.h" +#include <QtDataVis3D/q3dbars.h> +#include <QtDataVis3D/qcategoryaxis.h> +#include <QtDataVis3D/qitemmodelbardataproxy.h> +#include <QtDataVis3D/qvalueaxis.h> -#include <QGuiApplication> +#include <QApplication> +#include <QVBoxLayout> +#include <QTableWidget> #include <QScreen> #include <QTimer> #include <QFont> @@ -57,11 +39,11 @@ using namespace QtDataVis3D; class ChartDataGenerator : public QObject { public: - explicit ChartDataGenerator(Q3DBars *barchart); + explicit ChartDataGenerator(Q3DBars *barchart, QTableWidget *tableWidget); ~ChartDataGenerator(); - void addDataSet(); - void addBars(); + void setupModel(); + void addRow(); void changeStyle(); void changePresetCamera(); void changeTheme(); @@ -75,16 +57,18 @@ private: QTimer *m_themeTimer; int m_columnCount; int m_rowCount; + QTableWidget *m_tableWidget; // not owned }; -ChartDataGenerator::ChartDataGenerator(Q3DBars *barchart) +ChartDataGenerator::ChartDataGenerator(Q3DBars *barchart, QTableWidget *tableWidget) : m_chart(barchart), m_dataTimer(0), m_styleTimer(0), m_presetTimer(0), m_themeTimer(0), - m_columnCount(21), - m_rowCount(21) + m_columnCount(100), + m_rowCount(50), + m_tableWidget(tableWidget) { // Set up bar specifications; make the bars as wide as they are deep, // and add a small space between the bars @@ -92,20 +76,21 @@ ChartDataGenerator::ChartDataGenerator(Q3DBars *barchart) #ifndef USE_STATIC_DATA // Set up sample space; make it as deep as it's wide - m_chart->setupSampleSpace(m_columnCount, m_rowCount); + m_chart->setupSampleSpace(m_rowCount, m_columnCount); + m_tableWidget->setColumnCount(m_columnCount); #endif // Set bar type to smooth bar #ifndef CYCLE_THROUGH_STYLES - m_chart->setBarType(Pyramids, false); + m_chart->setBarType(QDataVis::Pyramids, false); #endif #ifndef USE_STATIC_DATA // Set selection mode to full - m_chart->setSelectionMode(ModeBarRowAndColumn); + m_chart->setSelectionMode(QDataVis::ModeItemRowAndColumn); #else // Set selection mode to zoom row - m_chart->setSelectionMode(ModeZoomRow); + m_chart->setSelectionMode(QDataVis::ModeZoomRow); m_chart->setFont(QFont("Courier", 25)); #endif @@ -113,11 +98,11 @@ ChartDataGenerator::ChartDataGenerator(Q3DBars *barchart) // Set bar colors m_chart->setBarColor(QColor(Qt::gray), QColor(Qt::red), QColor(Qt::darkBlue)); #else - m_chart->setLabelTransparency(TransparencyNone); + m_chart->setLabelTransparency(QDataVis::TransparencyNone); #endif // Set preset camera position - m_chart->setCameraPreset(PresetFront); + m_chart->setCameraPreset(QDataVis::PresetFront); } ChartDataGenerator::~ChartDataGenerator() @@ -146,11 +131,11 @@ void ChartDataGenerator::start() #ifndef USE_STATIC_DATA m_dataTimer = new QTimer(); m_dataTimer->setTimerType(Qt::CoarseTimer); - m_dataTimer->setInterval(100); - QObject::connect(m_dataTimer, &QTimer::timeout, this, &ChartDataGenerator::addBars); - m_dataTimer->start(100); + m_dataTimer->setInterval(20); + QObject::connect(m_dataTimer, &QTimer::timeout, this, &ChartDataGenerator::addRow); + m_dataTimer->start(20); #else - addDataSet(); + setupModel(); #endif #ifdef CYCLE_THROUGH_STYLES @@ -182,84 +167,53 @@ void ChartDataGenerator::start() #endif } -void ChartDataGenerator::addDataSet() +void ChartDataGenerator::setupModel() { -#if 0 - // Prepare data to be visualized - // Use float vector adder - QVector< QVector<float> > data; - QVector<float> row; - // TODO: Keep here for testing - for (int j = 0; j < m_rowCount; j++) { - for (int i = 0; i < m_columnCount; i++) { - row.prepend(((float)i / (float)m_columnCount) * 100 + (float)(rand() % 30)); - //row.append(1.0f); - } - data.append(row); - row.clear(); - } - // Set up sample space based on inserted data - m_chart->setupSampleSpace(m_columnCount, m_rowCount); - // Add data to chart - m_chart->addDataSet(data); -#else - // Prepare data to be visualized - // Use QDataSet adder - - // Set window title - m_chart->setWindowTitle(QStringLiteral("Hours playing banjo")); - // Set up row and column names - QVector<QString> days; + QStringList days; days << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday" << "Saturday" << "Sunday"; - QVector<QString> weeks; + QStringList weeks; weeks << "week 1" << "week 2" << "week 3" << "week 4" << "week 5"; // Set up data Mon Tue Wed Thu Fri Sat Sun - float hours[5][7] = {{2.0f, 1.0f, 3.0f, 0.2f, 1.0f, 5.0f, 7.0f}, // week 1 + float hours[5][7] = {{2.0f, 1.0f, 3.0f, 0.2f, 1.0f, 5.0f, 10.0f}, // week 1 {0.5f, 1.0f, 3.0f, 1.0f, 2.0f, 2.0f, 3.0f}, // week 2 {1.0f, 1.0f, 2.0f, 1.0f, 4.0f, 4.0f, 4.0f}, // week 3 - {0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 2.0f, 0.3f}, // week 4 + {0.0f, 1.0f, 0.0f, 0.0f, 2.0f, 2.0f, 0.3f}, // week 4 {3.0f, 3.0f, 6.0f, 2.0f, 2.0f, 1.0f, 1.0f}}; // week 5 - // Set tick count and step, we want a line every hour -> 7 ticks, step 1 hour - m_chart->setTickCount(7, 1.0f); - - // Create data set - QDataSet *dataSet = new QDataSet(); - // Add labels - dataSet->setLabels("Week of year", "Day of week", "Hours playing banjo", weeks, days); + m_chart->rowAxis()->setTitle("Week of year"); + m_chart->columnAxis()->setTitle("Day of week"); + m_chart->valueAxis()->setTitle("Hours playing banjo"); + m_chart->valueAxis()->setSegmentCount(5); + m_chart->rowAxis()->setCategoryLabels(weeks); + m_chart->columnAxis()->setCategoryLabels(days); + + m_tableWidget->setRowCount(5); + m_tableWidget->setColumnCount(7); + m_tableWidget->setHorizontalHeaderLabels(days); + m_tableWidget->setVerticalHeaderLabels(weeks); - // Create data rows - QDataRow *dataRow; for (int week = 0; week < weeks.size(); week++) { - dataRow = new QDataRow(weeks.at(week)); - // Create data items for (int day = 0; day < days.size(); day++) { - // Add data to rows - dataRow->addItem(new QDataItem(hours[week][day], "h"));//, " + days.at(day))); + QModelIndex index = m_tableWidget->model()->index(week, day); + m_tableWidget->model()->setData(index, hours[week][day]); } - // Add row to set - dataSet->addRow(dataRow); - // Get next pointer - dataRow++; } // Set up sample space based on prepared data - m_chart->setupSampleSpace(days.size(), weeks.size()); - - // Add data to chart - m_chart->addDataSet(dataSet); -#endif + m_chart->setupSampleSpace(weeks.size(), days.size()); } -void ChartDataGenerator::addBars() +void ChartDataGenerator::addRow() { - QVector<float> data; - for (int i = 0; i < m_columnCount; i++) - data.append(((float)i / (float)m_columnCount) / 2.0f + (float)(rand() % 30) / 100); - m_chart->addDataRow(data); + m_tableWidget->model()->insertRow(0); + for (int i = 0; i < m_columnCount; i++) { + QModelIndex index = m_tableWidget->model()->index(0, i); + m_tableWidget->model()->setData(index, + ((qreal)i / (qreal)m_columnCount) / 2.0 + (qreal)(rand() % 30) / 100.0); + } } void ChartDataGenerator::changeStyle() @@ -267,28 +221,28 @@ void ChartDataGenerator::changeStyle() static int model = 0; switch (model) { case 0: - m_chart->setBarType(Cylinders, false); + m_chart->setBarType(QDataVis::Cylinders, false); break; case 1: - m_chart->setBarType(Cylinders, true); + m_chart->setBarType(QDataVis::Cylinders, true); break; case 2: - m_chart->setBarType(Cones, false); + m_chart->setBarType(QDataVis::Cones, false); break; case 3: - m_chart->setBarType(Cones, true); + m_chart->setBarType(QDataVis::Cones, true); break; case 4: - m_chart->setBarType(Bars, false); + m_chart->setBarType(QDataVis::Bars, false); break; case 5: - m_chart->setBarType(Bars, true); + m_chart->setBarType(QDataVis::Bars, true); break; case 6: - m_chart->setBarType(Pyramids, false); + m_chart->setBarType(QDataVis::Pyramids, false); break; case 7: - m_chart->setBarType(Pyramids, true); + m_chart->setBarType(QDataVis::Pyramids, true); break; } model++; @@ -300,9 +254,9 @@ void ChartDataGenerator::changePresetCamera() { static int preset = 0; - m_chart->setCameraPreset((CameraPreset)preset); + m_chart->setCameraPreset((QDataVis::CameraPreset)preset); - if (++preset > (int)PresetDirectlyAboveCCW45) + if (++preset > (int)QDataVis::PresetDirectlyAboveCCW45) preset = 0; } @@ -310,24 +264,45 @@ void ChartDataGenerator::changeTheme() { static int theme = 0; - m_chart->setTheme((ColorTheme)theme); + m_chart->setTheme((QDataVis::ColorTheme)theme); - if (++theme > (int)ThemeLight) + if (++theme > (int)QDataVis::ThemeLight) theme = 0; } int main(int argc, char **argv) { - QGuiApplication app(argc, argv); + QApplication app(argc, argv); + + QWidget *widget = new QWidget; + QVBoxLayout *layout = new QVBoxLayout(widget); + + Q3DBars *chart = new Q3DBars(); + QSize screenSize = chart->screen()->size(); - Q3DBars barchart; - QSize screenSize = barchart.screen()->size(); - barchart.resize(screenSize.width() / 1.5, screenSize.height() / 1.5); - barchart.setPosition(screenSize.width() / 6, screenSize.height() / 6); - barchart.show(); + QWidget *container = QWidget::createWindowContainer(chart); + container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 2)); + container->setMaximumSize(screenSize); + container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + container->setFocusPolicy(Qt::StrongFocus); - ChartDataGenerator *generator = new ChartDataGenerator(&barchart); + widget->setWindowTitle(QStringLiteral("Hours playing banjo")); + + QTableWidget *tableWidget = new QTableWidget(0, 0, widget); + + layout->addWidget(tableWidget); + layout->addWidget(container, 1); + + // We don't need to initialize the mapping object in any way, as it defaults + // to row/column support and uses the Qt::DisplayRole role for value role by default. + QItemModelBarDataMapping mapping; + QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(tableWidget->model(), &mapping); + chart->setDataProxy(proxy); + + ChartDataGenerator *generator = new ChartDataGenerator(chart, tableWidget); generator->start(); + widget->show(); + return app.exec(); } diff --git a/examples/examples.pri b/examples/examples.pri index f20862e7..48d2f29a 100644 --- a/examples/examples.pri +++ b/examples/examples.pri @@ -11,6 +11,10 @@ win32 { DESTDIR = $$OUT_PWD } +LIBS += -L$$OUT_PWD/../../lib + +QT += datavis3d + contains(TARGET, qml.*) { uri = com.digia.QtDataVis3D lib_name = datavis3dqml2 @@ -46,7 +50,8 @@ contains(TARGET, qml.*) { src_lib = lib$${lib_name}.dylib } } else { - src_lib = $${lib_name}.so + # linux, android + src_lib = lib$${lib_name}.so } } copy_lib.target = $$make_qmldir_path/$$src_lib @@ -54,14 +59,12 @@ contains(TARGET, qml.*) { copy_lib.commands = $(COPY_FILE) \"$$replace(copy_lib.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_lib.target, /, $$QMAKE_DIR_SEP)\" QMAKE_EXTRA_TARGETS += copy_lib PRE_TARGETDEPS += $$copy_lib.target -} -#android { -# contains(TARGET, qml.*) { -# charts_qmldir.files = $$CHART_BUILD_QML_PLUGIN_DIR/qmldir -# charts_qmldir.path = /assets/imports/QtCommercial/Chart -# charts_qmlplugin.files = $$CHART_BUILD_QML_PLUGIN_DIR/libqtcommercialchartqml.so -# charts_qmlplugin.path = /libs/$$ANDROID_TARGET_ARCH -# INSTALLS += charts_qmldir charts_qmlplugin -# } -#} + android { + android_qmldir.files = $$copy_qmldir_examples.target + android_qmldir.path = /assets/imports/$$make_qmldir_target + android_qmlplugin.files = $$copy_lib.target + android_qmlplugin.path = $$target.path + INSTALLS += android_qmldir android_qmlplugin + } +} diff --git a/examples/examples.pro b/examples/examples.pro index dd772368..4db7ed2f 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -3,6 +3,10 @@ SUBDIRS += barchart \ rainfall \ widget \ mapdata \ - qmlbarchart + qmlbarchart \ + #qmlmaps \ + qmlscatter \ + surfacechart \ + scatterchart -qtHaveModule(multimedia): SUBDIRS += spectrum +qtHaveModule(multimedia):!android: SUBDIRS += spectrum diff --git a/examples/mapdata/doc/src/mapdata.qdoc b/examples/mapdata/doc/src/mapdata.qdoc index be424509..3014cadb 100644 --- a/examples/mapdata/doc/src/mapdata.qdoc +++ b/examples/mapdata/doc/src/mapdata.qdoc @@ -1,27 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of the QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/mapdata/main.cpp b/examples/mapdata/main.cpp index 976b2165..d176bd55 100644 --- a/examples/mapdata/main.cpp +++ b/examples/mapdata/main.cpp @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -199,6 +177,8 @@ int main(int argc, char **argv) QObject::connect(shadowQuality, SIGNAL(currentIndexChanged(int)), modifier, SLOT(changeShadowQuality(int))); + QObject::connect(modifier, &MapsModifier::shadowQuality, shadowQuality, + &QComboBox::setCurrentIndex); QObject::connect(fontList, &QFontComboBox::currentFontChanged, modifier, &MapsModifier::changeFont); diff --git a/examples/mapdata/mapdata.cpp b/examples/mapdata/mapdata.cpp index 8f4aee7c..6f0157da 100644 --- a/examples/mapdata/mapdata.cpp +++ b/examples/mapdata/mapdata.cpp @@ -1,44 +1,23 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #include "mapdata.h" +#include <QtDataVis3D/qmapdataproxy.h> #include <QImage> #include <QFile> @@ -64,6 +43,8 @@ MapsModifier::MapsModifier(Q3DMaps *maps) m_chart->setBarSpecs(m_barSpecs, Q3DMaps::AdjustAll); m_chart->setMeshFileName(QStringLiteral(":/meshes/weirdthing")); #endif + QMapDataProxy *proxy = new QMapDataProxy; + m_chart->setDataProxy(proxy); } MapsModifier::~MapsModifier() @@ -78,132 +59,156 @@ void MapsModifier::start() void MapsModifier::addData() { - QDataItem *item; - item = new QDataItem(); + QMapDataArray *dataArray = new QMapDataArray; + QMapDataItem *item; + item = new QMapDataItem(); item->setValue(191050); - item->setLabel("Oulu", true); - item->setPosition(QPoint(963, 1604)); - m_chart->addDataItem(item); + item->setLabel("Oulu"); + item->setMapPosition(QPointF(963, 1604)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(22274); - item->setLabel("Kemi", true); - item->setPosition(QPoint(857, 1383)); - m_chart->addDataItem(item); + item->setLabel("Kemi"); + item->setMapPosition(QPointF(857, 1383)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(60887); - item->setLabel("Rovaniemi", true); - item->setPosition(QPoint(1061, 1119)); - m_chart->addDataItem(item); + item->setLabel("Rovaniemi"); + item->setMapPosition(QPointF(1061, 1119)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(16176); - item->setLabel("Kuusamo", true); - item->setPosition(QPoint(1459, 1284)); - m_chart->addDataItem(item); + item->setLabel("Kuusamo"); + item->setMapPosition(QPointF(1459, 1284)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(3998); - item->setLabel("Ivalo", true); - item->setPosition(QPoint(1239, 474)); - m_chart->addDataItem(item); + item->setLabel("Ivalo"); + item->setMapPosition(QPointF(1239, 474)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(37978); - item->setLabel("Kajaani", true); - item->setPosition(QPoint(1285, 1859)); - m_chart->addDataItem(item); + item->setLabel("Kajaani"); + item->setMapPosition(QPointF(1285, 1859)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(46809); - item->setLabel("Kokkola", true); - item->setPosition(QPoint(580, 1973)); - m_chart->addDataItem(item); + item->setLabel("Kokkola"); + item->setMapPosition(QPointF(580, 1973)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(105236); - item->setLabel("Kuopio", true); - item->setPosition(QPoint(1292, 2283)); - m_chart->addDataItem(item); + item->setLabel("Kuopio"); + item->setMapPosition(QPointF(1292, 2283)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(133557); - item->setLabel("Jyväskylä", true); - item->setPosition(QPoint(991, 2496)); - m_chart->addDataItem(item); + item->setLabel("Jyväskylä"); + item->setMapPosition(QPointF(991, 2496)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(65771); - item->setLabel("Vaasa", true); - item->setPosition(QPoint(441, 2184)); - m_chart->addDataItem(item); + item->setLabel("Vaasa"); + item->setMapPosition(QPointF(441, 2184)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(217603); - item->setLabel("Tampere", true); - item->setPosition(QPoint(686, 2656)); - m_chart->addDataItem(item); + item->setLabel("Tampere"); + item->setMapPosition(QPointF(686, 2656)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(180350); - item->setLabel("Turku", true); - item->setPosition(QPoint(430, 3046)); - m_chart->addDataItem(item); + item->setLabel("Turku"); + item->setMapPosition(QPointF(430, 3046)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(72400); - item->setLabel("Lappeenranta", true); - item->setPosition(QPoint(1365, 2852)); - m_chart->addDataItem(item); + item->setLabel("Lappeenranta"); + item->setMapPosition(QPoint(1365, 2852)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(14754); - item->setLabel("Tammisaari", true); - item->setPosition(QPoint(605, 3215)); - m_chart->addDataItem(item); + item->setLabel("Tammisaari"); + item->setMapPosition(QPointF(605, 3215)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(1879); - item->setLabel("Enontekiö", true); - item->setPosition(QPoint(752, 556)); - m_chart->addDataItem(item); + item->setLabel("Enontekiö"); + item->setMapPosition(QPointF(752, 556)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(36624); - item->setLabel("Savonlinna", true); - item->setPosition(QPoint(1445, 2586)); - m_chart->addDataItem(item); + item->setLabel("Savonlinna"); + item->setMapPosition(QPointF(1445, 2586)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(605022); - item->setLabel("Helsinki", true); - item->setPosition(QPoint(822, 3130)); - m_chart->addDataItem(item); + item->setLabel("Helsinki"); + item->setMapPosition(QPointF(822, 3130)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(54887); - item->setLabel("Kotka", true); - item->setPosition(QPoint(1162, 3051)); - m_chart->addDataItem(item); + item->setLabel("Kotka"); + item->setMapPosition(QPointF(1162, 3051)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(11372); - item->setLabel("Maarianhamina", true); - item->setPosition(QPoint(56, 3101)); - m_chart->addDataItem(item); + item->setLabel("Maarianhamina"); + item->setMapPosition(QPointF(56, 3101)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(9266); - item->setLabel("Hanko", true); - item->setPosition(QPoint(527, 3228)); - m_chart->addDataItem(item); + item->setLabel("Hanko"); + item->setMapPosition(QPointF(527, 3228)); + dataArray->append(*item); + delete item; - item = new QDataItem(); + item = new QMapDataItem(); item->setValue(1287); - item->setLabel("Utsjoki", true); - item->setPosition(QPoint(1180, 72)); - m_chart->addDataItem(item); + item->setLabel("Utsjoki"); + item->setMapPosition(QPointF(1180, 72)); + dataArray->append(*item); + delete item; + + static_cast<QMapDataProxy *>(m_chart->dataProxy())->resetArray(dataArray); } void MapsModifier::changeStyle() @@ -211,40 +216,40 @@ void MapsModifier::changeStyle() static int model = 0; switch (model) { case 0: - m_chart->setBarType(Cylinders, false); + m_chart->setBarType(QDataVis::Cylinders, false); break; case 1: - m_chart->setBarType(Cylinders, true); + m_chart->setBarType(QDataVis::Cylinders, true); break; case 2: - m_chart->setBarType(Cones, false); + m_chart->setBarType(QDataVis::Cones, false); break; case 3: - m_chart->setBarType(Cones, true); + m_chart->setBarType(QDataVis::Cones, true); break; case 4: - m_chart->setBarType(Bars, false); + m_chart->setBarType(QDataVis::Bars, false); break; case 5: - m_chart->setBarType(Bars, true); + m_chart->setBarType(QDataVis::Bars, true); break; case 6: - m_chart->setBarType(Pyramids, false); + m_chart->setBarType(QDataVis::Pyramids, false); break; case 7: - m_chart->setBarType(Pyramids, true); + m_chart->setBarType(QDataVis::Pyramids, true); break; case 8: - m_chart->setBarType(BevelBars, false); + m_chart->setBarType(QDataVis::BevelBars, false); break; case 9: - m_chart->setBarType(BevelBars, true); + m_chart->setBarType(QDataVis::BevelBars, true); break; case 10: - m_chart->setBarType(Spheres, false); + m_chart->setBarType(QDataVis::Spheres, false); break; case 11: - m_chart->setBarType(Spheres, true); + m_chart->setBarType(QDataVis::Spheres, true); break; } model++; @@ -254,32 +259,32 @@ void MapsModifier::changeStyle() void MapsModifier::changePresetCamera() { - static int preset = PresetFrontLow; + static int preset = QDataVis::PresetFrontLow; - m_chart->setCameraPreset((CameraPreset)preset); + m_chart->setCameraPreset((QDataVis::CameraPreset)preset); - if (++preset > PresetDirectlyAboveCCW45) - preset = PresetFrontLow; + if (++preset > QDataVis::PresetDirectlyAboveCCW45) + preset = QDataVis::PresetFrontLow; } void MapsModifier::changeTheme() { - static int theme = ThemeSystem; + static int theme = QDataVis::ThemeSystem; - m_chart->setTheme((ColorTheme)theme); + m_chart->setTheme((QDataVis::ColorTheme)theme); - if (++theme > ThemeLight) - theme = ThemeSystem; + if (++theme > QDataVis::ThemeLight) + theme = QDataVis::ThemeSystem; } void MapsModifier::changeTransparency() { - static int transparency = TransparencyNone; + static int transparency = QDataVis::TransparencyNone; - m_chart->setLabelTransparency((LabelTransparency)transparency); + m_chart->setLabelTransparency((QDataVis::LabelTransparency)transparency); - if (++transparency > TransparencyNoBackground) - transparency = TransparencyFromTheme; + if (++transparency > QDataVis::TransparencyNoBackground) + transparency = QDataVis::TransparencyFromTheme; } void MapsModifier::changeValueDimension(int dimension) @@ -303,19 +308,34 @@ void MapsModifier::changeFontSize(int fontsize) void MapsModifier::changeShadowQuality(int quality) { - ShadowQuality sq = ShadowNone; + QDataVis::ShadowQuality sq = QDataVis::ShadowNone; switch (quality) { case 1: - sq = ShadowLow; + sq = QDataVis::ShadowLow; break; case 2: - sq = ShadowMedium; + sq = QDataVis::ShadowMedium; break; case 3: - sq = ShadowHigh; + sq = QDataVis::ShadowHigh; break; } - m_chart->setShadowQuality(sq); + QDataVis::ShadowQuality realquality = m_chart->setShadowQuality(sq); + // Check if it setting quality was successful + if (realquality != sq) { + switch (realquality) { + case QDataVis::ShadowLow: + quality = 1; + break; + case QDataVis::ShadowMedium: + quality = 2; + break; + case QDataVis::ShadowHigh: + quality = 3; + break; + } + emit shadowQuality(quality); + } } //void MapsModifier::setGridEnabled(int enabled) diff --git a/examples/mapdata/mapdata.h b/examples/mapdata/mapdata.h index 3b3c7219..8aed69fe 100644 --- a/examples/mapdata/mapdata.h +++ b/examples/mapdata/mapdata.h @@ -1,48 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #ifndef CHARTMODIFIER_H #define CHARTMODIFIER_H -#include "q3dmaps.h" -#include "qdataset.h" +#include <QtDataVis3D/q3dmaps.h> #include <QFont> #include <QDebug> @@ -75,6 +52,9 @@ public slots: void changeValueDimension(int dimension); void changeShadowQuality(int quality); +signals: + void shadowQuality(int quality); + private: Q3DMaps *m_chart; QRect m_imageRect; diff --git a/examples/mapdata/mapdata.pro b/examples/mapdata/mapdata.pro index 7ed5984e..091fdc7c 100644 --- a/examples/mapdata/mapdata.pro +++ b/examples/mapdata/mapdata.pro @@ -5,7 +5,7 @@ SOURCES += main.cpp mapdata.cpp HEADERS += mapdata.h -QT += datavis3d widgets +QT += widgets INSTALLS += target diff --git a/examples/qmlbarchart/doc/src/qmlbarchart.qdoc b/examples/qmlbarchart/doc/src/qmlbarchart.qdoc index 42bb05aa..becc5d8b 100644 --- a/examples/qmlbarchart/doc/src/qmlbarchart.qdoc +++ b/examples/qmlbarchart/doc/src/qmlbarchart.qdoc @@ -1,27 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of the QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/qmlbarchart/main.cpp b/examples/qmlbarchart/main.cpp index d813443e..b58e66f8 100644 --- a/examples/qmlbarchart/main.cpp +++ b/examples/qmlbarchart/main.cpp @@ -6,26 +6,27 @@ ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. ** ** If you have questions regarding the use of this file, please use ** contact form at http://qt.digia.com -** $QT_END_LICENSE$ ** ****************************************************************************/ #include <QtGui/QGuiApplication> #include "qtquick2applicationviewer.h" +#ifdef Q_OS_ANDROID +#include <QDir> +#include <QQmlEngine> +#endif #include <QDebug> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); - qDebug() << "Hello world."; QtQuick2ApplicationViewer viewer; #ifdef Q_OS_ANDROID @@ -36,7 +37,7 @@ int main(int argc, char *argv[]) viewer.addImportPath(QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), QString::fromLatin1("qml"))); #endif - viewer.setMainQmlFile(QStringLiteral("qml/qmlbarchart/main.qml")); + viewer.setSource(QUrl("qrc:/qml/main.qml")); viewer.setResizeMode(QQuickView::SizeRootObjectToView); viewer.show(); diff --git a/examples/qmlbarchart/qml/qmlbarchart/main.qml b/examples/qmlbarchart/qml/qmlbarchart/main.qml index 990c78e6..f10f98b9 100644 --- a/examples/qmlbarchart/qml/qmlbarchart/main.qml +++ b/examples/qmlbarchart/qml/qmlbarchart/main.qml @@ -6,116 +6,200 @@ ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. ** ** If you have questions regarding the use of this file, please use ** contact form at http://qt.digia.com -** $QT_END_LICENSE$ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 import QtQuick.Window 2.1 +import QtQuick.Controls 1.0 import com.digia.QtDataVis3D 1.0 Item { id: mainview - //title: "My MainWindow" - width: 640 - height: 480 + width: 800 + height: 600 visible: true - Bars3D { - id: testchart - width: mainview.width - height: mainview.height + Item { + id: dataView + width: parent.width - tableView.width + height: parent.height + anchors.right: parent.right; - DataItem { - id: testitem - label: "Test" - value: 10 + BarDataMapping { + id: valueMapping + rowRole: "year" + columnRole: "month" + valueRole: "expenses" + rowCategories: ["2000", "2001", "2002", "2003", "2004"] + columnCategories: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] } - DataItem { - id: testitem2 - label: "Test2" - value: -10 - } - DataItem { - id: testitem3 - label: "Test3" - value: 5 + + ListModel { + id: dataModel + ListElement{ year: "2000"; month: "Jan"; expenses: "3"; income: "8" } + ListElement{ year: "2000"; month: "Feb"; expenses: "8"; income: "14" } + ListElement{ year: "2000"; month: "Mar"; expenses: "10"; income: "20" } + ListElement{ year: "2000"; month: "Apr"; expenses: "12"; income: "24" } + ListElement{ year: "2000"; month: "May"; expenses: "10"; income: "19" } + ListElement{ year: "2000"; month: "Jun"; expenses: "5"; income: "8" } + ListElement{ year: "2000"; month: "Jul"; expenses: "1"; income: "4" } + ListElement{ year: "2000"; month: "Aug"; expenses: "7"; income: "12" } + ListElement{ year: "2000"; month: "Sep"; expenses: "4"; income: "16" } + ListElement{ year: "2000"; month: "Oct"; expenses: "22"; income: "33" } + ListElement{ year: "2000"; month: "Nov"; expenses: "16"; income: "25" } + ListElement{ year: "2000"; month: "Dec"; expenses: "2"; income: "7" } + + ListElement{ year: "2001"; month: "Jan"; expenses: "4"; income: "5" } + ListElement{ year: "2001"; month: "Feb"; expenses: "4"; income: "7" } + ListElement{ year: "2001"; month: "Mar"; expenses: "11"; income: "14" } + ListElement{ year: "2001"; month: "Apr"; expenses: "16"; income: "22" } + ListElement{ year: "2001"; month: "May"; expenses: "3"; income: "5" } + ListElement{ year: "2001"; month: "Jun"; expenses: "4"; income: "8" } + ListElement{ year: "2001"; month: "Jul"; expenses: "7"; income: "9" } + ListElement{ year: "2001"; month: "Aug"; expenses: "9"; income: "13" } + ListElement{ year: "2001"; month: "Sep"; expenses: "1"; income: "6" } + ListElement{ year: "2001"; month: "Oct"; expenses: "14"; income: "25" } + ListElement{ year: "2001"; month: "Nov"; expenses: "19"; income: "29" } + ListElement{ year: "2001"; month: "Dec"; expenses: "5"; income: "7" } + + ListElement{ year: "2002"; month: "Jan"; expenses: "14"; income: "22" } + ListElement{ year: "2002"; month: "Feb"; expenses: "5"; income: "7" } + ListElement{ year: "2002"; month: "Mar"; expenses: "1"; income: "9" } + ListElement{ year: "2002"; month: "Apr"; expenses: "1"; income: "12" } + ListElement{ year: "2002"; month: "May"; expenses: "5"; income: "9" } + ListElement{ year: "2002"; month: "Jun"; expenses: "5"; income: "8" } + ListElement{ year: "2002"; month: "Jul"; expenses: "3"; income: "7" } + ListElement{ year: "2002"; month: "Aug"; expenses: "1"; income: "5" } + ListElement{ year: "2002"; month: "Sep"; expenses: "2"; income: "4" } + ListElement{ year: "2002"; month: "Oct"; expenses: "10"; income: "13" } + ListElement{ year: "2002"; month: "Nov"; expenses: "12"; income: "17" } + ListElement{ year: "2002"; month: "Dec"; expenses: "6"; income: "9" } + + ListElement{ year: "2003"; month: "Jan"; expenses: "2"; income: "6" } + ListElement{ year: "2003"; month: "Feb"; expenses: "4"; income: "8" } + ListElement{ year: "2003"; month: "Mar"; expenses: "7"; income: "12" } + ListElement{ year: "2003"; month: "Apr"; expenses: "9"; income: "15" } + // rest of 2003 missing on purpose, as well as whole of 2004 } - DataItem { - id: testitem4 - label: "Test4" - value: -7 + CategoryAxis { + id: rowAxis + categoryLabels: ["2000", "2001", "2002", "2003", "2004"] } - DataItem { - id: testitem5 - label: "Test5" - value: 8 + CategoryAxis { + id: columnAxis + categoryLabels: ["January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"] } - DataItem { - id: testitem6 - label: "Test6" - value: 1 + ValueAxis { + id: valueAxis + min: 0 + max: 35 + labelFormat: "M\u20AC" } + Bars3D { + id: testchart + width: dataView.width + height: dataView.height + gridVisible: true + shadowQuality: Bars3D.ShadowNone + selectionMode: Bars3D.ModeItem + labelTransparency: Bars3D.TransparencyNone + rows: 5 + columns: 12 + mapping: valueMapping + barThickness: Qt.size(0.5, 1.0) + barSpacing: Qt.size(0.5, 0.5) + barSpacingRelative: false + barType: Bars3D.BevelBars + axisX: rowAxis + axisY: valueAxis + axisZ: columnAxis + } + } - DataRow { - id: testrow1 - function addData() { - testrow1.addItem(testitem); - testrow1.addItem(testitem2); - testrow1.addItem(testitem3); - testrow1.addItem(testitem4); - testrow1.addItem(testitem5); - testrow1.addItem(testitem6); - } + Component.onCompleted: { + testchart.data = dataModel + } + + TableView { + id: tableView + x: 0 + y: 0 + width: 270 + height: 500 + TableViewColumn{ role: "year" ; title: "Year" ; width: 40 } + TableViewColumn{ role: "month" ; title: "Month" ; width: 80 } + TableViewColumn{ role: "expenses" ; title: "Expenses" ; width: 70 } + TableViewColumn{ role: "income" ; title: "Income" ; width: 60 } + model: dataModel + } + + Rectangle { + id: shadowToggle + color: "#FFFFFF" + x: 0 + y: tableView.height + width: tableView.width + height: 50 + + TextArea { + id: shadowButtonText + text: "Toggle Shadows" + anchors.fill: parent + textColor: "#000000" } - //visible: true - //x: mainview.x + mainview.width - //y: mainview.y - - grid: false - shadowQuality: Bars3D.ShadowNone - selectionMode: Bars3D.ModeNone - labelTransparency: Bars3D.TransparencyNone - - function setUpBars3D() { - /*console.log(parent) - console.log(container.x) - console.log(container.y) - console.log(Window.x) - console.log(Window.y) - console.log(Screen.desktopAvailableHeight) - console.log(Screen.desktopAvailableWidth) - console.log(mainview.x) - console.log(mainview.y) - console.log(x) - console.log(y)*/ - testchart.setupSampleSpace(6, 1); - testchart.addDataRow(testrow1); + MouseArea { + anchors.fill: parent + onClicked: { + if (testchart.shadowQuality == Bars3D.ShadowNone) { + testchart.shadowQuality = Bars3D.ShadowLow; + shadowButtonText.textColor = "#FFFFFF"; + shadowToggle.color = "#000000"; + } else { + testchart.shadowQuality = Bars3D.ShadowNone; + shadowButtonText.textColor = "#000000"; + shadowToggle.color = "#FFFFFF"; + } + } } } + Rectangle { + id: mappingToggle + color: "#FFFFFF" + x: 0 + y: shadowToggle.height + shadowToggle.y + width: shadowToggle.width + height: 50 - MouseArea { - anchors.fill: parent - onClicked: { - Qt.quit(); + TextArea { + id: mappingButtonText + text: "Show Income" + anchors.fill: parent + textColor: "#000000" } - } - Component.onCompleted: { - // This allows us to flip the texture to be displayed correctly in scene graph - // TODO: Find a way to do it in code.. - //rotation.angle = 180 - testrow1.addData(); - testchart.setUpBars3D(); + MouseArea { + anchors.fill: parent + onClicked: { + if (valueMapping.valueRole == "expenses") { + valueMapping.valueRole = "income" + mappingButtonText.text = "Show Expenses" + } else { + valueMapping.valueRole = "expenses" + mappingButtonText.text = "Show Income" + } + } + } } } diff --git a/examples/qmlbarchart/qmlbarchart.pro b/examples/qmlbarchart/qmlbarchart.pro index 2c729f6b..ef609ef6 100644 --- a/examples/qmlbarchart/qmlbarchart.pro +++ b/examples/qmlbarchart/qmlbarchart.pro @@ -24,3 +24,6 @@ SOURCES += main.cpp # Please do not modify the following two lines. Required for deployment. include(qtquick2applicationviewer/qtquick2applicationviewer.pri) qtcAddDeployment() + +RESOURCES += \ + qmlbarchart.qrc diff --git a/examples/qmlbarchart/qmlbarchart.qrc b/examples/qmlbarchart/qmlbarchart.qrc new file mode 100644 index 00000000..b96401d5 --- /dev/null +++ b/examples/qmlbarchart/qmlbarchart.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/qml"> + <file alias="main.qml">qml/qmlbarchart/main.qml</file> + </qresource> +</RCC> diff --git a/examples/qmlmaps/doc/src/qmlmaps.qdoc b/examples/qmlmaps/doc/src/qmlmaps.qdoc new file mode 100644 index 00000000..f27dc126 --- /dev/null +++ b/examples/qmlmaps/doc/src/qmlmaps.qdoc @@ -0,0 +1,29 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +/*! + \example qmlmaps + \title Qt Quick 2 Maps Example + + The Qt Quick 2 maps example shows how to make a simple maps visualization using Q3DMaps using Qt + Quick 2. + + \image qmlmaps-example.png + + TODO +*/ diff --git a/examples/qmlmaps/floorplan.jpg b/examples/qmlmaps/floorplan.jpg Binary files differnew file mode 100644 index 00000000..578d8252 --- /dev/null +++ b/examples/qmlmaps/floorplan.jpg diff --git a/examples/qmlmaps/main.cpp b/examples/qmlmaps/main.cpp new file mode 100644 index 00000000..b58e66f8 --- /dev/null +++ b/examples/qmlmaps/main.cpp @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include <QtGui/QGuiApplication> +#include "qtquick2applicationviewer.h" +#ifdef Q_OS_ANDROID +#include <QDir> +#include <QQmlEngine> +#endif +#include <QDebug> + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QtQuick2ApplicationViewer viewer; +#ifdef Q_OS_ANDROID + viewer.addImportPath(QString::fromLatin1("assets:/qml")); + viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(), + QString::fromLatin1("lib"))); +#else + viewer.addImportPath(QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), + QString::fromLatin1("qml"))); +#endif + viewer.setSource(QUrl("qrc:/qml/main.qml")); + viewer.setResizeMode(QQuickView::SizeRootObjectToView); + viewer.show(); + + return app.exec(); +} diff --git a/examples/qmlmaps/qml/qmlmaps/main.qml b/examples/qmlmaps/qml/qmlmaps/main.qml new file mode 100644 index 00000000..9a8fa93b --- /dev/null +++ b/examples/qmlmaps/qml/qmlmaps/main.qml @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 +import com.digia.QtDataVis3D 1.0 + +Item { + id: mainview + width: 800 + height: 500 + visible: true + //title: "Noise levels from construction site" + + Item { + id: dataView + width: parent.width + height: parent.height - shadowToggle.height + anchors.bottom: parent.bottom + + Image { + id: testimage + source: "qrc:/images/floorplan.jpg" + visible: false + } + + MapDataMapping { + id: mapMapping + labelRole: "label" + valueRole: "value" + xPosRole: "xPos" + yPosRole: "yPos" + } + + ListModel { + id: dataModel + ListElement{ label: "dB"; value: 76; xPos: 95.0; yPos: 490.0 } + ListElement{ label: "dB"; value: 88; xPos: 185.0; yPos: 105.0 } + ListElement{ label: "dB"; value: 85; xPos: 700.0; yPos: 465.0 } + ListElement{ label: "dB"; value: 92; xPos: 505.0; yPos: 225.0 } + } + + Maps3D { + id: testmap + width: dataView.width + height: dataView.height + fontSize: 300.0 + mapping: mapMapping + + Component.onCompleted: { + console.log("testmap complete"); + console.log(testimage); + console.log(testimage.sourceSize); + setBarSpecs(Qt.vector3d(10.0, 10.0, 10.0)); + setAreaSpecs(Qt.rect(0, 0, testimage.sourceSize.width, testimage.sourceSize.height), + testimage); + //setImage(testimage); + setImage(":/images/floorplan.jpg"); + shadowQuality = Maps3D.ShadowNone + selectionMode = Maps3D.ModeBar + labelTransparency = Maps3D.TransparencyNoBackground//.TransparencyFromTheme + data = dataModel + } + } + } + + Component.onCompleted: { + console.log("mainview complete"); + } + + Rectangle { + id: shadowToggle + color: "#FFFFFF" + x: 0 + y: 0 + width: parent.width + height: 60 + + TextArea { + id: buttonText + text: "Toggle Shadows" + anchors.fill: parent + textColor: "#000000" + } + + MouseArea { + anchors.fill: parent + onClicked: { + if (testmap.shadowQuality === Maps3D.ShadowNone) { + testmap.shadowQuality = Maps3D.ShadowLow; + buttonText.textColor = "#999999"; + } else { + testmap.shadowQuality = Maps3D.ShadowNone; + buttonText.textColor = "#000000"; + } + } + } + } +} diff --git a/examples/qmlmaps/qmlmaps.desktop b/examples/qmlmaps/qmlmaps.desktop new file mode 100644 index 00000000..25959510 --- /dev/null +++ b/examples/qmlmaps/qmlmaps.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Type=Application +Terminal=false +Name=qmlmaps +Exec=/opt/qmlmaps/bin/qmlmaps +Icon=qmlmaps64 +X-Window-Icon= +X-HildonDesk-ShowInToolbar=true +X-Osso-Type=application/x-executable diff --git a/examples/qmlmaps/qmlmaps.pro b/examples/qmlmaps/qmlmaps.pro new file mode 100644 index 00000000..44963d48 --- /dev/null +++ b/examples/qmlmaps/qmlmaps.pro @@ -0,0 +1,29 @@ +!include( ../examples.pri ) { + error( "Couldn't find the examples.pri file!" ) +} + +# Add more folders to ship with the application, here +folder_01.source = qml/qmlmaps +folder_01.target = qml +DEPLOYMENTFOLDERS = folder_01 + +# Additional import path used to resolve QML modules in Creator's code model +QML_IMPORT_PATH = + +# If your application uses the Qt Mobility libraries, uncomment the following +# lines and add the respective components to the MOBILITY variable. +# CONFIG += mobility +# MOBILITY += + +# The .cpp file which was generated for your project. Feel free to hack it. +SOURCES += main.cpp + +# Installation path +# target.path = + +# Please do not modify the following two lines. Required for deployment. +include(qtquick2applicationviewer/qtquick2applicationviewer.pri) +qtcAddDeployment() + +RESOURCES += \ + qmlmaps.qrc diff --git a/examples/qmlmaps/qmlmaps.qrc b/examples/qmlmaps/qmlmaps.qrc new file mode 100644 index 00000000..81f1f83c --- /dev/null +++ b/examples/qmlmaps/qmlmaps.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/images"> + <file>floorplan.jpg</file> + </qresource> + <qresource prefix="/qml"> + <file alias="main.qml">qml/qmlmaps/main.qml</file> + </qresource> +</RCC> diff --git a/examples/qmlmaps/qmlmaps64.png b/examples/qmlmaps/qmlmaps64.png Binary files differnew file mode 100644 index 00000000..707d5c4e --- /dev/null +++ b/examples/qmlmaps/qmlmaps64.png diff --git a/examples/qmlmaps/qtquick2applicationviewer/qtquick2applicationviewer.cpp b/examples/qmlmaps/qtquick2applicationviewer/qtquick2applicationviewer.cpp new file mode 100644 index 00000000..10709d7a --- /dev/null +++ b/examples/qmlmaps/qtquick2applicationviewer/qtquick2applicationviewer.cpp @@ -0,0 +1,81 @@ +// checksum 0x4f6f version 0x90005 +/* + This file was generated by the Qt Quick 2 Application wizard of Qt Creator. + QtQuick2ApplicationViewer is a convenience class containing mobile device specific + code such as screen orientation handling. Also QML paths and debugging are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#include "qtquick2applicationviewer.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QDir> +#include <QtQml/QQmlEngine> + +class QtQuick2ApplicationViewerPrivate +{ + QString mainQmlFile; + friend class QtQuick2ApplicationViewer; + static QString adjustPath(const QString &path); +}; + +QString QtQuick2ApplicationViewerPrivate::adjustPath(const QString &path) +{ +#if defined(Q_OS_MAC) + if (!QDir::isAbsolutePath(path)) + return QString::fromLatin1("%1/../Resources/%2") + .arg(QCoreApplication::applicationDirPath(), path); +#elif defined(Q_OS_BLACKBERRY) + if (!QDir::isAbsolutePath(path)) + return QString::fromLatin1("app/native/%1").arg(path); +#elif !defined(Q_OS_ANDROID) + QString pathInInstallDir = + QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path); + if (QFileInfo(pathInInstallDir).exists()) + return pathInInstallDir; + pathInInstallDir = + QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), path); + if (QFileInfo(pathInInstallDir).exists()) + return pathInInstallDir; +#endif + return path; +} + +QtQuick2ApplicationViewer::QtQuick2ApplicationViewer(QWindow *parent) + : QQuickView(parent) + , d(new QtQuick2ApplicationViewerPrivate()) +{ + connect(engine(), SIGNAL(quit()), SLOT(close())); + setResizeMode(QQuickView::SizeRootObjectToView); +} + +QtQuick2ApplicationViewer::~QtQuick2ApplicationViewer() +{ + delete d; +} + +void QtQuick2ApplicationViewer::setMainQmlFile(const QString &file) +{ + d->mainQmlFile = QtQuick2ApplicationViewerPrivate::adjustPath(file); +#ifdef Q_OS_ANDROID + setSource(QUrl(QLatin1String("assets:/")+d->mainQmlFile)); +#else + setSource(QUrl::fromLocalFile(d->mainQmlFile)); +#endif +} + +void QtQuick2ApplicationViewer::addImportPath(const QString &path) +{ + engine()->addImportPath(QtQuick2ApplicationViewerPrivate::adjustPath(path)); +} + +void QtQuick2ApplicationViewer::showExpanded() +{ +#if defined(Q_WS_SIMULATOR) || defined(Q_OS_QNX) + showFullScreen(); +#else + show(); +#endif +} diff --git a/examples/qmlmaps/qtquick2applicationviewer/qtquick2applicationviewer.h b/examples/qmlmaps/qtquick2applicationviewer/qtquick2applicationviewer.h new file mode 100644 index 00000000..cf66f140 --- /dev/null +++ b/examples/qmlmaps/qtquick2applicationviewer/qtquick2applicationviewer.h @@ -0,0 +1,33 @@ +// checksum 0xfde6 version 0x90005 +/* + This file was generated by the Qt Quick 2 Application wizard of Qt Creator. + QtQuick2ApplicationViewer is a convenience class containing mobile device specific + code such as screen orientation handling. Also QML paths and debugging are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#ifndef QTQUICK2APPLICATIONVIEWER_H +#define QTQUICK2APPLICATIONVIEWER_H + +#include <QtQuick/QQuickView> + +class QtQuick2ApplicationViewer : public QQuickView +{ + Q_OBJECT + +public: + explicit QtQuick2ApplicationViewer(QWindow *parent = 0); + virtual ~QtQuick2ApplicationViewer(); + + void setMainQmlFile(const QString &file); + void addImportPath(const QString &path); + + void showExpanded(); + +private: + class QtQuick2ApplicationViewerPrivate *d; +}; + +#endif // QTQUICK2APPLICATIONVIEWER_H diff --git a/examples/qmlmaps/qtquick2applicationviewer/qtquick2applicationviewer.pri b/examples/qmlmaps/qtquick2applicationviewer/qtquick2applicationviewer.pri new file mode 100644 index 00000000..e5f7990f --- /dev/null +++ b/examples/qmlmaps/qtquick2applicationviewer/qtquick2applicationviewer.pri @@ -0,0 +1,180 @@ +# checksum 0x7b0d version 0x90005 +# This file was generated by the Qt Quick 2 Application wizard of Qt Creator. +# The code below adds the QtQuick2ApplicationViewer to the project and handles +# the activation of QML debugging. +# It is recommended not to modify this file, since newer versions of Qt Creator +# may offer an updated version of it. + +QT += qml quick + +SOURCES += $$PWD/qtquick2applicationviewer.cpp +HEADERS += $$PWD/qtquick2applicationviewer.h +INCLUDEPATH += $$PWD +# This file was generated by an application wizard of Qt Creator. +# The code below handles deployment to Android and Maemo, aswell as copying +# of the application data to shadow build directories on desktop. +# It is recommended not to modify this file, since newer versions of Qt Creator +# may offer an updated version of it. + +defineTest(qtcAddDeployment) { +for(deploymentfolder, DEPLOYMENTFOLDERS) { + item = item$${deploymentfolder} + greaterThan(QT_MAJOR_VERSION, 4) { + itemsources = $${item}.files + } else { + itemsources = $${item}.sources + } + $$itemsources = $$eval($${deploymentfolder}.source) + itempath = $${item}.path + $$itempath= $$eval($${deploymentfolder}.target) + export($$itemsources) + export($$itempath) + DEPLOYMENT += $$item +} + +MAINPROFILEPWD = $$PWD + +android-no-sdk { + for(deploymentfolder, DEPLOYMENTFOLDERS) { + item = item$${deploymentfolder} + itemfiles = $${item}.files + $$itemfiles = $$eval($${deploymentfolder}.source) + itempath = $${item}.path + $$itempath = /data/user/qt/$$eval($${deploymentfolder}.target) + export($$itemfiles) + export($$itempath) + INSTALLS += $$item + } + + target.path = /data/user/qt + + export(target.path) + INSTALLS += target +} else:android { + for(deploymentfolder, DEPLOYMENTFOLDERS) { + item = item$${deploymentfolder} + itemfiles = $${item}.files + $$itemfiles = $$eval($${deploymentfolder}.source) + itempath = $${item}.path + $$itempath = /assets/$$eval($${deploymentfolder}.target) + export($$itemfiles) + export($$itempath) + INSTALLS += $$item + } + + x86 { + target.path = /libs/x86 + } else: armeabi-v7a { + target.path = /libs/armeabi-v7a + } else { + target.path = /libs/armeabi + } + + export(target.path) + INSTALLS += target +} else:win32 { + copyCommand = + for(deploymentfolder, DEPLOYMENTFOLDERS) { + source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) + source = $$replace(source, /, \\) + sourcePathSegments = $$split(source, \\) + target = $$OUT_PWD/$$eval($${deploymentfolder}.target)/$$last(sourcePathSegments) + target = $$replace(target, /, \\) + target ~= s,\\\\\\.?\\\\,\\, + !isEqual(source,$$target) { + !isEmpty(copyCommand):copyCommand += && + isEqual(QMAKE_DIR_SEP, \\) { + copyCommand += $(COPY_DIR) \"$$source\" \"$$target\" + } else { + source = $$replace(source, \\\\, /) + target = $$OUT_PWD/$$eval($${deploymentfolder}.target) + target = $$replace(target, \\\\, /) + copyCommand += test -d \"$$target\" || mkdir -p \"$$target\" && cp -r \"$$source\" \"$$target\" + } + } + } + !isEmpty(copyCommand) { + copyCommand = @echo Copying application data... && $$copyCommand + copydeploymentfolders.commands = $$copyCommand + first.depends = $(first) copydeploymentfolders + export(first.depends) + export(copydeploymentfolders.commands) + QMAKE_EXTRA_TARGETS += first copydeploymentfolders + } +} else:unix { + maemo5 { + desktopfile.files = $${TARGET}.desktop + desktopfile.path = /usr/share/applications/hildon + icon.files = $${TARGET}64.png + icon.path = /usr/share/icons/hicolor/64x64/apps + } else:!isEmpty(MEEGO_VERSION_MAJOR) { + desktopfile.files = $${TARGET}_harmattan.desktop + desktopfile.path = /usr/share/applications + icon.files = $${TARGET}80.png + icon.path = /usr/share/icons/hicolor/80x80/apps + } else { # Assumed to be a Desktop Unix + copyCommand = + for(deploymentfolder, DEPLOYMENTFOLDERS) { + source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) + source = $$replace(source, \\\\, /) + macx { + target = $$OUT_PWD/$${TARGET}.app/Contents/Resources/$$eval($${deploymentfolder}.target) + } else { + target = $$OUT_PWD/$$eval($${deploymentfolder}.target) + } + target = $$replace(target, \\\\, /) + sourcePathSegments = $$split(source, /) + targetFullPath = $$target/$$last(sourcePathSegments) + targetFullPath ~= s,/\\.?/,/, + !isEqual(source,$$targetFullPath) { + !isEmpty(copyCommand):copyCommand += && + copyCommand += $(MKDIR) \"$$target\" + copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\" + } + } + !isEmpty(copyCommand) { + copyCommand = @echo Copying application data... && $$copyCommand + copydeploymentfolders.commands = $$copyCommand + first.depends = $(first) copydeploymentfolders + export(first.depends) + export(copydeploymentfolders.commands) + QMAKE_EXTRA_TARGETS += first copydeploymentfolders + } + } + !isEmpty(target.path) { + installPrefix = $${target.path} + } else { + installPrefix = /opt/$${TARGET} + } + for(deploymentfolder, DEPLOYMENTFOLDERS) { + item = item$${deploymentfolder} + itemfiles = $${item}.files + $$itemfiles = $$eval($${deploymentfolder}.source) + itempath = $${item}.path + $$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target) + export($$itemfiles) + export($$itempath) + INSTALLS += $$item + } + + !isEmpty(desktopfile.path) { + export(icon.files) + export(icon.path) + export(desktopfile.files) + export(desktopfile.path) + INSTALLS += icon desktopfile + } + + isEmpty(target.path) { + target.path = $${installPrefix}/bin + export(target.path) + } + INSTALLS += target +} + +export (ICON) +export (INSTALLS) +export (DEPLOYMENT) +export (LIBS) +export (QMAKE_EXTRA_TARGETS) +} diff --git a/examples/qmlscatter/doc/src/qmlscatter.qdoc b/examples/qmlscatter/doc/src/qmlscatter.qdoc new file mode 100644 index 00000000..d52798c2 --- /dev/null +++ b/examples/qmlscatter/doc/src/qmlscatter.qdoc @@ -0,0 +1,29 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +/*! + \example qmlscatter + \title Qt Quick 2 Scatter Example + + The Qt Quick 2 scatter example shows how to make a simple scatter chart visualization using + Q3DScatter using Qt Quick 2. + + \image qmlscatter-example.png + + TODO +*/ diff --git a/examples/qmlscatter/main.cpp b/examples/qmlscatter/main.cpp new file mode 100644 index 00000000..d48bea3d --- /dev/null +++ b/examples/qmlscatter/main.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include <QtGui/QGuiApplication> +#include "qtquick2applicationviewer.h" +#ifdef Q_OS_ANDROID +#include <QDir> +#include <QQmlEngine> +#endif +#include <QDebug> + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QtQuick2ApplicationViewer viewer; +#ifdef Q_OS_ANDROID + viewer.addImportPath(QString::fromLatin1("assets:/qml")); + viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(), + QString::fromLatin1("lib"))); +#else + viewer.addImportPath(QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), + QString::fromLatin1("qml"))); +#endif + viewer.setSource(QUrl("qrc:/qml/main.qml")); + viewer.setResizeMode(QQuickView::SizeRootObjectToView); + viewer.setMinimumSize(QSize(640, 480)); + viewer.show(); + + return app.exec(); +} diff --git a/examples/qmlscatter/qml/qmlscatter/main.qml b/examples/qmlscatter/qml/qmlscatter/main.qml new file mode 100644 index 00000000..6238529d --- /dev/null +++ b/examples/qmlscatter/qml/qmlscatter/main.qml @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 +import com.digia.QtDataVis3D 1.0 + +Item { + id: mainview + width: 800 + height: 700 + visible: true + + Item { + id: dataView + width: parent.width + height: parent.height - shadowToggle.height + anchors.bottom: parent.bottom + + ScatterDataMapping { + id: scatterMapping + xPosRole: "xPos" + yPosRole: "yPos" + zPosRole: "zPos" + } + + ListModel { + id: dataModel + ListElement{ xPos: -10.0; yPos: 4.9; zPos: -5.0 } + ListElement{ xPos: 10.0; yPos: 4.9; zPos: -5.0 } + ListElement{ xPos: -10.0; yPos: 4.9; zPos: 5.0 } + ListElement{ xPos: 10.0; yPos: 4.9; zPos: 5.0 } + ListElement{ xPos: -10.0; yPos: -4.9; zPos: -5.0 } + ListElement{ xPos: 10.0; yPos: -4.9; zPos: -5.0 } + ListElement{ xPos: -10.0; yPos: -4.9; zPos: 5.0 } + ListElement{ xPos: 10.0; yPos: -4.9; zPos: 5.0 } + + ListElement{ xPos: -1.0; yPos: 0.3; zPos: -0.5 } + ListElement{ xPos: 1.0; yPos: 2.105; zPos: 0.5 } + ListElement{ xPos: 0.5; yPos: -0.65; zPos: -0.5 } + ListElement{ xPos: -0.5; yPos: 1.225; zPos: 0.5 } + ListElement{ xPos: 0.0; yPos: 0.0; zPos: 0.0 } + ListElement{ xPos: 0.0; yPos: 2.0; zPos: 0.0 } + ListElement{ xPos: 0.0; yPos: -0.5; zPos: 0.0 } + + ListElement{ xPos: 6.0; yPos: 0.0; zPos: 4.0 } + ListElement{ xPos: 5.8; yPos: 0.2; zPos: 5.0 } + ListElement{ xPos: 5.6; yPos: 0.4; zPos: 4.5 } + ListElement{ xPos: 5.4; yPos: 0.6; zPos: 3.8 } + ListElement{ xPos: 5.2; yPos: 0.8; zPos: 4.8 } + ListElement{ xPos: 5.0; yPos: 0.3; zPos: 4.1 } + ListElement{ xPos: 4.9; yPos: -0.3; zPos: 4.9 } + ListElement{ xPos: 4.7; yPos: -0.5; zPos: 3.5 } + ListElement{ xPos: 4.5; yPos: -0.7; zPos: 3.3 } + ListElement{ xPos: 4.3; yPos: -0.4; zPos: 3.7 } + } + + Scatter3D { + id: testscatter + width: dataView.width + height: dataView.height + fontSize: 30.0 + mapping: scatterMapping + shadowQuality: Scatter3D.ShadowNone + selectionMode: Scatter3D.ModeItem + labelTransparency: Scatter3D.TransparencyNoBackground + + Component.onCompleted: { + console.log("testscatter complete"); + data = dataModel + } + } + } + + Rectangle { + id: shadowToggle + width: 120 + height: 30 + + TextArea { + id: shadowText + text: "Toggle Shadows On" + anchors.fill: parent + } + + MouseArea { + anchors.fill: parent + onClicked: { + if (testscatter.shadowQuality === Scatter3D.ShadowNone) { + testscatter.shadowQuality = Scatter3D.ShadowMedium; + shadowText.text = "Toggle Shadows Off"; + } else { + testscatter.shadowQuality = Scatter3D.ShadowNone; + shadowText.text = "Toggle Shadows On"; + } + } + } + } + Rectangle { + id: smoothToggle + width: 140 + height: 30 + anchors.left: shadowToggle.right + + TextArea { + id: smoothText + text: "Toggle Smooth Objects On" + anchors.fill: parent + } + + MouseArea { + anchors.fill: parent + onClicked: { + if (testscatter.objectSmooth === false) { + smoothText.text = "Toggle Smooth Objects Off" + testscatter.objectSmooth = true; + } else { + smoothText.text = "Toggle Smooth Objects On" + testscatter.objectSmooth = false; + } + } + } + } + Rectangle { + id: cameraToggle + width: 130 + height: 30 + anchors.left: smoothToggle.right + + TextArea { + text: "Toggle Camera Preset" + anchors.fill: parent + } + + MouseArea { + anchors.fill: parent + onClicked: { + if (testscatter.cameraPreset === Scatter3D.PresetFront) { + testscatter.cameraPreset = Scatter3D.PresetIsometricRightHigh; + } else { + testscatter.cameraPreset = Scatter3D.PresetFront; + } + } + } + } + Rectangle { + id: themeToggle + width: 120 + height: 30 + anchors.left: cameraToggle.right + + TextArea { + text: "Toggle Theme" + anchors.fill: parent + } + + MouseArea { + anchors.fill: parent + onClicked: { + if (testscatter.theme === Scatter3D.ThemeBlueCerulean) { + testscatter.theme = Scatter3D.ThemeSystem; + } else { + testscatter.theme = Scatter3D.ThemeBlueCerulean; + } + } + } + } + Rectangle { + id: backgroundToggle + width: 130 + height: 30 + anchors.left: themeToggle.right + + TextArea { + id: backgroundText + text: "Toggle Background Off" + anchors.fill: parent + } + + MouseArea { + anchors.fill: parent + onClicked: { + if (testscatter.backgroundVisible === true) { + testscatter.backgroundVisible = false; + backgroundText.text = "Toggle Background On"; + } else { + testscatter.backgroundVisible = true; + backgroundText.text = "Toggle Background Off"; + } + } + } + } + +} diff --git a/examples/qmlscatter/qmlscatter.desktop b/examples/qmlscatter/qmlscatter.desktop new file mode 100644 index 00000000..0f9e5498 --- /dev/null +++ b/examples/qmlscatter/qmlscatter.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Type=Application +Terminal=false +Name=qmlscatter +Exec=/opt/qmlscatter/bin/qmlscatter +Icon=qmlscatter64 +X-Window-Icon= +X-HildonDesk-ShowInToolbar=true +X-Osso-Type=application/x-executable diff --git a/examples/qmlscatter/qmlscatter.pro b/examples/qmlscatter/qmlscatter.pro new file mode 100644 index 00000000..6f89fbae --- /dev/null +++ b/examples/qmlscatter/qmlscatter.pro @@ -0,0 +1,23 @@ +!include( ../examples.pri ) { + error( "Couldn't find the examples.pri file!" ) +} + +# Add more folders to ship with the application, here +folder_01.source = qml/qmlscatter +folder_01.target = qml +DEPLOYMENTFOLDERS = folder_01 + +# Additional import path used to resolve QML modules in Creator's code model +QML_IMPORT_PATH = + +# The .cpp file which was generated for your project. Feel free to hack it. +SOURCES += main.cpp + +# Installation path +# target.path = + +# Please do not modify the following two lines. Required for deployment. +include(qtquick2applicationviewer/qtquick2applicationviewer.pri) +qtcAddDeployment() + +RESOURCES += qmlscatter.qrc diff --git a/examples/qmlscatter/qmlscatter.qrc b/examples/qmlscatter/qmlscatter.qrc new file mode 100644 index 00000000..62f5931b --- /dev/null +++ b/examples/qmlscatter/qmlscatter.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/qml"> + <file alias="main.qml">qml/qmlscatter/main.qml</file> + </qresource> +</RCC> diff --git a/examples/qmlscatter/qmlscatter64.png b/examples/qmlscatter/qmlscatter64.png Binary files differnew file mode 100644 index 00000000..707d5c4e --- /dev/null +++ b/examples/qmlscatter/qmlscatter64.png diff --git a/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.cpp b/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.cpp new file mode 100644 index 00000000..10709d7a --- /dev/null +++ b/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.cpp @@ -0,0 +1,81 @@ +// checksum 0x4f6f version 0x90005 +/* + This file was generated by the Qt Quick 2 Application wizard of Qt Creator. + QtQuick2ApplicationViewer is a convenience class containing mobile device specific + code such as screen orientation handling. Also QML paths and debugging are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#include "qtquick2applicationviewer.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QDir> +#include <QtQml/QQmlEngine> + +class QtQuick2ApplicationViewerPrivate +{ + QString mainQmlFile; + friend class QtQuick2ApplicationViewer; + static QString adjustPath(const QString &path); +}; + +QString QtQuick2ApplicationViewerPrivate::adjustPath(const QString &path) +{ +#if defined(Q_OS_MAC) + if (!QDir::isAbsolutePath(path)) + return QString::fromLatin1("%1/../Resources/%2") + .arg(QCoreApplication::applicationDirPath(), path); +#elif defined(Q_OS_BLACKBERRY) + if (!QDir::isAbsolutePath(path)) + return QString::fromLatin1("app/native/%1").arg(path); +#elif !defined(Q_OS_ANDROID) + QString pathInInstallDir = + QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path); + if (QFileInfo(pathInInstallDir).exists()) + return pathInInstallDir; + pathInInstallDir = + QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), path); + if (QFileInfo(pathInInstallDir).exists()) + return pathInInstallDir; +#endif + return path; +} + +QtQuick2ApplicationViewer::QtQuick2ApplicationViewer(QWindow *parent) + : QQuickView(parent) + , d(new QtQuick2ApplicationViewerPrivate()) +{ + connect(engine(), SIGNAL(quit()), SLOT(close())); + setResizeMode(QQuickView::SizeRootObjectToView); +} + +QtQuick2ApplicationViewer::~QtQuick2ApplicationViewer() +{ + delete d; +} + +void QtQuick2ApplicationViewer::setMainQmlFile(const QString &file) +{ + d->mainQmlFile = QtQuick2ApplicationViewerPrivate::adjustPath(file); +#ifdef Q_OS_ANDROID + setSource(QUrl(QLatin1String("assets:/")+d->mainQmlFile)); +#else + setSource(QUrl::fromLocalFile(d->mainQmlFile)); +#endif +} + +void QtQuick2ApplicationViewer::addImportPath(const QString &path) +{ + engine()->addImportPath(QtQuick2ApplicationViewerPrivate::adjustPath(path)); +} + +void QtQuick2ApplicationViewer::showExpanded() +{ +#if defined(Q_WS_SIMULATOR) || defined(Q_OS_QNX) + showFullScreen(); +#else + show(); +#endif +} diff --git a/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.h b/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.h new file mode 100644 index 00000000..cf66f140 --- /dev/null +++ b/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.h @@ -0,0 +1,33 @@ +// checksum 0xfde6 version 0x90005 +/* + This file was generated by the Qt Quick 2 Application wizard of Qt Creator. + QtQuick2ApplicationViewer is a convenience class containing mobile device specific + code such as screen orientation handling. Also QML paths and debugging are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#ifndef QTQUICK2APPLICATIONVIEWER_H +#define QTQUICK2APPLICATIONVIEWER_H + +#include <QtQuick/QQuickView> + +class QtQuick2ApplicationViewer : public QQuickView +{ + Q_OBJECT + +public: + explicit QtQuick2ApplicationViewer(QWindow *parent = 0); + virtual ~QtQuick2ApplicationViewer(); + + void setMainQmlFile(const QString &file); + void addImportPath(const QString &path); + + void showExpanded(); + +private: + class QtQuick2ApplicationViewerPrivate *d; +}; + +#endif // QTQUICK2APPLICATIONVIEWER_H diff --git a/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.pri b/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.pri new file mode 100644 index 00000000..e5f7990f --- /dev/null +++ b/examples/qmlscatter/qtquick2applicationviewer/qtquick2applicationviewer.pri @@ -0,0 +1,180 @@ +# checksum 0x7b0d version 0x90005 +# This file was generated by the Qt Quick 2 Application wizard of Qt Creator. +# The code below adds the QtQuick2ApplicationViewer to the project and handles +# the activation of QML debugging. +# It is recommended not to modify this file, since newer versions of Qt Creator +# may offer an updated version of it. + +QT += qml quick + +SOURCES += $$PWD/qtquick2applicationviewer.cpp +HEADERS += $$PWD/qtquick2applicationviewer.h +INCLUDEPATH += $$PWD +# This file was generated by an application wizard of Qt Creator. +# The code below handles deployment to Android and Maemo, aswell as copying +# of the application data to shadow build directories on desktop. +# It is recommended not to modify this file, since newer versions of Qt Creator +# may offer an updated version of it. + +defineTest(qtcAddDeployment) { +for(deploymentfolder, DEPLOYMENTFOLDERS) { + item = item$${deploymentfolder} + greaterThan(QT_MAJOR_VERSION, 4) { + itemsources = $${item}.files + } else { + itemsources = $${item}.sources + } + $$itemsources = $$eval($${deploymentfolder}.source) + itempath = $${item}.path + $$itempath= $$eval($${deploymentfolder}.target) + export($$itemsources) + export($$itempath) + DEPLOYMENT += $$item +} + +MAINPROFILEPWD = $$PWD + +android-no-sdk { + for(deploymentfolder, DEPLOYMENTFOLDERS) { + item = item$${deploymentfolder} + itemfiles = $${item}.files + $$itemfiles = $$eval($${deploymentfolder}.source) + itempath = $${item}.path + $$itempath = /data/user/qt/$$eval($${deploymentfolder}.target) + export($$itemfiles) + export($$itempath) + INSTALLS += $$item + } + + target.path = /data/user/qt + + export(target.path) + INSTALLS += target +} else:android { + for(deploymentfolder, DEPLOYMENTFOLDERS) { + item = item$${deploymentfolder} + itemfiles = $${item}.files + $$itemfiles = $$eval($${deploymentfolder}.source) + itempath = $${item}.path + $$itempath = /assets/$$eval($${deploymentfolder}.target) + export($$itemfiles) + export($$itempath) + INSTALLS += $$item + } + + x86 { + target.path = /libs/x86 + } else: armeabi-v7a { + target.path = /libs/armeabi-v7a + } else { + target.path = /libs/armeabi + } + + export(target.path) + INSTALLS += target +} else:win32 { + copyCommand = + for(deploymentfolder, DEPLOYMENTFOLDERS) { + source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) + source = $$replace(source, /, \\) + sourcePathSegments = $$split(source, \\) + target = $$OUT_PWD/$$eval($${deploymentfolder}.target)/$$last(sourcePathSegments) + target = $$replace(target, /, \\) + target ~= s,\\\\\\.?\\\\,\\, + !isEqual(source,$$target) { + !isEmpty(copyCommand):copyCommand += && + isEqual(QMAKE_DIR_SEP, \\) { + copyCommand += $(COPY_DIR) \"$$source\" \"$$target\" + } else { + source = $$replace(source, \\\\, /) + target = $$OUT_PWD/$$eval($${deploymentfolder}.target) + target = $$replace(target, \\\\, /) + copyCommand += test -d \"$$target\" || mkdir -p \"$$target\" && cp -r \"$$source\" \"$$target\" + } + } + } + !isEmpty(copyCommand) { + copyCommand = @echo Copying application data... && $$copyCommand + copydeploymentfolders.commands = $$copyCommand + first.depends = $(first) copydeploymentfolders + export(first.depends) + export(copydeploymentfolders.commands) + QMAKE_EXTRA_TARGETS += first copydeploymentfolders + } +} else:unix { + maemo5 { + desktopfile.files = $${TARGET}.desktop + desktopfile.path = /usr/share/applications/hildon + icon.files = $${TARGET}64.png + icon.path = /usr/share/icons/hicolor/64x64/apps + } else:!isEmpty(MEEGO_VERSION_MAJOR) { + desktopfile.files = $${TARGET}_harmattan.desktop + desktopfile.path = /usr/share/applications + icon.files = $${TARGET}80.png + icon.path = /usr/share/icons/hicolor/80x80/apps + } else { # Assumed to be a Desktop Unix + copyCommand = + for(deploymentfolder, DEPLOYMENTFOLDERS) { + source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) + source = $$replace(source, \\\\, /) + macx { + target = $$OUT_PWD/$${TARGET}.app/Contents/Resources/$$eval($${deploymentfolder}.target) + } else { + target = $$OUT_PWD/$$eval($${deploymentfolder}.target) + } + target = $$replace(target, \\\\, /) + sourcePathSegments = $$split(source, /) + targetFullPath = $$target/$$last(sourcePathSegments) + targetFullPath ~= s,/\\.?/,/, + !isEqual(source,$$targetFullPath) { + !isEmpty(copyCommand):copyCommand += && + copyCommand += $(MKDIR) \"$$target\" + copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\" + } + } + !isEmpty(copyCommand) { + copyCommand = @echo Copying application data... && $$copyCommand + copydeploymentfolders.commands = $$copyCommand + first.depends = $(first) copydeploymentfolders + export(first.depends) + export(copydeploymentfolders.commands) + QMAKE_EXTRA_TARGETS += first copydeploymentfolders + } + } + !isEmpty(target.path) { + installPrefix = $${target.path} + } else { + installPrefix = /opt/$${TARGET} + } + for(deploymentfolder, DEPLOYMENTFOLDERS) { + item = item$${deploymentfolder} + itemfiles = $${item}.files + $$itemfiles = $$eval($${deploymentfolder}.source) + itempath = $${item}.path + $$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target) + export($$itemfiles) + export($$itempath) + INSTALLS += $$item + } + + !isEmpty(desktopfile.path) { + export(icon.files) + export(icon.path) + export(desktopfile.files) + export(desktopfile.path) + INSTALLS += icon desktopfile + } + + isEmpty(target.path) { + target.path = $${installPrefix}/bin + export(target.path) + } + INSTALLS += target +} + +export (ICON) +export (INSTALLS) +export (DEPLOYMENT) +export (LIBS) +export (QMAKE_EXTRA_TARGETS) +} diff --git a/examples/rainfall/data/raindata.txt b/examples/rainfall/data/raindata.txt new file mode 100644 index 00000000..7f581bff --- /dev/null +++ b/examples/rainfall/data/raindata.txt @@ -0,0 +1,1358 @@ +# Fictitious rainfall per month from 1900 to 2012 in three cities +# Format: year, month, city 1 rainfall, city 2 rainfall, city 3 rainfall +1900, 1, 58, 60, 40 +1900, 2, 48, 101, 47 +1900, 3, 58, 90, 25 +1900, 4, 59, 81, 33 +1900, 5, 51, 90, 24 +1900, 6, 91, 92, 55 +1900, 7, 92, 124, 34 +1900, 8, 89, 124, 30 +1900, 9, 50, 89, 16 +1900, 10, 69, 100, 55 +1900, 11, 78, 86, 15 +1900, 12, 63, 62, 30 +1901, 1, 34, 56, 50 +1901, 2, 31, 93, 54 +1901, 3, 72, 98, 34 +1901, 4, 88, 104, 18 +1901, 5, 66, 107, 20 +1901, 6, 121, 123, 34 +1901, 7, 100, 133, 46 +1901, 8, 129, 90, 64 +1901, 9, 98, 75, 56 +1901, 10, 77, 84, 56 +1901, 11, 42, 62, 38 +1901, 12, 62, 94, 22 +1902, 1, 58, 80, 37 +1902, 2, 43, 56, 16 +1902, 3, 53, 92, 9 +1902, 4, 81, 87, 33 +1902, 5, 85, 86, 60 +1902, 6, 98, 98, 32 +1902, 7, 100, 100, 54 +1902, 8, 107, 116, 69 +1902, 9, 86, 101, 43 +1902, 10, 71, 112, 34 +1902, 11, 43, 61, 7 +1902, 12, 30, 77, 21 +1903, 1, 38, 89, 12 +1903, 2, 43, 95, 29 +1903, 3, 67, 81, 49 +1903, 4, 59, 104, 32 +1903, 5, 79, 80, 64 +1903, 6, 117, 123, 53 +1903, 7, 104, 101, 49 +1903, 8, 111, 137, 56 +1903, 9, 68, 72, 23 +1903, 10, 81, 100, 62 +1903, 11, 68, 67, 50 +1903, 12, 34, 76, 42 +1904, 1, 65, 66, 33 +1904, 2, 41, 95, 18 +1904, 3, 46, 101, 31 +1904, 4, 53, 72, 32 +1904, 5, 82, 104, 52 +1904, 6, 123, 102, 32 +1904, 7, 109, 127, 30 +1904, 8, 100, 114, 67 +1904, 9, 91, 99, 45 +1904, 10, 79, 84, 62 +1904, 11, 38, 86, 30 +1904, 12, 71, 56, 14 +1905, 1, 59, 64, 39 +1905, 2, 75, 73, 32 +1905, 3, 30, 102, 36 +1905, 4, 86, 83, 39 +1905, 5, 93, 66, 31 +1905, 6, 118, 137, 36 +1905, 7, 129, 95, 31 +1905, 8, 104, 128, 56 +1905, 9, 59, 87, 61 +1905, 10, 54, 86, 56 +1905, 11, 46, 78, 51 +1905, 12, 57, 94, 47 +1906, 1, 75, 79, 17 +1906, 2, 72, 91, 44 +1906, 3, 52, 77, 32 +1906, 4, 63, 94, 41 +1906, 5, 83, 92, 48 +1906, 6, 121, 98, 65 +1906, 7, 93, 129, 60 +1906, 8, 104, 100, 48 +1906, 9, 90, 102, 59 +1906, 10, 58, 74, 42 +1906, 11, 52, 57, 9 +1906, 12, 53, 87, 28 +1907, 1, 74, 82, 50 +1907, 2, 45, 76, 10 +1907, 3, 38, 62, 37 +1907, 4, 58, 93, 59 +1907, 5, 66, 69, 21 +1907, 6, 102, 112, 42 +1907, 7, 125, 129, 30 +1907, 8, 108, 128, 51 +1907, 9, 81, 98, 23 +1907, 10, 58, 84, 45 +1907, 11, 68, 70, 51 +1907, 12, 70, 76, 29 +1908, 1, 49, 75, 11 +1908, 2, 56, 73, 45 +1908, 3, 79, 93, 29 +1908, 4, 93, 82, 39 +1908, 5, 70, 87, 52 +1908, 6, 113, 107, 34 +1908, 7, 120, 97, 40 +1908, 8, 92, 95, 74 +1908, 9, 88, 83, 16 +1908, 10, 57, 67, 33 +1908, 11, 30, 55, 12 +1908, 12, 37, 85, 54 +1909, 1, 67, 79, 47 +1909, 2, 68, 101, 7 +1909, 3, 59, 94, 14 +1909, 4, 58, 93, 49 +1909, 5, 79, 71, 32 +1909, 6, 129, 126, 68 +1909, 7, 82, 138, 52 +1909, 8, 96, 124, 73 +1909, 9, 85, 72, 27 +1909, 10, 92, 107, 61 +1909, 11, 42, 97, 51 +1909, 12, 31, 96, 33 +1910, 1, 71, 104, 27 +1910, 2, 76, 103, 6 +1910, 3, 53, 70, 13 +1910, 4, 71, 102, 37 +1910, 5, 63, 96, 34 +1910, 6, 112, 106, 59 +1910, 7, 81, 94, 28 +1910, 8, 98, 107, 26 +1910, 9, 63, 77, 21 +1910, 10, 60, 72, 39 +1910, 11, 36, 66, 12 +1910, 12, 62, 99, 36 +1911, 1, 78, 101, 48 +1911, 2, 35, 61, 38 +1911, 3, 48, 86, 24 +1911, 4, 78, 93, 31 +1911, 5, 90, 92, 49 +1911, 6, 89, 115, 64 +1911, 7, 129, 90, 46 +1911, 8, 88, 116, 35 +1911, 9, 91, 109, 64 +1911, 10, 95, 78, 45 +1911, 11, 55, 103, 8 +1911, 12, 36, 79, 10 +1912, 1, 30, 90, 15 +1912, 2, 49, 76, 37 +1912, 3, 79, 68, 45 +1912, 4, 74, 90, 52 +1912, 5, 61, 99, 30 +1912, 6, 112, 93, 39 +1912, 7, 88, 110, 48 +1912, 8, 99, 138, 47 +1912, 9, 92, 93, 56 +1912, 10, 86, 98, 46 +1912, 11, 31, 104, 14 +1912, 12, 60, 101, 19 +1913, 1, 71, 103, 37 +1913, 2, 42, 104, 26 +1913, 3, 68, 66, 31 +1913, 4, 81, 108, 57 +1913, 5, 77, 88, 64 +1913, 6, 98, 94, 46 +1913, 7, 127, 111, 36 +1913, 8, 91, 95, 48 +1913, 9, 51, 110, 23 +1913, 10, 77, 73, 46 +1913, 11, 36, 103, 11 +1913, 12, 45, 66, 40 +1914, 1, 55, 78, 21 +1914, 2, 40, 80, 6 +1914, 3, 71, 84, 12 +1914, 4, 56, 111, 23 +1914, 5, 79, 84, 17 +1914, 6, 124, 105, 62 +1914, 7, 121, 95, 68 +1914, 8, 81, 121, 37 +1914, 9, 64, 65, 52 +1914, 10, 56, 106, 27 +1914, 11, 53, 97, 52 +1914, 12, 75, 104, 39 +1915, 1, 37, 86, 6 +1915, 2, 74, 85, 30 +1915, 3, 75, 77, 49 +1915, 4, 72, 104, 37 +1915, 5, 88, 95, 41 +1915, 6, 111, 122, 53 +1915, 7, 112, 108, 43 +1915, 8, 119, 107, 51 +1915, 9, 85, 95, 43 +1915, 10, 76, 69, 48 +1915, 11, 42, 88, 48 +1915, 12, 42, 68, 13 +1916, 1, 70, 100, 30 +1916, 2, 64, 77, 10 +1916, 3, 45, 104, 26 +1916, 4, 74, 98, 53 +1916, 5, 52, 86, 26 +1916, 6, 105, 139, 56 +1916, 7, 123, 90, 36 +1916, 8, 87, 99, 32 +1916, 9, 73, 107, 30 +1916, 10, 79, 109, 51 +1916, 11, 45, 69, 43 +1916, 12, 62, 85, 11 +1917, 1, 73, 87, 5 +1917, 2, 61, 102, 18 +1917, 3, 48, 71, 50 +1917, 4, 83, 95, 33 +1917, 5, 97, 102, 38 +1917, 6, 117, 114, 66 +1917, 7, 127, 107, 66 +1917, 8, 120, 101, 36 +1917, 9, 79, 102, 44 +1917, 10, 56, 114, 38 +1917, 11, 66, 69, 36 +1917, 12, 33, 71, 52 +1918, 1, 67, 76, 42 +1918, 2, 71, 95, 33 +1918, 3, 51, 56, 28 +1918, 4, 95, 66, 50 +1918, 5, 77, 92, 51 +1918, 6, 91, 92, 64 +1918, 7, 103, 97, 51 +1918, 8, 90, 116, 55 +1918, 9, 72, 108, 34 +1918, 10, 60, 76, 55 +1918, 11, 63, 100, 44 +1918, 12, 30, 65, 12 +1919, 1, 58, 89, 48 +1919, 2, 45, 102, 29 +1919, 3, 48, 101, 47 +1919, 4, 68, 105, 64 +1919, 5, 71, 112, 18 +1919, 6, 129, 90, 73 +1919, 7, 120, 95, 73 +1919, 8, 96, 109, 35 +1919, 9, 70, 92, 20 +1919, 10, 61, 90, 41 +1919, 11, 37, 103, 6 +1919, 12, 70, 95, 25 +1920, 1, 43, 86, 52 +1920, 2, 69, 87, 51 +1920, 3, 61, 79, 27 +1920, 4, 65, 103, 51 +1920, 5, 60, 66, 21 +1920, 6, 80, 129, 50 +1920, 7, 106, 127, 56 +1920, 8, 110, 120, 39 +1920, 9, 71, 110, 64 +1920, 10, 79, 78, 58 +1920, 11, 51, 69, 41 +1920, 12, 56, 83, 8 +1921, 1, 65, 94, 10 +1921, 2, 32, 61, 44 +1921, 3, 76, 75, 24 +1921, 4, 52, 76, 55 +1921, 5, 50, 81, 46 +1921, 6, 128, 123, 48 +1921, 7, 92, 122, 38 +1921, 8, 102, 107, 50 +1921, 9, 93, 88, 44 +1921, 10, 96, 92, 24 +1921, 11, 64, 90, 38 +1921, 12, 34, 58, 38 +1922, 1, 75, 68, 50 +1922, 2, 40, 89, 29 +1922, 3, 31, 72, 46 +1922, 4, 80, 101, 22 +1922, 5, 94, 89, 61 +1922, 6, 85, 100, 65 +1922, 7, 111, 132, 32 +1922, 8, 83, 110, 45 +1922, 9, 81, 90, 32 +1922, 10, 60, 88, 22 +1922, 11, 45, 59, 37 +1922, 12, 34, 73, 36 +1923, 1, 46, 92, 47 +1923, 2, 75, 73, 5 +1923, 3, 58, 65, 21 +1923, 4, 83, 99, 47 +1923, 5, 64, 71, 37 +1923, 6, 124, 120, 57 +1923, 7, 114, 132, 32 +1923, 8, 113, 136, 56 +1923, 9, 54, 91, 43 +1923, 10, 57, 107, 26 +1923, 11, 75, 85, 43 +1923, 12, 38, 71, 29 +1924, 1, 66, 95, 49 +1924, 2, 72, 92, 48 +1924, 3, 34, 86, 17 +1924, 4, 58, 69, 23 +1924, 5, 77, 71, 25 +1924, 6, 117, 125, 27 +1924, 7, 105, 105, 33 +1924, 8, 83, 124, 25 +1924, 9, 99, 107, 57 +1924, 10, 55, 75, 59 +1924, 11, 47, 93, 5 +1924, 12, 71, 73, 46 +1925, 1, 30, 78, 41 +1925, 2, 33, 59, 48 +1925, 3, 39, 59, 8 +1925, 4, 82, 82, 35 +1925, 5, 65, 76, 21 +1925, 6, 99, 97, 62 +1925, 7, 82, 104, 63 +1925, 8, 116, 111, 67 +1925, 9, 97, 82, 25 +1925, 10, 63, 78, 55 +1925, 11, 32, 86, 50 +1925, 12, 52, 63, 13 +1926, 1, 76, 94, 52 +1926, 2, 50, 62, 34 +1926, 3, 41, 95, 52 +1926, 4, 84, 68, 17 +1926, 5, 52, 76, 33 +1926, 6, 97, 125, 49 +1926, 7, 92, 137, 37 +1926, 8, 90, 127, 30 +1926, 9, 60, 98, 42 +1926, 10, 54, 113, 33 +1926, 11, 62, 91, 52 +1926, 12, 62, 87, 48 +1927, 1, 54, 64, 30 +1927, 2, 60, 99, 30 +1927, 3, 45, 81, 36 +1927, 4, 61, 82, 58 +1927, 5, 57, 65, 57 +1927, 6, 125, 90, 56 +1927, 7, 104, 132, 68 +1927, 8, 127, 96, 66 +1927, 9, 77, 96, 15 +1927, 10, 68, 95, 55 +1927, 11, 55, 76, 38 +1927, 12, 78, 82, 36 +1928, 1, 67, 56, 45 +1928, 2, 51, 96, 51 +1928, 3, 63, 72, 15 +1928, 4, 85, 85, 30 +1928, 5, 54, 72, 46 +1928, 6, 90, 100, 26 +1928, 7, 103, 133, 29 +1928, 8, 94, 110, 29 +1928, 9, 71, 103, 63 +1928, 10, 79, 69, 62 +1928, 11, 49, 55, 24 +1928, 12, 33, 63, 12 +1929, 1, 48, 62, 20 +1929, 2, 77, 62, 51 +1929, 3, 70, 75, 8 +1929, 4, 83, 81, 23 +1929, 5, 64, 92, 56 +1929, 6, 126, 106, 35 +1929, 7, 96, 118, 45 +1929, 8, 80, 120, 46 +1929, 9, 94, 88, 62 +1929, 10, 50, 102, 33 +1929, 11, 62, 76, 47 +1929, 12, 70, 68, 33 +1930, 1, 51, 100, 30 +1930, 2, 60, 57, 46 +1930, 3, 65, 78, 38 +1930, 4, 70, 67, 37 +1930, 5, 83, 106, 62 +1930, 6, 127, 126, 51 +1930, 7, 108, 137, 61 +1930, 8, 81, 117, 69 +1930, 9, 51, 93, 37 +1930, 10, 56, 78, 63 +1930, 11, 38, 65, 18 +1930, 12, 32, 72, 19 +1931, 1, 76, 57, 15 +1931, 2, 62, 71, 53 +1931, 3, 32, 70, 25 +1931, 4, 76, 96, 51 +1931, 5, 85, 76, 61 +1931, 6, 112, 111, 57 +1931, 7, 85, 108, 42 +1931, 8, 125, 114, 29 +1931, 9, 89, 92, 27 +1931, 10, 95, 83, 19 +1931, 11, 34, 103, 25 +1931, 12, 33, 102, 50 +1932, 1, 38, 87, 6 +1932, 2, 66, 101, 15 +1932, 3, 40, 63, 27 +1932, 4, 60, 107, 15 +1932, 5, 98, 83, 27 +1932, 6, 122, 104, 48 +1932, 7, 92, 137, 46 +1932, 8, 104, 129, 29 +1932, 9, 63, 95, 39 +1932, 10, 76, 83, 35 +1932, 11, 62, 65, 43 +1932, 12, 75, 78, 7 +1933, 1, 71, 90, 7 +1933, 2, 72, 67, 32 +1933, 3, 32, 102, 25 +1933, 4, 67, 107, 39 +1933, 5, 78, 95, 43 +1933, 6, 115, 104, 33 +1933, 7, 127, 135, 74 +1933, 8, 99, 137, 52 +1933, 9, 57, 94, 51 +1933, 10, 76, 96, 28 +1933, 11, 40, 70, 12 +1933, 12, 30, 64, 12 +1934, 1, 70, 62, 35 +1934, 2, 34, 71, 7 +1934, 3, 66, 96, 7 +1934, 4, 60, 75, 36 +1934, 5, 67, 110, 15 +1934, 6, 93, 124, 31 +1934, 7, 123, 109, 69 +1934, 8, 80, 97, 57 +1934, 9, 69, 82, 51 +1934, 10, 95, 67, 53 +1934, 11, 61, 65, 24 +1934, 12, 71, 82, 14 +1935, 1, 53, 59, 46 +1935, 2, 36, 76, 7 +1935, 3, 66, 102, 7 +1935, 4, 80, 85, 55 +1935, 5, 65, 104, 30 +1935, 6, 86, 134, 68 +1935, 7, 128, 109, 44 +1935, 8, 117, 111, 45 +1935, 9, 60, 72, 53 +1935, 10, 56, 83, 62 +1935, 11, 74, 69, 42 +1935, 12, 49, 100, 11 +1936, 1, 38, 64, 28 +1936, 2, 67, 101, 39 +1936, 3, 33, 65, 54 +1936, 4, 74, 110, 25 +1936, 5, 62, 69, 39 +1936, 6, 107, 101, 73 +1936, 7, 102, 90, 47 +1936, 8, 88, 135, 47 +1936, 9, 62, 88, 32 +1936, 10, 96, 102, 19 +1936, 11, 72, 59, 51 +1936, 12, 56, 66, 45 +1937, 1, 50, 80, 23 +1937, 2, 56, 86, 39 +1937, 3, 30, 79, 16 +1937, 4, 69, 100, 19 +1937, 5, 99, 114, 22 +1937, 6, 128, 92, 33 +1937, 7, 128, 98, 44 +1937, 8, 92, 133, 56 +1937, 9, 67, 89, 17 +1937, 10, 79, 89, 40 +1937, 11, 48, 58, 36 +1937, 12, 79, 96, 51 +1938, 1, 78, 85, 34 +1938, 2, 41, 67, 5 +1938, 3, 41, 57, 45 +1938, 4, 88, 113, 16 +1938, 5, 73, 78, 28 +1938, 6, 92, 100, 42 +1938, 7, 118, 124, 68 +1938, 8, 89, 105, 65 +1938, 9, 73, 110, 45 +1938, 10, 98, 81, 60 +1938, 11, 54, 85, 16 +1938, 12, 70, 65, 42 +1939, 1, 39, 64, 18 +1939, 2, 33, 92, 27 +1939, 3, 39, 100, 34 +1939, 4, 97, 101, 21 +1939, 5, 70, 84, 29 +1939, 6, 103, 126, 57 +1939, 7, 114, 102, 70 +1939, 8, 110, 105, 36 +1939, 9, 99, 79, 54 +1939, 10, 57, 88, 16 +1939, 11, 73, 59, 6 +1939, 12, 46, 78, 22 +1940, 1, 57, 77, 49 +1940, 2, 68, 80, 46 +1940, 3, 73, 100, 5 +1940, 4, 77, 66, 17 +1940, 5, 79, 111, 43 +1940, 6, 112, 125, 65 +1940, 7, 85, 111, 52 +1940, 8, 85, 96, 53 +1940, 9, 58, 75, 53 +1940, 10, 67, 82, 36 +1940, 11, 78, 89, 16 +1940, 12, 62, 104, 10 +1941, 1, 51, 61, 35 +1941, 2, 36, 88, 18 +1941, 3, 73, 65, 11 +1941, 4, 97, 68, 49 +1941, 5, 80, 110, 47 +1941, 6, 100, 112, 64 +1941, 7, 123, 104, 40 +1941, 8, 93, 99, 45 +1941, 9, 86, 99, 33 +1941, 10, 98, 76, 64 +1941, 11, 72, 101, 24 +1941, 12, 77, 78, 40 +1942, 1, 48, 98, 8 +1942, 2, 55, 69, 46 +1942, 3, 36, 77, 24 +1942, 4, 76, 111, 23 +1942, 5, 99, 85, 49 +1942, 6, 83, 125, 72 +1942, 7, 125, 97, 41 +1942, 8, 106, 98, 68 +1942, 9, 87, 105, 35 +1942, 10, 93, 73, 28 +1942, 11, 44, 71, 23 +1942, 12, 58, 92, 47 +1943, 1, 65, 72, 28 +1943, 2, 53, 74, 46 +1943, 3, 56, 76, 33 +1943, 4, 62, 94, 34 +1943, 5, 97, 109, 23 +1943, 6, 105, 95, 41 +1943, 7, 104, 128, 37 +1943, 8, 83, 117, 56 +1943, 9, 56, 97, 58 +1943, 10, 67, 99, 22 +1943, 11, 70, 68, 53 +1943, 12, 52, 89, 20 +1944, 1, 69, 83, 53 +1944, 2, 74, 57, 13 +1944, 3, 57, 67, 13 +1944, 4, 85, 103, 25 +1944, 5, 57, 113, 21 +1944, 6, 116, 102, 60 +1944, 7, 105, 92, 59 +1944, 8, 90, 125, 68 +1944, 9, 73, 93, 32 +1944, 10, 90, 84, 30 +1944, 11, 51, 83, 13 +1944, 12, 36, 82, 41 +1945, 1, 70, 82, 45 +1945, 2, 56, 82, 44 +1945, 3, 55, 103, 21 +1945, 4, 95, 93, 27 +1945, 5, 88, 86, 59 +1945, 6, 127, 98, 25 +1945, 7, 90, 112, 60 +1945, 8, 104, 132, 53 +1945, 9, 87, 96, 29 +1945, 10, 97, 81, 29 +1945, 11, 36, 82, 7 +1945, 12, 47, 72, 6 +1946, 1, 39, 65, 46 +1946, 2, 62, 74, 47 +1946, 3, 75, 83, 20 +1946, 4, 77, 107, 61 +1946, 5, 63, 110, 54 +1946, 6, 92, 131, 55 +1946, 7, 101, 111, 42 +1946, 8, 118, 118, 69 +1946, 9, 74, 109, 58 +1946, 10, 61, 67, 38 +1946, 11, 49, 94, 34 +1946, 12, 73, 81, 27 +1947, 1, 56, 72, 48 +1947, 2, 78, 97, 36 +1947, 3, 57, 102, 51 +1947, 4, 71, 92, 45 +1947, 5, 58, 81, 39 +1947, 6, 93, 136, 53 +1947, 7, 117, 132, 41 +1947, 8, 91, 104, 33 +1947, 9, 65, 95, 40 +1947, 10, 64, 87, 26 +1947, 11, 46, 87, 7 +1947, 12, 43, 78, 10 +1948, 1, 40, 79, 12 +1948, 2, 67, 63, 52 +1948, 3, 73, 66, 24 +1948, 4, 97, 86, 52 +1948, 5, 73, 105, 35 +1948, 6, 99, 129, 69 +1948, 7, 122, 109, 64 +1948, 8, 104, 134, 33 +1948, 9, 62, 79, 62 +1948, 10, 61, 71, 45 +1948, 11, 36, 91, 54 +1948, 12, 51, 95, 25 +1949, 1, 38, 73, 41 +1949, 2, 39, 76, 49 +1949, 3, 77, 84, 53 +1949, 4, 89, 69, 20 +1949, 5, 75, 114, 47 +1949, 6, 100, 117, 73 +1949, 7, 116, 105, 55 +1949, 8, 116, 95, 71 +1949, 9, 69, 98, 55 +1949, 10, 66, 111, 51 +1949, 11, 60, 77, 18 +1949, 12, 56, 97, 53 +1950, 1, 79, 82, 42 +1950, 2, 55, 71, 10 +1950, 3, 59, 104, 23 +1950, 4, 77, 107, 34 +1950, 5, 58, 72, 39 +1950, 6, 101, 139, 42 +1950, 7, 102, 135, 55 +1950, 8, 111, 133, 30 +1950, 9, 61, 89, 15 +1950, 10, 86, 113, 56 +1950, 11, 72, 63, 35 +1950, 12, 59, 80, 23 +1951, 1, 55, 80, 24 +1951, 2, 53, 83, 29 +1951, 3, 71, 68, 24 +1951, 4, 67, 98, 29 +1951, 5, 80, 91, 64 +1951, 6, 96, 108, 51 +1951, 7, 125, 103, 43 +1951, 8, 102, 124, 36 +1951, 9, 61, 77, 17 +1951, 10, 67, 77, 36 +1951, 11, 40, 90, 26 +1951, 12, 64, 69, 38 +1952, 1, 62, 86, 36 +1952, 2, 31, 74, 32 +1952, 3, 65, 70, 35 +1952, 4, 59, 99, 21 +1952, 5, 88, 82, 43 +1952, 6, 124, 94, 66 +1952, 7, 99, 90, 30 +1952, 8, 127, 107, 32 +1952, 9, 54, 74, 53 +1952, 10, 92, 80, 43 +1952, 11, 50, 59, 29 +1952, 12, 79, 87, 8 +1953, 1, 55, 94, 42 +1953, 2, 33, 77, 33 +1953, 3, 55, 70, 5 +1953, 4, 97, 87, 29 +1953, 5, 56, 88, 57 +1953, 6, 83, 116, 41 +1953, 7, 99, 126, 60 +1953, 8, 105, 99, 62 +1953, 9, 66, 79, 39 +1953, 10, 65, 91, 25 +1953, 11, 58, 62, 17 +1953, 12, 40, 78, 31 +1954, 1, 59, 59, 39 +1954, 2, 73, 92, 25 +1954, 3, 67, 86, 18 +1954, 4, 54, 99, 45 +1954, 5, 64, 68, 50 +1954, 6, 122, 102, 35 +1954, 7, 113, 134, 45 +1954, 8, 123, 102, 58 +1954, 9, 84, 102, 32 +1954, 10, 90, 110, 62 +1954, 11, 45, 103, 46 +1954, 12, 62, 96, 53 +1955, 1, 55, 74, 9 +1955, 2, 67, 97, 52 +1955, 3, 42, 62, 15 +1955, 4, 85, 75, 16 +1955, 5, 80, 102, 21 +1955, 6, 81, 103, 52 +1955, 7, 97, 99, 36 +1955, 8, 82, 91, 39 +1955, 9, 98, 95, 44 +1955, 10, 56, 70, 57 +1955, 11, 53, 74, 21 +1955, 12, 32, 100, 47 +1956, 1, 43, 102, 11 +1956, 2, 62, 104, 37 +1956, 3, 64, 64, 13 +1956, 4, 89, 72, 50 +1956, 5, 74, 75, 60 +1956, 6, 114, 95, 61 +1956, 7, 123, 99, 39 +1956, 8, 104, 110, 49 +1956, 9, 81, 87, 22 +1956, 10, 88, 78, 43 +1956, 11, 36, 69, 43 +1956, 12, 53, 88, 43 +1957, 1, 69, 66, 7 +1957, 2, 79, 80, 13 +1957, 3, 38, 98, 10 +1957, 4, 93, 108, 30 +1957, 5, 80, 95, 36 +1957, 6, 125, 124, 52 +1957, 7, 96, 100, 74 +1957, 8, 85, 91, 58 +1957, 9, 81, 93, 24 +1957, 10, 70, 71, 54 +1957, 11, 32, 66, 33 +1957, 12, 49, 75, 45 +1958, 1, 43, 89, 25 +1958, 2, 55, 86, 12 +1958, 3, 73, 84, 31 +1958, 4, 57, 99, 24 +1958, 5, 81, 81, 33 +1958, 6, 108, 118, 27 +1958, 7, 112, 114, 51 +1958, 8, 96, 136, 40 +1958, 9, 77, 105, 44 +1958, 10, 73, 90, 58 +1958, 11, 59, 93, 20 +1958, 12, 47, 73, 54 +1959, 1, 64, 68, 16 +1959, 2, 55, 95, 18 +1959, 3, 71, 64, 49 +1959, 4, 94, 71, 22 +1959, 5, 83, 67, 35 +1959, 6, 95, 130, 38 +1959, 7, 101, 130, 43 +1959, 8, 93, 95, 61 +1959, 9, 58, 100, 48 +1959, 10, 69, 94, 18 +1959, 11, 36, 77, 13 +1959, 12, 60, 81, 26 +1960, 1, 58, 83, 25 +1960, 2, 69, 85, 49 +1960, 3, 43, 57, 36 +1960, 4, 90, 72, 62 +1960, 5, 94, 102, 37 +1960, 6, 121, 128, 65 +1960, 7, 88, 133, 57 +1960, 8, 87, 127, 35 +1960, 9, 62, 79, 39 +1960, 10, 54, 113, 21 +1960, 11, 64, 60, 24 +1960, 12, 54, 68, 18 +1961, 1, 70, 93, 18 +1961, 2, 63, 72, 15 +1961, 3, 43, 102, 19 +1961, 4, 53, 87, 45 +1961, 5, 52, 66, 27 +1961, 6, 110, 100, 58 +1961, 7, 92, 133, 35 +1961, 8, 116, 98, 66 +1961, 9, 93, 82, 29 +1961, 10, 85, 96, 48 +1961, 11, 74, 88, 17 +1961, 12, 32, 77, 31 +1962, 1, 69, 59, 31 +1962, 2, 42, 90, 53 +1962, 3, 33, 79, 22 +1962, 4, 67, 75, 26 +1962, 5, 91, 114, 40 +1962, 6, 118, 134, 72 +1962, 7, 128, 118, 30 +1962, 8, 84, 115, 27 +1962, 9, 75, 82, 38 +1962, 10, 52, 76, 48 +1962, 11, 45, 96, 29 +1962, 12, 71, 103, 15 +1963, 1, 75, 84, 7 +1963, 2, 42, 70, 10 +1963, 3, 36, 66, 41 +1963, 4, 51, 110, 45 +1963, 5, 59, 88, 42 +1963, 6, 118, 126, 41 +1963, 7, 123, 114, 61 +1963, 8, 96, 111, 66 +1963, 9, 91, 109, 30 +1963, 10, 93, 66, 15 +1963, 11, 62, 64, 49 +1963, 12, 68, 91, 22 +1964, 1, 43, 101, 12 +1964, 2, 33, 83, 20 +1964, 3, 36, 100, 12 +1964, 4, 81, 93, 55 +1964, 5, 81, 110, 42 +1964, 6, 93, 127, 37 +1964, 7, 122, 103, 74 +1964, 8, 118, 90, 58 +1964, 9, 76, 71, 57 +1964, 10, 84, 103, 36 +1964, 11, 51, 88, 14 +1964, 12, 56, 88, 22 +1965, 1, 38, 80, 28 +1965, 2, 73, 102, 25 +1965, 3, 67, 81, 13 +1965, 4, 84, 67, 40 +1965, 5, 93, 104, 54 +1965, 6, 92, 127, 58 +1965, 7, 123, 90, 40 +1965, 8, 91, 121, 70 +1965, 9, 55, 111, 54 +1965, 10, 54, 104, 16 +1965, 11, 71, 56, 13 +1965, 12, 45, 100, 44 +1966, 1, 41, 86, 42 +1966, 2, 70, 95, 35 +1966, 3, 37, 89, 16 +1966, 4, 50, 101, 55 +1966, 5, 81, 91, 31 +1966, 6, 111, 91, 72 +1966, 7, 110, 92, 59 +1966, 8, 91, 92, 57 +1966, 9, 60, 80, 60 +1966, 10, 70, 80, 41 +1966, 11, 48, 72, 13 +1966, 12, 48, 95, 37 +1967, 1, 74, 68, 16 +1967, 2, 61, 77, 21 +1967, 3, 62, 103, 20 +1967, 4, 72, 72, 22 +1967, 5, 81, 89, 32 +1967, 6, 88, 122, 67 +1967, 7, 90, 125, 50 +1967, 8, 88, 125, 57 +1967, 9, 59, 94, 20 +1967, 10, 94, 83, 27 +1967, 11, 74, 71, 46 +1967, 12, 72, 93, 50 +1968, 1, 58, 104, 50 +1968, 2, 37, 103, 10 +1968, 3, 68, 94, 10 +1968, 4, 94, 75, 44 +1968, 5, 55, 77, 37 +1968, 6, 85, 111, 61 +1968, 7, 87, 99, 53 +1968, 8, 87, 126, 39 +1968, 9, 64, 104, 44 +1968, 10, 64, 93, 49 +1968, 11, 37, 64, 11 +1968, 12, 40, 63, 19 +1969, 1, 56, 78, 48 +1969, 2, 56, 70, 12 +1969, 3, 32, 75, 11 +1969, 4, 52, 65, 29 +1969, 5, 67, 76, 44 +1969, 6, 107, 119, 61 +1969, 7, 115, 91, 50 +1969, 8, 85, 129, 59 +1969, 9, 60, 100, 19 +1969, 10, 93, 108, 31 +1969, 11, 67, 64, 12 +1969, 12, 47, 81, 44 +1970, 1, 42, 96, 23 +1970, 2, 73, 94, 10 +1970, 3, 34, 79, 54 +1970, 4, 59, 81, 16 +1970, 5, 99, 103, 48 +1970, 6, 82, 108, 51 +1970, 7, 99, 108, 39 +1970, 8, 99, 117, 26 +1970, 9, 96, 98, 44 +1970, 10, 92, 86, 19 +1970, 11, 33, 55, 5 +1970, 12, 78, 95, 29 +1971, 1, 56, 66, 15 +1971, 2, 67, 86, 5 +1971, 3, 77, 85, 17 +1971, 4, 64, 99, 48 +1971, 5, 74, 76, 26 +1971, 6, 94, 134, 32 +1971, 7, 110, 114, 43 +1971, 8, 84, 120, 58 +1971, 9, 85, 100, 21 +1971, 10, 87, 77, 61 +1971, 11, 69, 83, 36 +1971, 12, 51, 61, 9 +1972, 1, 62, 104, 9 +1972, 2, 32, 73, 28 +1972, 3, 77, 84, 46 +1972, 4, 82, 71, 36 +1972, 5, 55, 79, 40 +1972, 6, 124, 118, 74 +1972, 7, 85, 124, 39 +1972, 8, 112, 128, 68 +1972, 9, 51, 95, 24 +1972, 10, 73, 87, 26 +1972, 11, 66, 65, 51 +1972, 12, 65, 85, 10 +1973, 1, 68, 62, 51 +1973, 2, 78, 101, 46 +1973, 3, 43, 97, 5 +1973, 4, 81, 95, 52 +1973, 5, 77, 84, 45 +1973, 6, 103, 131, 42 +1973, 7, 105, 92, 55 +1973, 8, 121, 130, 56 +1973, 9, 82, 104, 35 +1973, 10, 98, 107, 58 +1973, 11, 67, 104, 43 +1973, 12, 63, 91, 51 +1974, 1, 65, 104, 25 +1974, 2, 62, 73, 15 +1974, 3, 69, 97, 42 +1974, 4, 89, 113, 39 +1974, 5, 75, 71, 63 +1974, 6, 112, 108, 51 +1974, 7, 116, 99, 52 +1974, 8, 87, 120, 55 +1974, 9, 77, 72, 16 +1974, 10, 97, 86, 27 +1974, 11, 33, 57, 5 +1974, 12, 43, 88, 40 +1975, 1, 54, 59, 53 +1975, 2, 75, 88, 52 +1975, 3, 50, 59, 21 +1975, 4, 55, 87, 53 +1975, 5, 91, 82, 52 +1975, 6, 96, 125, 51 +1975, 7, 116, 110, 25 +1975, 8, 117, 120, 71 +1975, 9, 98, 85, 36 +1975, 10, 82, 101, 32 +1975, 11, 70, 100, 28 +1975, 12, 32, 92, 24 +1976, 1, 33, 85, 42 +1976, 2, 40, 91, 11 +1976, 3, 69, 99, 5 +1976, 4, 68, 76, 33 +1976, 5, 56, 87, 40 +1976, 6, 113, 110, 67 +1976, 7, 80, 108, 63 +1976, 8, 88, 94, 29 +1976, 9, 84, 73, 26 +1976, 10, 95, 75, 45 +1976, 11, 79, 65, 31 +1976, 12, 75, 59, 37 +1977, 1, 30, 96, 48 +1977, 2, 60, 56, 23 +1977, 3, 60, 104, 50 +1977, 4, 77, 112, 57 +1977, 5, 81, 84, 31 +1977, 6, 129, 108, 64 +1977, 7, 88, 96, 59 +1977, 8, 123, 121, 45 +1977, 9, 89, 82, 41 +1977, 10, 62, 81, 17 +1977, 11, 77, 65, 19 +1977, 12, 48, 82, 14 +1978, 1, 57, 67, 49 +1978, 2, 41, 60, 47 +1978, 3, 33, 77, 43 +1978, 4, 83, 99, 30 +1978, 5, 69, 70, 45 +1978, 6, 107, 130, 49 +1978, 7, 98, 117, 44 +1978, 8, 105, 116, 53 +1978, 9, 66, 99, 18 +1978, 10, 69, 86, 28 +1978, 11, 44, 103, 23 +1978, 12, 70, 95, 15 +1979, 1, 33, 63, 15 +1979, 2, 59, 92, 9 +1979, 3, 39, 64, 7 +1979, 4, 59, 103, 61 +1979, 5, 61, 80, 36 +1979, 6, 99, 124, 70 +1979, 7, 121, 134, 50 +1979, 8, 82, 132, 30 +1979, 9, 76, 106, 61 +1979, 10, 69, 82, 56 +1979, 11, 42, 78, 27 +1979, 12, 39, 71, 32 +1980, 1, 60, 91, 33 +1980, 2, 79, 84, 21 +1980, 3, 41, 66, 35 +1980, 4, 93, 89, 60 +1980, 5, 93, 109, 58 +1980, 6, 96, 139, 41 +1980, 7, 114, 94, 45 +1980, 8, 127, 136, 71 +1980, 9, 99, 75, 62 +1980, 10, 97, 97, 45 +1980, 11, 47, 89, 31 +1980, 12, 73, 80, 22 +1981, 1, 69, 89, 52 +1981, 2, 34, 96, 14 +1981, 3, 38, 91, 33 +1981, 4, 82, 85, 34 +1981, 5, 83, 91, 46 +1981, 6, 95, 128, 31 +1981, 7, 98, 95, 63 +1981, 8, 90, 96, 71 +1981, 9, 57, 93, 27 +1981, 10, 52, 91, 28 +1981, 11, 50, 89, 16 +1981, 12, 65, 66, 35 +1982, 1, 49, 69, 24 +1982, 2, 53, 99, 7 +1982, 3, 74, 55, 18 +1982, 4, 81, 82, 27 +1982, 5, 55, 101, 29 +1982, 6, 107, 109, 48 +1982, 7, 117, 114, 61 +1982, 8, 105, 117, 46 +1982, 9, 51, 83, 44 +1982, 10, 74, 97, 17 +1982, 11, 75, 100, 11 +1982, 12, 45, 76, 16 +1983, 1, 52, 91, 5 +1983, 2, 74, 75, 27 +1983, 3, 56, 92, 23 +1983, 4, 97, 89, 59 +1983, 5, 68, 66, 17 +1983, 6, 83, 99, 28 +1983, 7, 119, 105, 29 +1983, 8, 120, 108, 39 +1983, 9, 97, 91, 26 +1983, 10, 75, 97, 15 +1983, 11, 55, 63, 21 +1983, 12, 65, 63, 54 +1984, 1, 68, 73, 11 +1984, 2, 65, 56, 23 +1984, 3, 44, 81, 7 +1984, 4, 55, 111, 55 +1984, 5, 75, 106, 59 +1984, 6, 92, 95, 74 +1984, 7, 115, 92, 62 +1984, 8, 112, 92, 26 +1984, 9, 99, 102, 40 +1984, 10, 58, 86, 51 +1984, 11, 66, 76, 13 +1984, 12, 63, 92, 27 +1985, 1, 63, 69, 39 +1985, 2, 60, 64, 43 +1985, 3, 73, 71, 28 +1985, 4, 76, 98, 45 +1985, 5, 80, 86, 61 +1985, 6, 116, 103, 60 +1985, 7, 122, 127, 41 +1985, 8, 115, 118, 48 +1985, 9, 53, 110, 47 +1985, 10, 70, 114, 44 +1985, 11, 66, 104, 6 +1985, 12, 32, 92, 37 +1986, 1, 68, 72, 25 +1986, 2, 73, 91, 48 +1986, 3, 76, 59, 9 +1986, 4, 69, 93, 36 +1986, 5, 90, 94, 39 +1986, 6, 101, 91, 42 +1986, 7, 110, 126, 32 +1986, 8, 87, 136, 33 +1986, 9, 65, 107, 60 +1986, 10, 88, 65, 54 +1986, 11, 65, 96, 49 +1986, 12, 34, 58, 46 +1987, 1, 63, 90, 30 +1987, 2, 33, 74, 25 +1987, 3, 75, 84, 46 +1987, 4, 86, 67, 21 +1987, 5, 63, 98, 17 +1987, 6, 81, 105, 58 +1987, 7, 106, 120, 64 +1987, 8, 85, 99, 36 +1987, 9, 97, 94, 24 +1987, 10, 61, 67, 53 +1987, 11, 77, 85, 15 +1987, 12, 72, 79, 41 +1988, 1, 72, 66, 44 +1988, 2, 65, 85, 16 +1988, 3, 31, 90, 41 +1988, 4, 78, 99, 37 +1988, 5, 68, 106, 51 +1988, 6, 88, 113, 35 +1988, 7, 121, 105, 42 +1988, 8, 84, 132, 65 +1988, 9, 69, 100, 41 +1988, 10, 83, 101, 15 +1988, 11, 30, 86, 37 +1988, 12, 72, 75, 26 +1989, 1, 74, 100, 10 +1989, 2, 69, 94, 48 +1989, 3, 46, 65, 34 +1989, 4, 50, 85, 59 +1989, 5, 82, 112, 62 +1989, 6, 126, 119, 50 +1989, 7, 124, 125, 43 +1989, 8, 108, 100, 73 +1989, 9, 87, 103, 52 +1989, 10, 86, 69, 40 +1989, 11, 78, 56, 33 +1989, 12, 78, 77, 53 +1990, 1, 67, 65, 7 +1990, 2, 40, 60, 38 +1990, 3, 55, 83, 7 +1990, 4, 50, 70, 54 +1990, 5, 71, 108, 24 +1990, 6, 84, 126, 27 +1990, 7, 117, 109, 71 +1990, 8, 109, 96, 25 +1990, 9, 83, 96, 44 +1990, 10, 92, 114, 38 +1990, 11, 62, 65, 24 +1990, 12, 76, 65, 25 +1991, 1, 37, 69, 48 +1991, 2, 35, 63, 17 +1991, 3, 66, 69, 13 +1991, 4, 78, 80, 39 +1991, 5, 95, 78, 25 +1991, 6, 127, 113, 68 +1991, 7, 88, 102, 40 +1991, 8, 125, 95, 61 +1991, 9, 54, 96, 40 +1991, 10, 85, 109, 53 +1991, 11, 75, 65, 10 +1991, 12, 72, 90, 44 +1992, 1, 33, 64, 52 +1992, 2, 39, 81, 43 +1992, 3, 68, 82, 15 +1992, 4, 72, 94, 32 +1992, 5, 97, 76, 58 +1992, 6, 125, 111, 55 +1992, 7, 127, 129, 29 +1992, 8, 128, 122, 52 +1992, 9, 81, 105, 38 +1992, 10, 99, 107, 42 +1992, 11, 54, 101, 47 +1992, 12, 35, 81, 42 +1993, 1, 53, 69, 40 +1993, 2, 77, 75, 44 +1993, 3, 59, 94, 46 +1993, 4, 90, 110, 40 +1993, 5, 95, 105, 24 +1993, 6, 126, 102, 68 +1993, 7, 98, 139, 66 +1993, 8, 113, 117, 74 +1993, 9, 87, 109, 33 +1993, 10, 96, 73, 63 +1993, 11, 42, 97, 21 +1993, 12, 36, 85, 10 +1994, 1, 36, 88, 31 +1994, 2, 67, 74, 21 +1994, 3, 40, 87, 13 +1994, 4, 95, 109, 37 +1994, 5, 56, 79, 64 +1994, 6, 127, 96, 32 +1994, 7, 87, 108, 70 +1994, 8, 106, 131, 70 +1994, 9, 58, 78, 20 +1994, 10, 58, 67, 23 +1994, 11, 75, 96, 42 +1994, 12, 31, 92, 30 +1995, 1, 62, 95, 27 +1995, 2, 30, 89, 48 +1995, 3, 71, 91, 46 +1995, 4, 56, 105, 20 +1995, 5, 83, 66, 25 +1995, 6, 84, 90, 42 +1995, 7, 128, 128, 30 +1995, 8, 97, 117, 29 +1995, 9, 93, 93, 50 +1995, 10, 83, 89, 50 +1995, 11, 70, 72, 47 +1995, 12, 33, 96, 34 +1996, 1, 38, 93, 19 +1996, 2, 69, 103, 41 +1996, 3, 31, 82, 25 +1996, 4, 96, 67, 41 +1996, 5, 76, 91, 21 +1996, 6, 98, 109, 66 +1996, 7, 90, 110, 42 +1996, 8, 97, 128, 67 +1996, 9, 70, 73, 32 +1996, 10, 65, 65, 58 +1996, 11, 45, 84, 26 +1996, 12, 48, 72, 29 +1997, 1, 42, 77, 17 +1997, 2, 48, 62, 23 +1997, 3, 57, 74, 40 +1997, 4, 69, 106, 51 +1997, 5, 77, 108, 19 +1997, 6, 126, 95, 63 +1997, 7, 121, 110, 56 +1997, 8, 129, 119, 70 +1997, 9, 66, 74, 52 +1997, 10, 72, 68, 64 +1997, 11, 77, 89, 17 +1997, 12, 37, 88, 10 +1998, 1, 49, 93, 35 +1998, 2, 55, 84, 18 +1998, 3, 64, 81, 21 +1998, 4, 75, 106, 44 +1998, 5, 97, 80, 60 +1998, 6, 83, 132, 29 +1998, 7, 99, 119, 62 +1998, 8, 92, 139, 63 +1998, 9, 77, 68, 16 +1998, 10, 66, 78, 29 +1998, 11, 38, 75, 36 +1998, 12, 70, 94, 9 +1999, 1, 69, 66, 42 +1999, 2, 76, 98, 43 +1999, 3, 34, 88, 43 +1999, 4, 69, 97, 29 +1999, 5, 57, 93, 48 +1999, 6, 127, 112, 49 +1999, 7, 125, 133, 46 +1999, 8, 116, 137, 62 +1999, 9, 74, 88, 27 +1999, 10, 93, 82, 64 +1999, 11, 75, 75, 38 +1999, 12, 51, 55, 6 +2000, 1, 55, 94, 42 +2000, 2, 41, 85, 16 +2000, 3, 51, 81, 49 +2000, 4, 86, 93, 26 +2000, 5, 98, 92, 46 +2000, 6, 86, 130, 38 +2000, 7, 108, 107, 37 +2000, 8, 112, 123, 53 +2000, 9, 93, 105, 39 +2000, 10, 54, 67, 51 +2000, 11, 69, 60, 40 +2000, 12, 64, 92, 38 +2001, 1, 35, 58, 15 +2001, 2, 69, 57, 11 +2001, 3, 60, 81, 45 +2001, 4, 68, 98, 27 +2001, 5, 78, 110, 21 +2001, 6, 124, 124, 72 +2001, 7, 94, 102, 45 +2001, 8, 124, 93, 69 +2001, 9, 62, 84, 33 +2001, 10, 56, 71, 35 +2001, 11, 63, 96, 34 +2001, 12, 76, 101, 38 +2002, 1, 46, 83, 34 +2002, 2, 57, 97, 25 +2002, 3, 33, 59, 23 +2002, 4, 67, 76, 61 +2002, 5, 52, 66, 43 +2002, 6, 103, 120, 66 +2002, 7, 96, 118, 48 +2002, 8, 84, 107, 28 +2002, 9, 74, 91, 30 +2002, 10, 62, 109, 21 +2002, 11, 73, 99, 39 +2002, 12, 49, 84, 11 +2003, 1, 51, 55, 54 +2003, 2, 74, 58, 18 +2003, 3, 45, 55, 24 +2003, 4, 56, 108, 52 +2003, 5, 94, 84, 38 +2003, 6, 113, 136, 50 +2003, 7, 112, 94, 43 +2003, 8, 120, 121, 69 +2003, 9, 99, 75, 28 +2003, 10, 60, 65, 25 +2003, 11, 50, 96, 10 +2003, 12, 35, 79, 33 +2004, 1, 44, 84, 53 +2004, 2, 38, 87, 7 +2004, 3, 77, 58, 16 +2004, 4, 84, 91, 17 +2004, 5, 72, 107, 59 +2004, 6, 108, 98, 70 +2004, 7, 97, 92, 26 +2004, 8, 109, 106, 30 +2004, 9, 99, 71, 53 +2004, 10, 95, 108, 22 +2004, 11, 42, 80, 47 +2004, 12, 32, 69, 23 +2005, 1, 72, 98, 13 +2005, 2, 54, 55, 31 +2005, 3, 43, 76, 34 +2005, 4, 92, 90, 40 +2005, 5, 55, 67, 32 +2005, 6, 124, 105, 70 +2005, 7, 126, 115, 30 +2005, 8, 106, 109, 59 +2005, 9, 79, 75, 31 +2005, 10, 86, 100, 16 +2005, 11, 69, 93, 49 +2005, 12, 56, 101, 41 +2006, 1, 70, 78, 6 +2006, 2, 52, 90, 14 +2006, 3, 50, 58, 14 +2006, 4, 85, 101, 21 +2006, 5, 79, 84, 28 +2006, 6, 112, 121, 41 +2006, 7, 97, 104, 33 +2006, 8, 109, 109, 47 +2006, 9, 62, 70, 24 +2006, 10, 60, 99, 58 +2006, 11, 74, 86, 53 +2006, 12, 74, 81, 49 +2007, 1, 49, 74, 9 +2007, 2, 45, 64, 50 +2007, 3, 59, 72, 9 +2007, 4, 74, 90, 63 +2007, 5, 86, 99, 62 +2007, 6, 84, 127, 44 +2007, 7, 101, 97, 26 +2007, 8, 82, 105, 70 +2007, 9, 88, 91, 30 +2007, 10, 53, 84, 51 +2007, 11, 67, 102, 20 +2007, 12, 61, 56, 20 +2008, 1, 38, 66, 5 +2008, 2, 35, 100, 49 +2008, 3, 69, 62, 18 +2008, 4, 69, 90, 17 +2008, 5, 78, 101, 53 +2008, 6, 99, 129, 53 +2008, 7, 89, 112, 64 +2008, 8, 91, 117, 41 +2008, 9, 69, 71, 15 +2008, 10, 73, 95, 41 +2008, 11, 31, 96, 13 +2008, 12, 37, 91, 43 +2009, 1, 55, 78, 48 +2009, 2, 64, 56, 21 +2009, 3, 46, 89, 7 +2009, 4, 61, 81, 27 +2009, 5, 70, 112, 58 +2009, 6, 124, 97, 30 +2009, 7, 91, 92, 46 +2009, 8, 122, 104, 47 +2009, 9, 79, 83, 40 +2009, 10, 68, 73, 16 +2009, 11, 51, 89, 52 +2009, 12, 32, 82, 9 +2010, 1, 39, 56, 8 +2010, 2, 63, 56, 41 +2010, 3, 65, 57, 46 +2010, 4, 98, 84, 32 +2010, 5, 71, 96, 58 +2010, 6, 113, 130, 51 +2010, 7, 105, 115, 28 +2010, 8, 93, 100, 36 +2010, 9, 76, 107, 54 +2010, 10, 64, 84, 31 +2010, 11, 73, 88, 29 +2010, 12, 43, 86, 8 +2011, 1, 76, 55, 29 +2011, 2, 77, 100, 23 +2011, 3, 33, 66, 5 +2011, 4, 52, 102, 48 +2011, 5, 97, 82, 44 +2011, 6, 117, 105, 71 +2011, 7, 92, 127, 50 +2011, 8, 83, 132, 48 +2011, 9, 54, 109, 60 +2011, 10, 53, 68, 48 +2011, 11, 75, 102, 32 +2011, 12, 30, 98, 26 +2012, 1, 44, 79, 34 +2012, 2, 69, 62, 33 +2012, 3, 67, 65, 10 +2012, 4, 70, 70, 49 +2012, 5, 50, 98, 61 +2012, 6, 92, 97, 64 +2012, 7, 91, 95, 51 +2012, 8, 107, 107, 26 +2012, 9, 64, 102, 22 +2012, 10, 75, 76, 31 +2012, 11, 66, 75, 6 +2012, 12, 33, 100, 36 diff --git a/examples/rainfall/doc/src/rainfall.qdoc b/examples/rainfall/doc/src/rainfall.qdoc index b1a4d8e0..bfe7fc36 100644 --- a/examples/rainfall/doc/src/rainfall.qdoc +++ b/examples/rainfall/doc/src/rainfall.qdoc @@ -1,27 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of the QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/rainfall/main.cpp b/examples/rainfall/main.cpp index 47acee0b..2b9b2861 100644 --- a/examples/rainfall/main.cpp +++ b/examples/rainfall/main.cpp @@ -1,327 +1,26 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of the Qt Toolkit. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ -#include "q3dbars.h" -#include "qdataitem.h" - +#include "rainfallchart.h" #include <QGuiApplication> -#include <QFont> -//#include <QDebug> using namespace QtDataVis3D; -class RainfallChart : public QObject -{ -public: - explicit RainfallChart(Q3DBars *rainfall); - ~RainfallChart(); - - void addDataSet(); - void start(); - -private: - Q3DBars *m_chart; - int m_columnCount; - int m_rowCount; -}; - -RainfallChart::RainfallChart(Q3DBars *rainfall) - : m_chart(rainfall), - m_columnCount(12), - m_rowCount(13) -{ - // Set up bar specifications; make the bars as wide as they are deep, - // and add a small space between the bars - m_chart->setBarSpecs(QSizeF(1.0f, 1.0f), QSizeF(0.2f, 0.2f), true); - - // Set up sample space; make it match actual data size - m_chart->setupSampleSpace(m_columnCount, m_rowCount, - QStringLiteral("year"), QStringLiteral("month"), - QStringLiteral("rainfall (in mm)")); - - // Set bar type to cylinder - m_chart->setBarType(Cylinders, false); - - // Set shadows to medium - m_chart->setShadowQuality(ShadowMedium); - - // Set font - m_chart->setFont(QFont("Century Gothic", 40)); - - // Set selection mode to bar and column - //m_chart->setSelectionMode(ModeBarAndColumn); - m_chart->setSelectionMode(ModeZoomColumn); - - // Set theme - m_chart->setTheme(ThemeBlueNcs); - - // Set preset camera position - m_chart->setCameraPreset(PresetIsometricRightHigh); - - // Disable grid - m_chart->setGridEnabled(false); - - // Set window title - m_chart->setWindowTitle(QStringLiteral("Monthly rainfall in Northern Finland (2000-2012)")); -} - -RainfallChart::~RainfallChart() -{ - delete m_chart; -} - -void RainfallChart::start() -{ - addDataSet(); -} - -void RainfallChart::addDataSet() -{ - // Fill in rainfall per month from 2000 to 2012 in Northern Finland (Sodankylä, Utsjoki, Kuusamo) - QVector< QVector<QDataItem*> > data; - QVector<QDataItem*> row; - // TODO: Change this example to load data from file - // 2000 - row.append(new QDataItem(72, "mm")); //January 2000 - row.append(new QDataItem(47, "mm")); //February 2000 - row.append(new QDataItem(37, "mm")); //March 2000 - row.append(new QDataItem(79, "mm")); //April 2000 - row.append(new QDataItem(42, "mm")); //May 2000 - row.append(new QDataItem(73, "mm")); //June 2000 - row.append(new QDataItem(94, "mm")); //July 2000 - row.append(new QDataItem(37, "mm")); //August 2000 - row.append(new QDataItem(17, "mm")); //September 2000 - row.append(new QDataItem(69, "mm")); //October 2000 - row.append(new QDataItem(42, "mm")); //November 2000 - row.append(new QDataItem(42, "mm")); //December 2000 - data.append(row); - row.clear(); - // 2001 - row.append(new QDataItem(25, "mm")); //January 2001 - row.append(new QDataItem(47, "mm")); //February 2001 - row.append(new QDataItem(20, "mm")); //March 2001 - row.append(new QDataItem(70, "mm")); //April 2001 - row.append(new QDataItem(27, "mm")); //May 2001 - row.append(new QDataItem(40, "mm")); //June 2001 - row.append(new QDataItem(123, "mm")); //July 2001 - row.append(new QDataItem(39, "mm")); //August 2001 - row.append(new QDataItem(66, "mm")); //September 2001 - row.append(new QDataItem(55, "mm")); //October 2001 - row.append(new QDataItem(29, "mm")); //November 2001 - row.append(new QDataItem(12, "mm")); //December 2001 - data.append(row); - row.clear(); - // 2002 - row.append(new QDataItem(24, "mm")); //January 2002 - row.append(new QDataItem(45, "mm")); //February 2002 - row.append(new QDataItem(27, "mm")); //March 2002 - row.append(new QDataItem(30, "mm")); //April 2002 - row.append(new QDataItem(16, "mm")); //May 2002 - row.append(new QDataItem(98, "mm")); //June 2002 - row.append(new QDataItem(122, "mm")); //July 2002 - row.append(new QDataItem(20, "mm")); //August 2002 - row.append(new QDataItem(50, "mm")); //September 2002 - row.append(new QDataItem(24, "mm")); //October 2002 - row.append(new QDataItem(22, "mm")); //November 2002 - row.append(new QDataItem(12, "mm")); //December 2002 - data.append(row); - row.clear(); - // 2003 - row.append(new QDataItem(43, "mm")); //January 2003 - row.append(new QDataItem(17, "mm")); //February 2003 - row.append(new QDataItem(26, "mm")); //March 2003 - row.append(new QDataItem(22, "mm")); //April 2003 - row.append(new QDataItem(60, "mm")); //May 2003 - row.append(new QDataItem(14, "mm")); //June 2003 - row.append(new QDataItem(86, "mm")); //July 2003 - row.append(new QDataItem(77, "mm")); //August 2003 - row.append(new QDataItem(69, "mm")); //September 2003 - row.append(new QDataItem(49, "mm")); //October 2003 - row.append(new QDataItem(23, "mm")); //November 2003 - row.append(new QDataItem(44, "mm")); //December 2003 - data.append(row); - row.clear(); - // 2004 - row.append(new QDataItem(15, "mm")); //January 2004 - row.append(new QDataItem(19, "mm")); //February 2004 - row.append(new QDataItem(10, "mm")); //March 2004 - row.append(new QDataItem(11, "mm")); //April 2004 - row.append(new QDataItem(41, "mm")); //May 2004 - row.append(new QDataItem(29, "mm")); //June 2004 - row.append(new QDataItem(49, "mm")); //July 2004 - row.append(new QDataItem(72, "mm")); //August 2004 - row.append(new QDataItem(50, "mm")); //September 2004 - row.append(new QDataItem(18, "mm")); //October 2004 - row.append(new QDataItem(19, "mm")); //November 2004 - row.append(new QDataItem(40, "mm")); //December 2004 - data.append(row); - row.clear(); - // 2005 - row.append(new QDataItem(60, "mm")); //January 2005 - row.append(new QDataItem(24, "mm")); //February 2005 - row.append(new QDataItem(12, "mm")); //March 2005 - row.append(new QDataItem(50, "mm")); //April 2005 - row.append(new QDataItem(88, "mm")); //May 2005 - row.append(new QDataItem(32, "mm")); //June 2005 - row.append(new QDataItem(76, "mm")); //July 2005 - row.append(new QDataItem(55, "mm")); //August 2005 - row.append(new QDataItem(92, "mm")); //September 2005 - row.append(new QDataItem(35, "mm")); //October 2005 - row.append(new QDataItem(105, "mm")); //November 2005 - row.append(new QDataItem(59, "mm")); //December 2005 - data.append(row); - row.clear(); - // 2006 - row.append(new QDataItem(27, "mm")); //January 2006 - row.append(new QDataItem(18, "mm")); //February 2006 - row.append(new QDataItem(17, "mm")); //March 2006 - row.append(new QDataItem(26, "mm")); //April 2006 - row.append(new QDataItem(24, "mm")); //May 2006 - row.append(new QDataItem(18, "mm")); //June 2006 - row.append(new QDataItem(35, "mm")); //July 2006 - row.append(new QDataItem(28, "mm")); //August 2006 - row.append(new QDataItem(80, "mm")); //September 2006 - row.append(new QDataItem(52, "mm")); //October 2006 - row.append(new QDataItem(43, "mm")); //November 2006 - row.append(new QDataItem(44, "mm")); //December 2006 - data.append(row); - row.clear(); - // 2007 - row.append(new QDataItem(41, "mm")); //January 2007 - row.append(new QDataItem(21, "mm")); //February 2007 - row.append(new QDataItem(30, "mm")); //March 2007 - row.append(new QDataItem(20, "mm")); //April 2007 - row.append(new QDataItem(53, "mm")); //May 2007 - row.append(new QDataItem(29, "mm")); //June 2007 - row.append(new QDataItem(139, "mm")); //July 2007 - row.append(new QDataItem(52, "mm")); //August 2007 - row.append(new QDataItem(51, "mm")); //September 2007 - row.append(new QDataItem(24, "mm")); //October 2007 - row.append(new QDataItem(47, "mm")); //November 2007 - row.append(new QDataItem(33, "mm")); //December 2007 - data.append(row); - row.clear(); - // 2008 - row.append(new QDataItem(67, "mm")); //January 2008 - row.append(new QDataItem(19, "mm")); //February 2008 - row.append(new QDataItem(30, "mm")); //March 2008 - row.append(new QDataItem(31, "mm")); //April 2008 - row.append(new QDataItem(29, "mm")); //May 2008 - row.append(new QDataItem(79, "mm")); //June 2008 - row.append(new QDataItem(75, "mm")); //July 2008 - row.append(new QDataItem(99, "mm")); //August 2008 - row.append(new QDataItem(34, "mm")); //September 2008 - row.append(new QDataItem(52, "mm")); //October 2008 - row.append(new QDataItem(60, "mm")); //November 2008 - row.append(new QDataItem(20, "mm")); //December 2008 - data.append(row); - row.clear(); - // 2009 - row.append(new QDataItem(9, "mm")); //January 2009 - row.append(new QDataItem(22, "mm")); //February 2009 - row.append(new QDataItem(11, "mm")); //March 2009 - row.append(new QDataItem(10, "mm")); //April 2009 - row.append(new QDataItem(69, "mm")); //May 2009 - row.append(new QDataItem(30, "mm")); //June 2009 - row.append(new QDataItem(78, "mm")); //July 2009 - row.append(new QDataItem(93, "mm")); //August 2009 - row.append(new QDataItem(70, "mm")); //September 2009 - row.append(new QDataItem(32, "mm")); //October 2009 - row.append(new QDataItem(56, "mm")); //November 2009 - row.append(new QDataItem(23, "mm")); //December 2009 - data.append(row); - row.clear(); - // 2010 - row.append(new QDataItem(12, "mm")); //January 2010 - row.append(new QDataItem(28, "mm")); //February 2010 - row.append(new QDataItem(55, "mm")); //March 2010 - row.append(new QDataItem(20, "mm")); //April 2010 - row.append(new QDataItem(65, "mm")); //May 2010 - row.append(new QDataItem(26, "mm")); //June 2010 - row.append(new QDataItem(134, "mm")); //July 2010 - row.append(new QDataItem(57, "mm")); //August 2010 - row.append(new QDataItem(51, "mm")); //September 2010 - row.append(new QDataItem(53, "mm")); //October 2010 - row.append(new QDataItem(8, "mm")); //November 2010 - row.append(new QDataItem(9, "mm")); //December 2010 - data.append(row); - row.clear(); - // 2011 - row.append(new QDataItem(34, "mm")); //January 2011 - row.append(new QDataItem(20, "mm")); //February 2011 - row.append(new QDataItem(30, "mm")); //March 2011 - row.append(new QDataItem(31, "mm")); //April 2011 - row.append(new QDataItem(42, "mm")); //May 2011 - row.append(new QDataItem(78, "mm")); //June 2011 - row.append(new QDataItem(85, "mm")); //July 2011 - row.append(new QDataItem(33, "mm")); //August 2011 - row.append(new QDataItem(42, "mm")); //September 2011 - row.append(new QDataItem(87, "mm")); //October 2011 - row.append(new QDataItem(41, "mm")); //November 2011 - row.append(new QDataItem(72, "mm")); //December 2011 - data.append(row); - row.clear(); - // 2012 - row.append(new QDataItem(32, "mm")); //January 2012 - row.append(new QDataItem(42, "mm")); //February 2012 - row.append(new QDataItem(30, "mm")); //March 2012 - row.append(new QDataItem(50, "mm")); //April 2012 - row.append(new QDataItem(30, "mm")); //May 2012 - row.append(new QDataItem(70, "mm")); //June 2012 - row.append(new QDataItem(52, "mm")); //July 2012 - row.append(new QDataItem(20, "mm")); //August 2012 - row.append(new QDataItem(99, "mm")); //September 2012 - row.append(new QDataItem(70, "mm")); //October 2012 - row.append(new QDataItem(69, "mm")); //November 2012 - row.append(new QDataItem(49, "mm")); //December 2012 - data.append(row); - row.clear(); - // Set up row and column names - QVector<QString> months; - months << "January" << "February" << "March" << "April" << "May" << "June" << "July" << "August" << "September" << "October" << "November" << "December"; - QVector<QString> years; - years << "2000" << "2001" << "2002" << "2003" << "2004" << "2005" << "2006" << "2007" << "2008" << "2009" << "2010" << "2011" << "2012"; - - m_chart->addDataSet(data, years, months); -} - int main(int argc, char **argv) { QGuiApplication app(argc, argv); diff --git a/examples/rainfall/rainfall.pro b/examples/rainfall/rainfall.pro index 381b3402..af7f963b 100644 --- a/examples/rainfall/rainfall.pro +++ b/examples/rainfall/rainfall.pro @@ -2,7 +2,22 @@ error( "Couldn't find the examples.pri file!" ) } -SOURCES += main.cpp -QT += datavis3d +SOURCES += main.cpp \ + rainfallchart.cpp \ + variantdataset.cpp \ + variantbardataproxy.cpp \ + variantbardatamapping.cpp \ + +HEADERS += \ + rainfallchart.h \ + variantdataset.h \ + variantbardataproxy.h \ + variantbardatamapping.h INSTALLS += target + +RESOURCES += \ + rainfall.qrc + +OTHER_FILES += data/raindata.txt + diff --git a/examples/rainfall/rainfall.qrc b/examples/rainfall/rainfall.qrc new file mode 100644 index 00000000..53cd4915 --- /dev/null +++ b/examples/rainfall/rainfall.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>data/raindata.txt</file> + </qresource> +</RCC> diff --git a/examples/rainfall/rainfallchart.cpp b/examples/rainfall/rainfallchart.cpp new file mode 100644 index 00000000..f7bcd82b --- /dev/null +++ b/examples/rainfall/rainfallchart.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "rainfallchart.h" +#include <QtDataVis3D/qcategoryaxis.h> +#include <QtDataVis3D/qvalueaxis.h> +#include <QGuiApplication> +#include <QFont> +#include <QDebug> +#include <QTextStream> +#include <QFile> + +#define CHANGE_CITY_WITH_TIMER + +using namespace QtDataVis3D; + +RainfallChart::RainfallChart(Q3DBars *rainfall) + : m_chart(rainfall), + m_city(2) +{ + // In data file the months are in numeric format, so create custom list + for (int i = 1; i <= 12; i++) + m_numericMonths << QString::number(i); + + m_columnCount = m_numericMonths.size(); + + m_proxy = new VariantBarDataProxy; + m_proxy->setItemLabelFormat(QStringLiteral(" mm")); + m_chart->setDataProxy(m_proxy); + + updateYearsList(2000, 2012); + + // Set up bar specifications; make the bars as wide as they are deep, + // and add a small space between the bars + m_chart->setBarSpecs(QSizeF(1.0f, 1.0f), QSizeF(0.2f, 0.2f), true); + + // Set axis labels and titles + QStringList months; + months << "January" << "February" << "March" << "April" << "May" << "June" << "July" << "August" << "September" << "October" << "November" << "December"; + m_chart->rowAxis()->setTitle("Year"); + m_chart->columnAxis()->setTitle("Month"); + m_chart->valueAxis()->setTitle(QString("rainfall (in mm) in city %1").arg(m_city - 1)); + m_chart->rowAxis()->setCategoryLabels(m_years); + m_chart->columnAxis()->setCategoryLabels(months); + + // Set bar type to cylinder + m_chart->setBarType(QDataVis::Cylinders, false); + + // Set shadows to medium + m_chart->setShadowQuality(QDataVis::ShadowMedium); + + // Set font + m_chart->setFont(QFont("Century Gothic", 40)); + + // Set selection mode to bar and column + //m_chart->setSelectionMode(ModeItemAndColumn); + m_chart->setSelectionMode(QDataVis::ModeZoomColumn); + + // Set theme + m_chart->setTheme(QDataVis::ThemeBlueNcs); + + // Set preset camera position + m_chart->setCameraPreset(QDataVis::PresetIsometricRightHigh); + + // Disable grid + m_chart->setGridVisible(false); + + // Set window title + m_chart->setWindowTitle(QStringLiteral("Monthly rainfall in various cities")); +} + +RainfallChart::~RainfallChart() +{ + delete m_mapping; + delete m_dataSet; + delete m_chart; +} + +void RainfallChart::start() +{ + addDataSet(); + +#ifdef CHANGE_CITY_WITH_TIMER + connect(&m_timer, &QTimer::timeout, this, &RainfallChart::timeout); + m_timer.start(3000); +#endif +} + +void RainfallChart::timeout() +{ + if (++m_city > 4) + m_city = 2; + + m_proxy->mapping()->setValueIndex(m_city); + m_chart->valueAxis()->setTitle(QString("rainfall (in mm) in city %1").arg(m_city - 1)); +} + +void RainfallChart::updateYearsList(int start, int end) +{ + m_years.clear(); + for (int i = start; i <= end; i++) + m_years << QString::number(i); + + m_rowCount = m_years.size(); + + // Set up sample space; make it match actual resolved data size + m_chart->setupSampleSpace(m_rowCount, m_columnCount); +} + +void RainfallChart::addDataSet() +{ + m_dataSet = new VariantDataSet; + VariantDataItemList *itemList = new VariantDataItemList; + QTextStream stream; + QFile dataFile(":/data/raindata.txt"); + if (dataFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + stream.setDevice(&dataFile); + while (!stream.atEnd()) { + QString line = stream.readLine(); + if (line.startsWith("#")) + continue; + QStringList strList = line.split(",", QString::SkipEmptyParts); + if (strList.size() < 5) { + qWarning() << "Invalid row read from data:" << line; + continue; + } + VariantDataItem *newItem = new VariantDataItem; + for (int i = 0; i < 2; i++) + newItem->append(strList.at(i).trimmed()); + for (int i = 2; i < 5; i++) + newItem->append(strList.at(i).trimmed().toDouble()); + itemList->append(newItem); + } + } else { + qWarning() << "Unable to open data file:" << dataFile.fileName(); + } + + m_dataSet->addItems(itemList); + + m_proxy->setDataSet(m_dataSet); + + m_mapping = new VariantBarDataMapping(0, 1, m_city, m_years, m_numericMonths); + m_proxy->setMapping(m_mapping); +} diff --git a/examples/rainfall/rainfallchart.h b/examples/rainfall/rainfallchart.h new file mode 100644 index 00000000..585f2bd0 --- /dev/null +++ b/examples/rainfall/rainfallchart.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef RAINFALLCHART_H +#define RAINFALLCHART_H + +#include "variantbardataproxy.h" +#include <QtDataVis3D/q3dbars.h> +#include <QTimer> + +using namespace QtDataVis3D; + +class RainfallChart : public QObject +{ + Q_OBJECT +public: + explicit RainfallChart(Q3DBars *rainfall); + ~RainfallChart(); + + void addDataSet(); + void start(); + +public slots: + void timeout(); +private: + + void updateYearsList(int start, int end); + Q3DBars *m_chart; + int m_columnCount; + int m_rowCount; + QStringList m_years; + QStringList m_numericMonths; + QTimer m_timer; + VariantBarDataProxy *m_proxy; + int m_city; + VariantBarDataMapping *m_mapping; + VariantDataSet *m_dataSet; +}; + + +#endif // RAINFALLCHART_H diff --git a/examples/rainfall/variantbardatamapping.cpp b/examples/rainfall/variantbardatamapping.cpp new file mode 100644 index 00000000..288a3b55 --- /dev/null +++ b/examples/rainfall/variantbardatamapping.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "variantbardatamapping.h" + +VariantBarDataMapping::VariantBarDataMapping() + : QObject(0), + m_rowIndex(0), + m_columnIndex(1), + m_valueIndex(2) +{ +} + +VariantBarDataMapping::VariantBarDataMapping(const VariantBarDataMapping &other) + : QObject(0), + m_rowIndex(0), + m_columnIndex(1), + m_valueIndex(2) +{ + operator=(other); +} + +VariantBarDataMapping::VariantBarDataMapping(int rowIndex, int columnIndex, int valueIndex, + const QStringList &rowCategories, + const QStringList &columnCategories) + : QObject(0), + m_rowIndex(0), + m_columnIndex(1), + m_valueIndex(2) +{ + m_rowIndex = rowIndex; + m_columnIndex = columnIndex; + m_valueIndex = valueIndex; + m_rowCategories = rowCategories; + m_columnCategories = columnCategories; +} + +VariantBarDataMapping::~VariantBarDataMapping() +{ +} + +VariantBarDataMapping &VariantBarDataMapping::operator=(const VariantBarDataMapping &other) +{ + m_rowIndex = other.m_rowIndex; + m_columnIndex = other.m_columnIndex; + m_valueIndex = other.m_valueIndex; + m_rowCategories = other.m_rowCategories; + m_columnCategories = other.m_columnCategories; + + return *this; +} + +void VariantBarDataMapping::setRowIndex(int index) +{ + m_rowIndex = index; + emit mappingChanged(); +} + +int VariantBarDataMapping::rowIndex() const +{ + return m_rowIndex; +} + +void VariantBarDataMapping::setColumnIndex(int index) +{ + m_columnIndex = index; + emit mappingChanged(); +} + +int VariantBarDataMapping::columnIndex() const +{ + return m_columnIndex; +} + +void VariantBarDataMapping::setValueIndex(int index) +{ + m_valueIndex = index; + emit mappingChanged(); +} + +int VariantBarDataMapping::valueIndex() const +{ + return m_valueIndex; +} + +void VariantBarDataMapping::setRowCategories(const QStringList &categories) +{ + m_rowCategories = categories; + emit mappingChanged(); +} + +const QStringList &VariantBarDataMapping::rowCategories() const +{ + return m_rowCategories; +} + +void VariantBarDataMapping::setColumnCategories(const QStringList &categories) +{ + m_columnCategories = categories; + emit mappingChanged(); +} + +const QStringList &VariantBarDataMapping::columnCategories() const +{ + return m_columnCategories; +} + +void VariantBarDataMapping::remap(int rowIndex, int columnIndex, int valueIndex, + const QStringList &rowCategories, + const QStringList &columnCategories) +{ + m_rowIndex = rowIndex; + m_columnIndex = columnIndex; + m_valueIndex = valueIndex; + m_rowCategories = rowCategories; + m_columnCategories = columnCategories; + emit mappingChanged(); +} diff --git a/examples/rainfall/variantbardatamapping.h b/examples/rainfall/variantbardatamapping.h new file mode 100644 index 00000000..616ee563 --- /dev/null +++ b/examples/rainfall/variantbardatamapping.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef VARIANTBARDATAMAPPING_H +#define VARIANTBARDATAMAPPING_H + +#include "qdatavis3denums.h" +#include <QStringList> + +using namespace QtDataVis3D; + +class VariantBarDataMapping : public QObject +{ + Q_OBJECT + Q_PROPERTY(int rowIndex READ rowIndex WRITE setRowIndex) + Q_PROPERTY(int columnIndex READ columnIndex WRITE setColumnIndex) + Q_PROPERTY(int valueIndex READ valueIndex WRITE setValueIndex) + Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories) + Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories) +public: + explicit VariantBarDataMapping(); + VariantBarDataMapping(const VariantBarDataMapping &other); + VariantBarDataMapping(int rowIndex, int columnIndex, int valueIndex, + const QStringList &rowCategories, + const QStringList &columnCategories); + virtual ~VariantBarDataMapping(); + + VariantBarDataMapping &operator=(const VariantBarDataMapping &other); + + void setRowIndex(int index); + int rowIndex() const; + void setColumnIndex(int index); + int columnIndex() const; + void setValueIndex(int index); + int valueIndex() const; + + void setRowCategories(const QStringList &categories); + const QStringList &rowCategories() const; + void setColumnCategories(const QStringList &categories); + const QStringList &columnCategories() const; + + void remap(int rowIndex, int columnIndex, int valueIndex, + const QStringList &rowCategories, + const QStringList &columnCategories); +signals: + void mappingChanged(); + +private: + // Indexes of the mapped items in the VariantDataItem + int m_rowIndex; + int m_columnIndex; + int m_valueIndex; + + // For row/column items, sort items into these categories. Other categories are ignored. + QStringList m_rowCategories; + QStringList m_columnCategories; +}; + +#endif diff --git a/examples/rainfall/variantbardataproxy.cpp b/examples/rainfall/variantbardataproxy.cpp new file mode 100644 index 00000000..79b5c67f --- /dev/null +++ b/examples/rainfall/variantbardataproxy.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "variantbardataproxy.h" + +using namespace QtDataVis3D; + +VariantBarDataProxy::VariantBarDataProxy() : + QBarDataProxy() +{ +} + +VariantBarDataProxy::VariantBarDataProxy(VariantDataSet *newSet, + VariantBarDataMapping *mapping) : + QBarDataProxy() +{ + setDataSet(newSet); + setMapping(mapping); +} + +VariantBarDataProxy::~VariantBarDataProxy() +{ +} + +void VariantBarDataProxy::setDataSet(VariantDataSet *newSet) +{ + if (!m_dataSet.isNull()) + QObject::disconnect(m_dataSet.data(), 0, this, 0); + + m_dataSet = newSet; + + if (!m_dataSet.isNull()) { + QObject::connect(m_dataSet.data(), &VariantDataSet::itemsAdded, this, &VariantBarDataProxy::handleItemsAdded); + QObject::connect(m_dataSet.data(), &VariantDataSet::dataCleared, this, &VariantBarDataProxy::handleDataCleared); + } + resolveDataSet(); +} + +VariantDataSet *VariantBarDataProxy::dataSet() +{ + return m_dataSet.data(); +} + +void VariantBarDataProxy::setMapping(VariantBarDataMapping *mapping) +{ + if (!m_mapping.isNull()) + QObject::disconnect(m_mapping.data(), &VariantBarDataMapping::mappingChanged, this, &VariantBarDataProxy::handleMappingChanged); + + m_mapping = mapping; + + if (!m_mapping.isNull()) + QObject::connect(m_mapping.data(), &VariantBarDataMapping::mappingChanged, this, &VariantBarDataProxy::handleMappingChanged); + + resolveDataSet(); +} + +VariantBarDataMapping *VariantBarDataProxy::mapping() +{ + return m_mapping.data(); +} + +void VariantBarDataProxy::handleItemsAdded(int index, int count) +{ + Q_UNUSED(index) + Q_UNUSED(count) + + // Resolve new items + resolveDataSet(); // TODO Resolving entire dataset is inefficient +} + +void VariantBarDataProxy::handleDataCleared() +{ + // Data cleared, reset array + resetArray(0); +} + +void VariantBarDataProxy::handleMappingChanged() +{ + resolveDataSet(); +} + +// Resolve entire dataset into QBarDataArray. +void VariantBarDataProxy::resolveDataSet() +{ + if (m_dataSet.isNull() || m_mapping.isNull() || !m_mapping->rowCategories().size() || !m_mapping->columnCategories().size()) { + resetArray(0); + return; + } + const VariantDataItemList &itemList = m_dataSet->itemList(); + + int rowIndex = m_mapping->rowIndex(); + int columnIndex = m_mapping->columnIndex(); + int valueIndex = m_mapping->valueIndex(); + const QStringList &rowList = m_mapping->rowCategories(); + const QStringList &columnList = m_mapping->columnCategories(); + + // Sort values into rows and columns + typedef QHash<QString, qreal> ColumnValueMap; + QHash <QString, ColumnValueMap> itemValueMap; + foreach (const VariantDataItem *item, itemList) + itemValueMap[item->at(rowIndex).toString()][item->at(columnIndex).toString()] = item->at(valueIndex).toReal(); + + // Create new data array from itemValueMap + QBarDataArray *newProxyArray = new QBarDataArray; + foreach (QString rowKey, rowList) { + QBarDataRow *newProxyRow = new QBarDataRow(columnList.size()); + for (int i = 0; i < columnList.size(); i++) + (*newProxyRow)[i].setValue(itemValueMap[rowKey][columnList.at(i)]); + newProxyArray->append(newProxyRow); + } + + resetArray(newProxyArray); +} diff --git a/examples/rainfall/variantbardataproxy.h b/examples/rainfall/variantbardataproxy.h new file mode 100644 index 00000000..2c80c0b1 --- /dev/null +++ b/examples/rainfall/variantbardataproxy.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef VARIANTBARDATAPROXY_H +#define VARIANTBARDATAPROXY_H + +#include "qbardataproxy.h" +#include "variantdataset.h" +#include "variantbardatamapping.h" +#include <QStringList> +#include <QMap> +#include <QPointer> + +using namespace QtDataVis3D; + +class VariantBarDataProxy : public QBarDataProxy +{ + Q_OBJECT + +public: + explicit VariantBarDataProxy(); + explicit VariantBarDataProxy(VariantDataSet *newSet, VariantBarDataMapping *mapping); + virtual ~VariantBarDataProxy(); + + // Doesn't gain ownership of the dataset, but does connect to it to listen for data changes. + void setDataSet(VariantDataSet *newSet); + VariantDataSet *dataSet(); + + // Map key (row, column, value) to value index in data item (VariantItem). + // Doesn't gain ownership of mapping, but does connect to it to listen for mapping changes. + // Modifying mapping that is set to proxy will trigger dataset re-resolving. + void setMapping(VariantBarDataMapping *mapping); + VariantBarDataMapping *mapping(); + +public slots: + void handleItemsAdded(int index, int count); + void handleDataCleared(); + void handleMappingChanged(); + +private: + void resolveDataSet(); + + QPointer<VariantDataSet> m_dataSet; + QPointer<VariantBarDataMapping> m_mapping; + + Q_DISABLE_COPY(VariantBarDataProxy) + + friend class VariantBarDataProxy; +}; + +#endif diff --git a/examples/rainfall/variantdataset.cpp b/examples/rainfall/variantdataset.cpp new file mode 100644 index 00000000..3fe4fa6b --- /dev/null +++ b/examples/rainfall/variantdataset.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "variantdataset.h" + +VariantDataSet::VariantDataSet() + : QObject(0) +{ +} + +VariantDataSet::~VariantDataSet() +{ + clear(); +} + +void VariantDataSet::clear() +{ + foreach (VariantDataItem *item, m_variantData) { + item->clear(); + delete item; + } + m_variantData.clear(); + emit dataCleared(); +} + +int VariantDataSet::addItem(VariantDataItem *item) +{ + m_variantData.append(item); + int addIndex = m_variantData.size(); + + emit itemsAdded(addIndex, 1); + return addIndex; +} + +int VariantDataSet::addItems(VariantDataItemList *itemList) +{ + int newCount = itemList->size(); + int addIndex = m_variantData.size(); + m_variantData.append(*itemList); + delete itemList; + emit itemsAdded(addIndex, newCount); + return addIndex; +} + +const VariantDataItemList &VariantDataSet::itemList() const +{ + return m_variantData; +} diff --git a/examples/rainfall/variantdataset.h b/examples/rainfall/variantdataset.h new file mode 100644 index 00000000..f3965978 --- /dev/null +++ b/examples/rainfall/variantdataset.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef VARIANTDATASET_H +#define VARIANTDATASET_H + +#include "qdatavis3denums.h" +#include <QScopedPointer> +#include <QVariantList> + +using namespace QtDataVis3D; + +typedef QVariantList VariantDataItem; +typedef QList<VariantDataItem *> VariantDataItemList; + +class VariantDataSet : public QObject +{ + Q_OBJECT + +public: + explicit VariantDataSet(); + ~VariantDataSet(); + + void clear(); + + int addItem(VariantDataItem *item); + int addItems(VariantDataItemList *itemList); + + const VariantDataItemList &itemList() const; + +signals: + void itemsAdded(int index, int count); + void dataCleared(); + +private: + VariantDataItemList m_variantData; + + Q_DISABLE_COPY(VariantDataSet) +}; + +#endif diff --git a/examples/scatterchart/doc/src/scatterchart.qdoc b/examples/scatterchart/doc/src/scatterchart.qdoc new file mode 100644 index 00000000..6e8dcd03 --- /dev/null +++ b/examples/scatterchart/doc/src/scatterchart.qdoc @@ -0,0 +1,29 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +/*! + \example scatterchart + \title Scatter Chart Example + + The scatterchart example shows how to make a simple 3D scatter chart using Q3DScatter and + combining the use of widgets for adjusting several adjustable qualities. + + \image scatterchart-example.png + + TODO +*/ diff --git a/examples/scatterchart/main.cpp b/examples/scatterchart/main.cpp new file mode 100644 index 00000000..ab6eb313 --- /dev/null +++ b/examples/scatterchart/main.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "scatterchart.h" + +#include <QApplication> +#include <QWidget> +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QPushButton> +#include <QCheckBox> +#include <QSlider> +#include <QComboBox> +#include <QFontComboBox> +#include <QLabel> +#include <QScreen> +#include <QFontDatabase> + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + QWidget *widget = new QWidget; + QHBoxLayout *hLayout = new QHBoxLayout(widget); + QVBoxLayout *vLayout = new QVBoxLayout(); + + Q3DScatter *chart = new Q3DScatter(); + QSize screenSize = chart->screen()->size(); + + QWidget *container = QWidget::createWindowContainer(chart); + container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 2)); + container->setMaximumSize(screenSize); + container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + container->setFocusPolicy(Qt::StrongFocus); + + widget->setWindowTitle(QStringLiteral("values of some things in something")); + + hLayout->addWidget(container, 1); + hLayout->addLayout(vLayout); + + QPushButton *themeButton = new QPushButton(widget); + themeButton->setText(QStringLiteral("Change theme")); + + QPushButton *labelButton = new QPushButton(widget); + labelButton->setText(QStringLiteral("Change label style")); + + QPushButton *styleButton = new QPushButton(widget); + styleButton->setText(QStringLiteral("Change item style")); + + QPushButton *cameraButton = new QPushButton(widget); + cameraButton->setText(QStringLiteral("Change camera preset")); + + QPushButton *clearButton = new QPushButton(widget); + clearButton->setText(QStringLiteral("Clear chart")); + + QPushButton *addOneButton = new QPushButton(widget); + addOneButton->setText(QStringLiteral("Add item")); + + QPushButton *addBunchButton = new QPushButton(widget); + addBunchButton->setText(QStringLiteral("Add bunch of items")); + + QPushButton *insertOneButton = new QPushButton(widget); + insertOneButton->setText(QStringLiteral("Insert item")); + + QPushButton *insertBunchButton = new QPushButton(widget); + insertBunchButton->setText(QStringLiteral("Insert bunch of items")); + + QPushButton *changeOneButton = new QPushButton(widget); + changeOneButton->setText(QStringLiteral("Change item")); + + QPushButton *changeBunchButton = new QPushButton(widget); + changeBunchButton->setText(QStringLiteral("Change bunch of items")); + + QPushButton *removeOneButton = new QPushButton(widget); + removeOneButton->setText(QStringLiteral("Remove item")); + + QPushButton *removeBunchButton = new QPushButton(widget); + removeBunchButton->setText(QStringLiteral("Remove bunch of items")); + + QPushButton *startTimerButton = new QPushButton(widget); + startTimerButton->setText(QStringLiteral("Start/stop timer")); + + QCheckBox *backgroundCheckBox = new QCheckBox(widget); + backgroundCheckBox->setText(QStringLiteral("Show background")); + backgroundCheckBox->setChecked(true); + + QCheckBox *gridCheckBox = new QCheckBox(widget); + gridCheckBox->setText(QStringLiteral("Show grid")); + gridCheckBox->setChecked(true); + + QComboBox *shadowQuality = new QComboBox(widget); + shadowQuality->addItem(QStringLiteral("None")); + shadowQuality->addItem(QStringLiteral("Low")); + shadowQuality->addItem(QStringLiteral("Medium")); + shadowQuality->addItem(QStringLiteral("High")); + shadowQuality->setCurrentIndex(1); + + QFontComboBox *fontList = new QFontComboBox(widget); + + QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, widget); + fontSizeSlider->setTickInterval(1); + fontSizeSlider->setMinimum(1); + fontSizeSlider->setValue(30); + fontSizeSlider->setMaximum(200); + + vLayout->addWidget(themeButton, 0, Qt::AlignTop); + vLayout->addWidget(labelButton, 0, Qt::AlignTop); + vLayout->addWidget(styleButton, 0, Qt::AlignTop); + vLayout->addWidget(cameraButton, 0, Qt::AlignTop); + vLayout->addWidget(clearButton, 0, Qt::AlignTop); + vLayout->addWidget(addOneButton, 0, Qt::AlignTop); + vLayout->addWidget(addBunchButton, 0, Qt::AlignTop); + vLayout->addWidget(insertOneButton, 0, Qt::AlignTop); + vLayout->addWidget(insertBunchButton, 0, Qt::AlignTop); + vLayout->addWidget(changeOneButton, 0, Qt::AlignTop); + vLayout->addWidget(changeBunchButton, 0, Qt::AlignTop); + vLayout->addWidget(removeOneButton, 0, Qt::AlignTop); + vLayout->addWidget(removeBunchButton, 0, Qt::AlignTop); + vLayout->addWidget(startTimerButton, 0, Qt::AlignTop); + vLayout->addWidget(backgroundCheckBox); + vLayout->addWidget(gridCheckBox); + vLayout->addWidget(new QLabel(QStringLiteral("Adjust shadow quality"))); + vLayout->addWidget(shadowQuality); + vLayout->addWidget(new QLabel(QStringLiteral("Change font"))); + vLayout->addWidget(fontList); + vLayout->addWidget(new QLabel(QStringLiteral("Adjust font size"))); + vLayout->addWidget(fontSizeSlider, 1, Qt::AlignTop); + + widget->show(); + + ScatterDataModifier *modifier = new ScatterDataModifier(chart); + + QObject::connect(fontSizeSlider, &QSlider::valueChanged, modifier, + &ScatterDataModifier::changeFontSize); + + QObject::connect(styleButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::changeStyle); + QObject::connect(cameraButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::changePresetCamera); + QObject::connect(clearButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::clear); + QObject::connect(addOneButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::addOne); + QObject::connect(addBunchButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::addBunch); + QObject::connect(insertOneButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::insertOne); + QObject::connect(insertBunchButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::insertBunch); + QObject::connect(changeOneButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::changeOne); + QObject::connect(changeBunchButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::changeBunch); + QObject::connect(removeOneButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::removeOne); + QObject::connect(removeBunchButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::removeBunch); + QObject::connect(startTimerButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::startStopTimer); + QObject::connect(themeButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::changeTheme); + QObject::connect(labelButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::changeTransparency); + + QObject::connect(shadowQuality, SIGNAL(currentIndexChanged(int)), modifier, + SLOT(changeShadowQuality(int))); + QObject::connect(modifier, &ScatterDataModifier::shadowQualityChanged, shadowQuality, + &QComboBox::setCurrentIndex); + QObject::connect(chart, &Q3DScatter::shadowQualityChanged, modifier, + &ScatterDataModifier::shadowQualityUpdatedByVisual); + + QObject::connect(fontList, &QFontComboBox::currentFontChanged, modifier, + &ScatterDataModifier::changeFont); + + QObject::connect(backgroundCheckBox, &QCheckBox::stateChanged, modifier, + &ScatterDataModifier::setBackgroundEnabled); + QObject::connect(gridCheckBox, &QCheckBox::stateChanged, modifier, + &ScatterDataModifier::setGridEnabled); + + modifier->start(); + + return app.exec(); +} diff --git a/examples/scatterchart/scatterchart.cpp b/examples/scatterchart/scatterchart.cpp new file mode 100644 index 00000000..ac8676b5 --- /dev/null +++ b/examples/scatterchart/scatterchart.cpp @@ -0,0 +1,325 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "scatterchart.h" +#include <QtDataVis3D/qscatterdataproxy.h> +#include <QtDataVis3D/qvalueaxis.h> +#include <qmath.h> +using namespace QtDataVis3D; + +//#define RANDOM_SCATTER + +const int numberOfItems = 10000; + +ScatterDataModifier::ScatterDataModifier(Q3DScatter *scatter) + : m_chart(scatter), + m_fontSize(30.0f) +{ + m_chart->setFontSize(m_fontSize); + m_chart->setObjectType(QDataVis::Spheres, true); + m_chart->setTheme(QDataVis::ThemeBrownSand); + m_chart->setShadowQuality(QDataVis::ShadowHigh); + + QScatterDataProxy *proxy = new QScatterDataProxy; + m_chart->setDataProxy(proxy); + + connect(&m_timer, &QTimer::timeout, this, &ScatterDataModifier::timeout); +} + +ScatterDataModifier::~ScatterDataModifier() +{ + delete m_chart; +} + +void ScatterDataModifier::start() +{ + addData(); +} + +void ScatterDataModifier::addData() +{ + // Add labels + m_chart->valueAxisX()->setTitle("Somethings"); + m_chart->valueAxisY()->setTitle("Values"); + m_chart->valueAxisZ()->setTitle("Others"); + m_chart->valueAxisX()->setRange(-50.0, 50.0); + m_chart->valueAxisY()->setRange(-1.0, 1.0); + m_chart->valueAxisZ()->setRange(-50.0, 50.0); + + QScatterDataArray *dataArray = new QScatterDataArray; + dataArray->resize(numberOfItems); + QScatterDataItem *ptrToDataArray = &dataArray->first(); + +#if RANDOM_SCATTER + for (int i = 0; i < numberOfItems; i++) { + ptrToDataArray->setPosition(randVector()); + ptrToDataArray++; + } +#else + float limit = qSqrt(numberOfItems) / 2.0f; + for (float i = -limit; i < limit; i++) { + for (float j = -limit; j < limit; j++) { + ptrToDataArray->setPosition(QVector3D(i, qCos(qDegreesToRadians((i * j) / 7.5)), j)); + ptrToDataArray++; + } + } +#endif + + static_cast<QScatterDataProxy *>(m_chart->dataProxy())->resetArray(dataArray); +} + +void ScatterDataModifier::changeStyle() +{ + static int model = 0; + switch (model) { + case 0: + m_chart->setObjectType(QDataVis::Dots, false); + break; + case 1: + m_chart->setObjectType(QDataVis::Dots, true); + break; + case 2: + m_chart->setObjectType(QDataVis::Spheres, false); + break; + case 3: + m_chart->setObjectType(QDataVis::Spheres, true); + break; + } + model++; + if (model > 3) + model = 0; +} + +void ScatterDataModifier::changePresetCamera() +{ + static int preset = QDataVis::PresetFrontLow; + + m_chart->setCameraPreset((QDataVis::CameraPreset)preset); + + if (++preset > QDataVis::PresetDirectlyAboveCCW45) + preset = QDataVis::PresetFrontLow; +} + +void ScatterDataModifier::changeTheme() +{ + static int theme = QDataVis::ThemeSystem; + + m_chart->setTheme((QDataVis::ColorTheme)theme); + + if (++theme > QDataVis::ThemeLight) + theme = QDataVis::ThemeSystem; +} + +void ScatterDataModifier::changeTransparency() +{ + static int transparency = QDataVis::TransparencyNone; + + m_chart->setLabelTransparency((QDataVis::LabelTransparency)transparency); + + if (++transparency > QDataVis::TransparencyNoBackground) + transparency = QDataVis::TransparencyNone; +} + +void ScatterDataModifier::changeFont(const QFont &font) +{ + QFont newFont = font; + newFont.setPointSizeF(m_fontSize); + m_chart->setFont(newFont); +} + +void ScatterDataModifier::changeFontSize(int fontsize) +{ + m_fontSize = fontsize; + m_chart->setFontSize((GLfloat)m_fontSize); +} + +void ScatterDataModifier::shadowQualityUpdatedByVisual(QDataVis::ShadowQuality sq) +{ + int quality = 0; + switch (sq) { + case QDataVis::ShadowLow: + quality = 1; + break; + case QDataVis::ShadowMedium: + quality = 2; + break; + case QDataVis::ShadowHigh: + quality = 3; + break; + } + + // Updates the UI component to show correct shadow quality + emit shadowQualityChanged(quality); +} + +void ScatterDataModifier::clear() +{ + m_chart->dataProxy()->resetArray(0); + qDebug() << m_loopCounter << "Cleared array"; +} + +void ScatterDataModifier::addOne() +{ + QScatterDataItem item(randVector()); + int addIndex = m_chart->dataProxy()->addItem(item); + qDebug() << m_loopCounter << "added one to index:" << addIndex << "array size:" << m_chart->dataProxy()->array()->size(); +} + +void ScatterDataModifier::addBunch() +{ + QScatterDataArray items(100); + for (int i = 0; i < items.size(); i++) + items[i].setPosition(randVector()); + int addIndex = m_chart->dataProxy()->addItems(items); + qDebug() << m_loopCounter << "added bunch to index:" << addIndex << "array size:" << m_chart->dataProxy()->array()->size(); +} + +void ScatterDataModifier::insertOne() +{ + QScatterDataItem item(randVector()); + m_chart->dataProxy()->insertItem(0, item); + qDebug() << m_loopCounter << "Inserted one, array size:" << m_chart->dataProxy()->array()->size(); +} + +void ScatterDataModifier::insertBunch() +{ + QScatterDataArray items(100); + for (int i = 0; i < items.size(); i++) + items[i].setPosition(randVector()); + m_chart->dataProxy()->insertItems(0, items); + qDebug() << m_loopCounter << "Inserted bunch, array size:" << m_chart->dataProxy()->array()->size(); +} + +void ScatterDataModifier::changeOne() +{ + if (m_chart->dataProxy()->array()->size()) { + QScatterDataItem item(randVector()); + m_chart->dataProxy()->setItem(0, item); + qDebug() << m_loopCounter << "Changed one, array size:" << m_chart->dataProxy()->array()->size(); + } +} + +void ScatterDataModifier::changeBunch() +{ + if (m_chart->dataProxy()->array()->size()) { + int amount = qMin(m_chart->dataProxy()->array()->size(), 100); + QScatterDataArray items(amount); + for (int i = 0; i < items.size(); i++) + items[i].setPosition(randVector()); + m_chart->dataProxy()->setItems(0, items); + qDebug() << m_loopCounter << "Changed bunch, array size:" << m_chart->dataProxy()->array()->size(); + } +} + +void ScatterDataModifier::removeOne() +{ + m_chart->dataProxy()->removeItems(0, 1); + qDebug() << m_loopCounter << "Removed one, array size:" << m_chart->dataProxy()->array()->size(); +} + +void ScatterDataModifier::removeBunch() +{ + m_chart->dataProxy()->removeItems(0, 100); + qDebug() << m_loopCounter << "Removed bunch, array size:" << m_chart->dataProxy()->array()->size(); +} + +void ScatterDataModifier::timeout() +{ + int doWhat = rand() % 8; + if (!(rand() % 100)) + doWhat = -1; + + switch (doWhat) { + case 0: + addOne(); + break; + case 1: + addBunch(); + break; + case 2: + insertOne(); + break; + case 3: + insertBunch(); + break; + case 4: + changeOne(); + break; + case 5: + changeBunch(); + break; + case 6: + removeOne(); + break; + case 7: + removeBunch(); + break; + default: + clear(); + break; + } + + m_loopCounter++; +} + +void ScatterDataModifier::startStopTimer() +{ + if (m_timer.isActive()) { + m_timer.stop(); + } else { + clear(); + m_loopCounter = 0; + m_timer.start(0); + } +} + +void ScatterDataModifier::changeShadowQuality(int quality) +{ + QDataVis::ShadowQuality sq = QDataVis::ShadowNone; + switch (quality) { + case 1: + sq = QDataVis::ShadowLow; + break; + case 2: + sq = QDataVis::ShadowMedium; + break; + case 3: + sq = QDataVis::ShadowHigh; + break; + } + m_chart->setShadowQuality(sq); + emit shadowQualityChanged(quality); +} + +void ScatterDataModifier::setBackgroundEnabled(int enabled) +{ + m_chart->setBackgroundVisible((bool)enabled); +} + +void ScatterDataModifier::setGridEnabled(int enabled) +{ + m_chart->setGridVisible((bool)enabled); +} + +QVector3D ScatterDataModifier::randVector() +{ + return QVector3D( + (float)(rand() % 100) / 2.0f - (float)(rand() % 100) / 2.0f, + (float)(rand() % 100) / 100.0f - (float)(rand() % 100) / 100.0f, + (float)(rand() % 100) / 2.0f - (float)(rand() % 100) / 2.0f); +} diff --git a/examples/scatterchart/scatterchart.h b/examples/scatterchart/scatterchart.h new file mode 100644 index 00000000..8500ef29 --- /dev/null +++ b/examples/scatterchart/scatterchart.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef SCATTERDATAMODIFIER_H +#define SCATTERDATAMODIFIER_H + +#include <QtDataVis3D/q3dscatter.h> + +#include <QFont> +#include <QDebug> +#include <QTimer> + +using namespace QtDataVis3D; + +class ScatterDataModifier : public QObject +{ + Q_OBJECT +public: + explicit ScatterDataModifier(Q3DScatter *scatter); + ~ScatterDataModifier(); + + void addData(); + void changeStyle(); + void changePresetCamera(); + void changeTheme(); + void changeTransparency(); + void changeFont(const QFont &font); + void changeFontSize(int fontsize); + void setBackgroundEnabled(int enabled); + void setGridEnabled(int enabled); + void start(); + +public slots: + void changeShadowQuality(int quality); + void shadowQualityUpdatedByVisual(QDataVis::ShadowQuality shadowQuality); + void clear(); + void addOne(); + void addBunch(); + void insertOne(); + void insertBunch(); + void changeOne(); + void changeBunch(); + void removeOne(); + void removeBunch(); + void timeout(); + void startStopTimer(); + +signals: + void shadowQualityChanged(int quality); + +private: + QVector3D randVector(); + Q3DScatter *m_chart; + int m_fontSize; + QTimer m_timer; + int m_loopCounter; +}; + +#endif diff --git a/examples/scatterchart/scatterchart.pro b/examples/scatterchart/scatterchart.pro new file mode 100644 index 00000000..5dee59fd --- /dev/null +++ b/examples/scatterchart/scatterchart.pro @@ -0,0 +1,10 @@ +!include( ../examples.pri ) { + error( "Couldn't find the examples.pri file!" ) +} + +SOURCES += main.cpp scatterchart.cpp +HEADERS += scatterchart.h + +QT += widgets + +INSTALLS += target diff --git a/examples/spectrum/doc/src/spectrum.qdoc b/examples/spectrum/doc/src/spectrum.qdoc index 87028e9c..612c31cd 100644 --- a/examples/spectrum/doc/src/spectrum.qdoc +++ b/examples/spectrum/doc/src/spectrum.qdoc @@ -1,27 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of the QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/spectrum/spectrum.pro b/examples/spectrum/spectrum.pro index eb431bd8..9a8d45ae 100644 --- a/examples/spectrum/spectrum.pro +++ b/examples/spectrum/spectrum.pro @@ -1,7 +1,3 @@ -!include( ../examples.pri ) { - error( "Couldn't find the examples.pri file!" ) -} - qtHaveModule(multimedia) { include(spectrum.pri) diff --git a/examples/spectrum/spectrumapp/engine.cpp b/examples/spectrum/spectrumapp/engine.cpp index 7016af4a..c23a4f78 100644 --- a/examples/spectrum/spectrumapp/engine.cpp +++ b/examples/spectrum/spectrumapp/engine.cpp @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the examples of the Qt Toolkit. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/spectrum/spectrumapp/engine.h b/examples/spectrum/spectrumapp/engine.h index 3d04e13b..cdd8373f 100644 --- a/examples/spectrum/spectrumapp/engine.h +++ b/examples/spectrum/spectrumapp/engine.h @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the examples of QtDataVis3D. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/spectrum/spectrumapp/frequencyspectrum.cpp b/examples/spectrum/spectrumapp/frequencyspectrum.cpp index f4a4167b..013d0454 100644 --- a/examples/spectrum/spectrumapp/frequencyspectrum.cpp +++ b/examples/spectrum/spectrumapp/frequencyspectrum.cpp @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the examples of the Qt Toolkit. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/spectrum/spectrumapp/frequencyspectrum.h b/examples/spectrum/spectrumapp/frequencyspectrum.h index e7ea2e53..fac9a1b7 100644 --- a/examples/spectrum/spectrumapp/frequencyspectrum.h +++ b/examples/spectrum/spectrumapp/frequencyspectrum.h @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the examples of QtDataVis3D. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/spectrum/spectrumapp/main.cpp b/examples/spectrum/spectrumapp/main.cpp index 4296a347..d0333e75 100644 --- a/examples/spectrum/spectrumapp/main.cpp +++ b/examples/spectrum/spectrumapp/main.cpp @@ -1,47 +1,28 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the examples of the Qt Toolkit. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ -#include "q3dbars.h" #include "engine.h" #include "utils.h" +#include <QtDataVis3D/q3dbars.h> +#include <QtDataVis3D/qbardataproxy.h> +#include <QtDataVis3D/qvalueaxis.h> + #include <QGuiApplication> #include <QAudio> #include <QTimer> @@ -85,20 +66,21 @@ MainApp::MainApp(Q3DBars *window) m_lowFreq(SpectrumLowFreq), m_highFreq(SpectrumHighFreq) { - m_chart->setupSampleSpace(SpectrumNumBands, SpectrumNumBands * 2); + m_chart->setupSampleSpace(SpectrumNumBands * 2, SpectrumNumBands); // Disable grid - m_chart->setGridEnabled(false); - // Disable auto-scaling of height by defining tick count and step, even though we don't draw grid - // By setting count to 1 and step to the max we can get, we lock the scale of the bars. - m_chart->setTickCount(1, 1.0f); + m_chart->setGridVisible(false); + // Disable auto-scaling of height by defining explicit range + // By setting count to 0 we avoid getting any grid + m_chart->valueAxis()->setSegmentCount(0); + m_chart->valueAxis()->setRange(0.0, 1.0); // Disable shadows - m_chart->setShadowQuality(ShadowNone); + m_chart->setShadowQuality(QDataVis::ShadowNone); #if USE_CONES // Set bar specifications; make them a bit wider than deep and make them be drawn 75% // inside each other m_chart->setBarSpecs(QSizeF(1.0f, 0.75f), QSizeF(0.2f, -0.75f)); // Set bar type, smooth cones - m_chart->setBarType(Cones, true); + m_chart->setBarType(QDataVis::Cones, true); // Adjust zoom manually; automatic zoom level calculation does not work well with negative // spacings (in setBarSpecs) m_chart->setCameraPosition(10.0f, 5.0f, 70); @@ -106,18 +88,21 @@ MainApp::MainApp(Q3DBars *window) // Set bar specifications; make them twice as wide as they're deep m_chart->setBarSpecs(QSizeF(1.0f, 0.5f), QSizeF(0.0f, 0.0f)); // Set bar type, flat bars - m_chart->setBarType(Bars, false); + m_chart->setBarType(QDataVis::Bars, false); // Adjust camera position m_chart->setCameraPosition(10.0f, 7.5f, 75); #endif // Set color scheme m_chart->setBarColor(QColor(Qt::black), QColor(Qt::red), QColor(Qt::darkYellow)); // Disable selection - m_chart->setSelectionMode(ModeNone); + m_chart->setSelectionMode(QDataVis::ModeNone); QObject::connect(m_engine, &Engine::changedSpectrum, this, &MainApp::spectrumChanged); QObject::connect(m_engine, &Engine::stateChanged, this, &MainApp::stateChanged); m_restartTimer->setSingleShot(true); QObject::connect(m_restartTimer, &QTimer::timeout, this, &MainApp::restart); + + QBarDataProxy *proxy = new QBarDataProxy; + m_chart->setDataProxy(proxy); } MainApp::~MainApp() @@ -141,22 +126,20 @@ void MainApp::spectrumChanged(qint64 position, qint64 length, const FrequencySpe Q_UNUSED(position); Q_UNUSED(length); //qDebug() << "updating bar values" << position << length; - QVector<float> data; + QBarDataRow *data = new QBarDataRow(SpectrumNumBands); for (int bar = 0; bar < SpectrumNumBands; bar++) { // init data set - data.append(0.0f); + (*data)[bar].setValue(qreal(0.0)); } FrequencySpectrum::const_iterator i = spectrum.begin(); const FrequencySpectrum::const_iterator end = spectrum.end(); for ( ; i != end; ++i) { const FrequencySpectrum::Element e = *i; if (e.frequency >= m_lowFreq && e.frequency < m_highFreq) { - data.replace(barIndex(e.frequency) - , qMax(data.at(barIndex(e.frequency)), (float)e.amplitude)); + (*data)[barIndex(e.frequency)].setValue(qMax(data->at(barIndex(e.frequency)).value(), qreal(e.amplitude))); } } - if (data.size() > 0) - m_chart->addDataRow(data); + static_cast<QBarDataProxy *>(m_chart->dataProxy())->insertRow(0, data); } void MainApp::stateChanged(QAudio::Mode mode, QAudio::State state) diff --git a/examples/spectrum/spectrumapp/spectrum.h b/examples/spectrum/spectrumapp/spectrum.h index 244a5892..015989d5 100644 --- a/examples/spectrum/spectrumapp/spectrum.h +++ b/examples/spectrum/spectrumapp/spectrum.h @@ -1,49 +1,27 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the examples of QtDataVis3D. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #ifndef SPECTRUM_H #define SPECTRUM_H -#include <qglobal.h> #include "utils.h" #include "fftreal_wrapper.h" // For FFTLengthPowerOfTwo +#include <qglobal.h> //----------------------------------------------------------------------------- // Constants diff --git a/examples/spectrum/spectrumapp/spectrumanalyser.cpp b/examples/spectrum/spectrumapp/spectrumanalyser.cpp index 518bb6da..4cebfde9 100644 --- a/examples/spectrum/spectrumapp/spectrumanalyser.cpp +++ b/examples/spectrum/spectrumapp/spectrumanalyser.cpp @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the examples of the Qt Toolkit. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/spectrum/spectrumapp/spectrumanalyser.h b/examples/spectrum/spectrumapp/spectrumanalyser.h index 50d4fb66..6d9291ef 100644 --- a/examples/spectrum/spectrumapp/spectrumanalyser.h +++ b/examples/spectrum/spectrumapp/spectrumanalyser.h @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the examples of QtDataVis3D. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/spectrum/spectrumapp/spectrumapp.pro b/examples/spectrum/spectrumapp/spectrumapp.pro index f73336a1..c2455f78 100644 --- a/examples/spectrum/spectrumapp/spectrumapp.pro +++ b/examples/spectrum/spectrumapp/spectrumapp.pro @@ -1,4 +1,10 @@ -include(../spectrum.pri) +!include( ../../examples.pri ) { + error( "Couldn't find the examples.pri file!" ) +} + +!include( ../spectrum.pri ) { + error( "Couldn't find the spectrum.pri file!" ) +} static: error(This application cannot be statically linked to the fftreal library) @@ -6,7 +12,7 @@ TEMPLATE = app TARGET = spectrum -QT += multimedia datavis3d +QT += multimedia SOURCES += main.cpp \ engine.cpp \ diff --git a/examples/spectrum/spectrumapp/utils.cpp b/examples/spectrum/spectrumapp/utils.cpp index 723dd6f6..bad6cc48 100644 --- a/examples/spectrum/spectrumapp/utils.cpp +++ b/examples/spectrum/spectrumapp/utils.cpp @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the examples of the Qt Toolkit. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/spectrum/spectrumapp/utils.h b/examples/spectrum/spectrumapp/utils.h index 62215db5..f0ae5633 100644 --- a/examples/spectrum/spectrumapp/utils.h +++ b/examples/spectrum/spectrumapp/utils.h @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the examples of QtDataVis3D. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/spectrum/spectrumapp/wavfile.cpp b/examples/spectrum/spectrumapp/wavfile.cpp index 0fe8833d..24482507 100644 --- a/examples/spectrum/spectrumapp/wavfile.cpp +++ b/examples/spectrum/spectrumapp/wavfile.cpp @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the examples of QtDataVis3D. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/spectrum/spectrumapp/wavfile.h b/examples/spectrum/spectrumapp/wavfile.h index a9bca7e1..e408911b 100644 --- a/examples/spectrum/spectrumapp/wavfile.h +++ b/examples/spectrum/spectrumapp/wavfile.h @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the examples of QtDataVis3D. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/surfacechart/chartmodifier.cpp b/examples/surfacechart/chartmodifier.cpp new file mode 100644 index 00000000..b685a680 --- /dev/null +++ b/examples/surfacechart/chartmodifier.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "chartmodifier.h" + +#include <qmath.h> + +#include <QDebug> + +QT_DATAVIS3D_USE_NAMESPACE + +ChartModifier::ChartModifier(Q3DSurface *chart) + : m_chart(chart), + m_xCount(10), + m_zCount(10) +{ +} + +ChartModifier::~ChartModifier() +{ + delete m_chart; +} + +void ChartModifier::toggleSmooth(bool enabled) +{ + qDebug() << "ChartModifier::toggleSmooth " << enabled; + m_chart->setSmoothSurface(enabled); +} + +void ChartModifier::toggleSurfaceGrid(bool enable) +{ + qDebug() << "ChartModifier::toggleSurfaceGrid" << enable; + m_chart->setSurfaceGrid(enable); +} + +void ChartModifier::toggleSqrtSin(bool enable) +{ + qreal biggest = -9999.0; + qreal smallest = 9999.0; + QList<qreal> series; + + if (enable) { + qDebug() << "Create Sqrt&Sin surface, (" << m_xCount << ", " << m_zCount << ")"; + + qreal stepZ = 16.0 / qreal(m_zCount); + qreal stepX = 16.0 / qreal(m_xCount); + + for (qreal i = -8.0 + stepZ / 2.0 ; i < 8.0 ; i += stepZ) { + for (qreal j = -8.0 + stepX / 2.0; j < 8.0; j += stepX) { + qreal R = qSqrt(i*i + j*j) + 0.01; + qreal y = (sin(R)/R + 0.24) * 1.61; + series << y; + if (y > biggest) biggest = y; + if (y < smallest) smallest = y; + } + } + + m_chart->setSegmentCount(4, 0.5f); + m_chart->appendSeries(series, m_xCount, m_zCount); + + qDebug() << "biggest = " << biggest << ", smallest = " << smallest; + } else { + qDebug() << "Remove surface"; + } +} + +void ChartModifier::togglePlane(bool enable) +{ + qDebug() << "ChartModifier::togglePlane " << enable; + if (enable) { + QList<qreal> series; + + qreal y = 2.0 / qreal(m_zCount - 1); + for (int i = 0; i < m_zCount; i++) { + for (int j = 0; j < m_xCount; j++) { + series << i * y; + } + } + + m_chart->setSegmentCount(4, 0.5f); + m_chart->appendSeries(series, m_xCount, m_zCount); + } +} + +void ChartModifier::toggleGridSliderLock(bool enable) +{ + m_gridSlidersLocked = enable; + if (m_gridSlidersLocked) { + m_gridSliderZ->setEnabled(false); + m_gridSliderZ->setValue(m_gridSliderX->value()); + } else { + m_gridSliderZ->setEnabled(true); + } +} + +void ChartModifier::adjustXCount(int count) +{ + m_xCount = count; + if (m_gridSlidersLocked) + m_gridSliderZ->setValue(count); + + qDebug() << "X count = " << count; +} + +void ChartModifier::adjustZCount(int count) +{ + m_zCount = count; + + qDebug() << "Z count = " << count; +} + diff --git a/examples/surfacechart/chartmodifier.h b/examples/surfacechart/chartmodifier.h new file mode 100644 index 00000000..3ab2d179 --- /dev/null +++ b/examples/surfacechart/chartmodifier.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef CHARTMODIFIER_H +#define CHARTMODIFIER_H + +#include <QtDataVis3D/Q3DSurface> +#include <QSlider> + +using namespace QtDataVis3D; + +class ChartModifier : public QObject +{ + Q_OBJECT +public: + explicit ChartModifier(Q3DSurface *chart); + ~ChartModifier(); + + void toggleSmooth(bool enabled); + void toggleSurfaceGrid(bool enable); + void toggleSqrtSin(bool enable); + void togglePlane(bool enable); + void toggleGridSliderLock(bool enable); + void setGridSliderX(QSlider *slider) { m_gridSliderX = slider; } + void setGridSliderZ(QSlider *slider) { m_gridSliderZ = slider; } + void adjustXCount(int count); + void adjustZCount(int count); + +private: + Q3DSurface *m_chart; + QSlider *m_gridSliderX; + QSlider *m_gridSliderZ; + bool m_gridSlidersLocked; + int m_xCount; + int m_zCount; +}; + +#endif // CHARTMODIFIER_H diff --git a/examples/surfacechart/main.cpp b/examples/surfacechart/main.cpp new file mode 100644 index 00000000..1297d92b --- /dev/null +++ b/examples/surfacechart/main.cpp @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "chartmodifier.h" + +#include <QApplication> +#include <QApplication> +#include <QWidget> +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QPushButton> +#include <QCheckBox> +#include <QSlider> +#include <QLabel> +#include <QScreen> +#include <QPainter> +#include <QDebug> + +using namespace QtDataVis3D; + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QWidget *widget = new QWidget; + QHBoxLayout *hLayout = new QHBoxLayout(widget); + QVBoxLayout *vLayout = new QVBoxLayout(); + vLayout->setAlignment(Qt::AlignTop); + + Q3DSurface *surfaceChart = new Q3DSurface(); + QSize screenSize = surfaceChart->screen()->size(); + + QWidget *container = QWidget::createWindowContainer(surfaceChart); + container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 2)); + container->setMaximumSize(screenSize); + container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + container->setFocusPolicy(Qt::StrongFocus); + + widget->setWindowTitle(QStringLiteral("Surface tester")); + + hLayout->addWidget(container, 1); + hLayout->addLayout(vLayout); + + QCheckBox *smoothCB = new QCheckBox(widget); + smoothCB->setText(QStringLiteral("Smooth ")); + smoothCB->setChecked(surfaceChart->smoothSurface()); + + QCheckBox *surfaceGridCB = new QCheckBox(widget); + surfaceGridCB->setText(QStringLiteral("Surface Grid")); + surfaceGridCB->setChecked(true); + + QCheckBox *sqrtSinCB = new QCheckBox(widget); + sqrtSinCB->setText(QStringLiteral("Sqrt & Sin")); + sqrtSinCB->setChecked(false); + + QCheckBox *planeCB = new QCheckBox(widget); + planeCB->setText(QStringLiteral("Plane")); + planeCB->setChecked(false); + + QCheckBox *gridSlidersLockCB = new QCheckBox(widget); + gridSlidersLockCB->setText(QStringLiteral("Lock")); + gridSlidersLockCB->setChecked(false); + + QSlider *gridSliderX = new QSlider(Qt::Horizontal, widget); + gridSliderX->setTickInterval(1); + gridSliderX->setMinimum(2); + gridSliderX->setValue(10); + gridSliderX->setMaximum(200); + gridSliderX->setEnabled(true); + QSlider *gridSliderZ = new QSlider(Qt::Horizontal, widget); + gridSliderZ->setTickInterval(1); + gridSliderZ->setMinimum(2); + gridSliderZ->setValue(10); + gridSliderZ->setMaximum(200); + gridSliderZ->setEnabled(true); + + QLinearGradient gr(0, 0, 100, 1); + gr.setColorAt(0.0, Qt::green); + gr.setColorAt(0.5, Qt::yellow); + gr.setColorAt(1.0, Qt::red); + QPixmap pm(100, 24); + QPainter pmp(&pm); + pmp.setBrush(QBrush(gr)); + pmp.setPen(Qt::NoPen); + pmp.drawRect(0, 0, 100, 24); + //pm.save("C:\\Users\\misalmel\\Work\\test.png", "png"); + QPushButton *color = new QPushButton(); + color->setIcon(QIcon(pm)); + color->setIconSize(QSize(100, 24)); + color->setFlat(true); + + // Add controls to the layout + vLayout->addWidget(smoothCB); + vLayout->addWidget(surfaceGridCB); + vLayout->addWidget(new QLabel(QStringLiteral("Select surface sample"))); + vLayout->addWidget(sqrtSinCB); + vLayout->addWidget(planeCB); + vLayout->addWidget(new QLabel(QStringLiteral("Adjust sample count"))); + vLayout->addWidget(gridSlidersLockCB); + vLayout->addWidget(gridSliderX); + vLayout->addWidget(gridSliderZ); + vLayout->addWidget(color); + + widget->show(); + + ChartModifier *modifier = new ChartModifier(surfaceChart); + + // Connect controls to slots on modifier + QObject::connect(smoothCB, &QCheckBox::stateChanged, + modifier, &ChartModifier::toggleSmooth); + QObject::connect(surfaceGridCB, &QCheckBox::stateChanged, + modifier, &ChartModifier::toggleSurfaceGrid); + QObject::connect(sqrtSinCB, &QCheckBox::stateChanged, + modifier, &ChartModifier::toggleSqrtSin); + QObject::connect(planeCB, &QCheckBox::stateChanged, + modifier, &ChartModifier::togglePlane); + QObject::connect(gridSlidersLockCB, &QCheckBox::stateChanged, + modifier, &ChartModifier::toggleGridSliderLock); + QObject::connect(gridSliderX, &QSlider::valueChanged, + modifier, &ChartModifier::adjustXCount); + QObject::connect(gridSliderZ, &QSlider::valueChanged, + modifier, &ChartModifier::adjustZCount); + + modifier->setGridSliderZ(gridSliderZ); + modifier->setGridSliderX(gridSliderX); + modifier->toggleGridSliderLock(gridSlidersLockCB->checkState()); + +// QList<qreal> lowList; +// lowList << 15.0 << 35.0 << 55.0 << 75.0 << 80.0 << 75.0 << 55.0 << 35.0 << 15.0; +// lowList << 65.0 << 105.0 << 135.0 << 155.0 << 190.0 << 155.0 << 135.0 << 105.0 << 65.0; +// lowList << 105.0 << 170.0 << 215.0 << 240.0 << 245.0 << 240.0 << 215.0 << 170.0 << 105.0; +// lowList << 65.0 << 105.0 << 135.0 << 155.0 << 190.0 << 155.0 << 135.0 << 105.0 << 65.0; +// lowList << 15.0 << 35.0 << 55.0 << 75.0 << 80.0 << 75.0 << 55.0 << 35.0 << 16.1; + +// lowList << 15.0 << 65.0 << 105.0 << 65.0 << 15.0; +// lowList << 35.0 << 105.0 << 170.0 << 105.0 << 35; +// lowList << 55.0 << 135.0 << 215.0 << 135.0 << 55; +// lowList << 75.0 << 155.0 << 240.0 << 155.0 << 75; +// lowList << 80.0 << 190.0 << 245.0 << 190.0 << 80; +// lowList << 75.0 << 155.0 << 240.0 << 155.0 << 75.0; +// lowList << 55.0 << 135.0 << 215.0 << 135.0 << 55; +// lowList << 35.0 << 105.0 << 170.0 << 105.0 << 35.0; +// lowList << 15.0 << 65.0 << 105.0 << 65.0 << 16.1; + +// surfaceChart->appendSeries(lowList, 9, 5); + +// QList<qreal> topList; +// topList << 2.1 << 2.2; +// surfaceChart.appendSeries(topList); + +// surfaceChart.resize(screenSize.width() / 1.5, screenSize.height() / 1.5); +// surfaceChart.setPosition(screenSize.width() / 6, screenSize.height() / 6); +// surfaceChart.show(); + + return app.exec(); +} diff --git a/examples/surfacechart/surfacechart.pro b/examples/surfacechart/surfacechart.pro new file mode 100644 index 00000000..79fd967d --- /dev/null +++ b/examples/surfacechart/surfacechart.pro @@ -0,0 +1,11 @@ +!include( ../examples.pri ) { + error( "Couldn't find the examples.pri file!" ) +} + +SOURCES += main.cpp \ + chartmodifier.cpp + +INSTALLS += target + +HEADERS += \ + chartmodifier.h diff --git a/examples/widget/chart.cpp b/examples/widget/chart.cpp index c57a6752..a8c6c14a 100644 --- a/examples/widget/chart.cpp +++ b/examples/widget/chart.cpp @@ -1,46 +1,28 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #include "chart.h" +#include <QtDataVis3D/qcategoryaxis.h> +#include <QtDataVis3D/qvalueaxis.h> +#include <QtDataVis3D/qbardataproxy.h> +#include <QTime> -using namespace QtDataVis3D; +QT_DATAVIS3D_USE_NAMESPACE const QString celsiusString = QString(QChar(0xB0)) + "C"; @@ -56,11 +38,25 @@ ChartModifier::ChartModifier(Q3DBars *barchart) m_barSpacingX(0.1f), m_barSpacingZ(0.1f), m_fontSize(20), - m_ticks(20), - m_tickStep(1), - m_minval(-15.2f) + m_segments(4), + m_subSegments(3), + m_minval(-20.0), // TODO Barchart Y-axis currently only properly supports zero-centered ranges + m_maxval(20.0) { // Don't set any styles or specifications, start from defaults + // Generate generic labels + for (int i = 0; i < 200; i++) { + if (i % 5) + m_genericRowLabels << QString(); + else + m_genericRowLabels << QStringLiteral("Row %1").arg(i); + } + for (int i = 0; i < 200; i++) { + if (i % 5) + m_genericColumnLabels << QString(); + else + m_genericColumnLabels << QStringLiteral("Column %1").arg(i); + } } ChartModifier::~ChartModifier() @@ -81,16 +77,27 @@ void ChartModifier::restart(bool dynamicData) if (m_static) { start(); // Set selection mode to zoom row - m_chart->setSelectionMode(ModeZoomRow); + m_chart->setSelectionMode(QDataVis::ModeZoomRow); m_chart->setFont(QFont("Times Roman", 20)); - m_chart->setTickCount(m_ticks, m_tickStep, m_minval); } else { + m_chart->dataProxy()->resetArray(0); // Set up sample space - m_chart->setupSampleSpace(m_columnCount, m_rowCount); + m_chart->setupSampleSpace(m_rowCount, m_columnCount); // Set selection mode to full - m_chart->setSelectionMode(ModeBarRowAndColumn); - // Reset tick count to default - m_chart->setTickCount(0, 0); + m_chart->setSelectionMode(QDataVis::ModeItemRowAndColumn); + m_chart->valueAxis()->setSegmentCount(m_segments * 2); + m_chart->valueAxis()->setSubSegmentCount(0); + m_chart->valueAxis()->setAutoAdjustRange(true); + + m_chart->rowAxis()->setTitle("Generic Row"); + m_chart->columnAxis()->setTitle("Generic Column"); + m_chart->valueAxis()->setTitle("Generic Value"); + + if (m_chart->rowAxis()->labels().size() < m_rowCount) + m_chart->rowAxis()->setCategoryLabels(m_genericRowLabels.mid(0, m_rowCount)); + + if (m_chart->columnAxis()->labels().size() < m_rowCount) + m_chart->columnAxis()->setCategoryLabels(m_genericColumnLabels.mid(0, m_columnCount)); } } @@ -103,9 +110,9 @@ void ChartModifier::addDataSet() m_chart->setWindowTitle(QStringLiteral("Average temperatures in Oulu, Finland (2006-2012)")); // Set up row and column names - QVector<QString> months; + QStringList months; months << "January" << "February" << "March" << "April" << "May" << "June" << "July" << "August" << "September" << "October" << "November" << "December"; - QVector<QString> years; + QStringList years; years << "2006" << "2007" << "2008" << "2009" << "2010" << "2011" << "2012"; // Set up data @@ -117,46 +124,126 @@ void ChartModifier::addDataSet() {-9.0f, -15.2f, -3.8f, 2.6f, 8.3f, 15.9f, 18.6f, 14.9f, 11.1f, 5.3f, 1.8f, -0.2f}, // 2011 {-8.7f, -11.3f, -2.3f, 0.4f, 7.5f, 12.2f, 16.4f, 14.1f, 9.2f, 3.1f, 0.3f, -12.1f}}; // 2012 - // Create data set - QDataSet *dataSet = new QDataSet(); + // Use default data proxy to feed data directly in expected format + QBarDataProxy *proxy = m_chart->dataProxy(); + proxy->setItemLabelFormat(celsiusString); // Add labels - dataSet->setLabels("Year", "Month", "Average temperature (" + celsiusString + ")", - years, months); + m_chart->rowAxis()->setTitle("Year"); + m_chart->columnAxis()->setTitle("Month"); + m_chart->valueAxis()->setTitle("Average temperature (" + celsiusString + ")"); + m_chart->rowAxis()->setCategoryLabels(years); + m_chart->columnAxis()->setCategoryLabels(months); + m_chart->valueAxis()->setSegmentCount(m_segments); + m_chart->valueAxis()->setSubSegmentCount(m_subSegments); + m_chart->valueAxis()->setRange(m_minval, m_maxval); // Create data rows - QDataRow *dataRow; + QBarDataArray *dataSet = new QBarDataArray; + QBarDataRow *dataRow; + + dataSet->reserve(years.size()); for (int year = 0; year < years.size(); year++) { - dataRow = new QDataRow(years.at(year)); + dataRow = new QBarDataRow(months.size()); // Create data items for (int month = 0; month < months.size(); month++) { // Add data to rows - dataRow->addItem(new QDataItem(temp[year][month], celsiusString)); + (*dataRow)[month].setValue(temp[year][month]); } // Add row to set - dataSet->addRow(dataRow); - // Get next pointer - dataRow++; + dataSet->append(dataRow); } - // Set tick count (4 steps of 5 degrees, with absolute minimum of -16C, even though we don't have quite that low temperatures in the data) - //m_chart->setTickCount(4, 5, -16.0f); - // ..or 20 steps of 1 degree, with absolute minimum of -15.2C - m_chart->setTickCount(m_ticks, m_tickStep, m_minval); - // Set up sample space based on prepared data - m_chart->setupSampleSpace(months.size(), years.size()); + m_chart->setupSampleSpace(years.size(), months.size()); + + // Add data to chart (chart assumes ownership) + proxy->resetArray(dataSet); +} + +void ChartModifier::addRow() +{ + QBarDataRow *dataRow = new QBarDataRow(m_columnCount); + for (float i = 0; i < m_columnCount; i++) { + (*dataRow)[i].setValue(((i + 1) / (float)m_columnCount) * (float)(rand() % 100)); + //(*dataRow)[i].setValue(i + m_chart->dataProxy()->rowCount()); + } + m_chart->dataProxy()->insertRow(0, dataRow); +} + +void ChartModifier::addRows() +{ + QTime timer; + timer.start(); + QBarDataArray dataArray; + for (int i = 0; i < m_rowCount; i++) { + QBarDataRow *dataRow = new QBarDataRow(m_columnCount); + for (int j = 0; j < m_columnCount; j++) + (*dataRow)[j].setValue(qreal(j + i + m_chart->dataProxy()->rowCount())); + dataArray.append(dataRow); + } + m_chart->dataProxy()->insertRows(0, dataArray); + qDebug() << "Added" << m_rowCount << "rows, time:" << timer.elapsed(); +} + +void ChartModifier::changeItem() +{ + // TODO fix to use actual selected item, for now just assume some row/column are selected + int row = qMin(4, (m_chart->dataProxy()->rowCount() - 1)); + if (row >= 0) { + int column = qMin(4, (m_chart->dataProxy()->rowAt(row)->size() - 1)); + if (column >= 0) { + QBarDataItem item(qreal(rand() % 100)); + m_chart->dataProxy()->setItem(row, column, item); + } + } +} + +void ChartModifier::changeRow() +{ + // TODO fix to use actual selected item, for now just assume some is selected + int row = qMin(4, (m_chart->dataProxy()->rowCount() - 1)); + if (row >= 0) { + QBarDataRow *newRow = new QBarDataRow(m_chart->dataProxy()->rowAt(row)->size()); + for (int i = 0; i < newRow->size(); i++) + (*newRow)[i].setValue(qreal(rand() % 100)); + m_chart->dataProxy()->setRow(row, newRow); + } +} + +void ChartModifier::changeRows() +{ + // TODO fix to use actual selected item, for now just assume some is selected + int row = qMin(4, (m_chart->dataProxy()->rowCount() - 1)); + if (row >= 0) { + int startRow = qMax(row - 2, 0); + QBarDataArray newArray; + for (int i = startRow; i <= row; i++ ) { + QBarDataRow *newRow = new QBarDataRow(m_chart->dataProxy()->rowAt(i)->size()); + for (int j = 0; j < newRow->size(); j++) + (*newRow)[j].setValue(qreal(rand() % 100)); + newArray.append(newRow); + } + m_chart->dataProxy()->setRows(startRow, newArray); + } +} - // Add data to chart - m_chart->addDataSet(dataSet); +void ChartModifier::removeRow() +{ + // TODO fix to use actual selected item, for now just assume some is selected + int row = qMin(4, (m_chart->dataProxy()->rowCount() - 1)); + if (row >= 0) + m_chart->dataProxy()->removeRows(row, 1); } -void ChartModifier::addBars() +void ChartModifier::removeRows() { - QVector<float> data; - for (float i = 0; i < m_columnCount; i++) - data.append(((i + 1) / (float)m_columnCount) * (float)(rand() % 100)); - m_chart->addDataRow(data); + // TODO fix to use actual selected item, for now just assume some is selected + int row = qMin(4, (m_chart->dataProxy()->rowCount() - 1)); + if (row >= 0) { + int startRow = qMax(row - 2, 0); + m_chart->dataProxy()->removeRows(startRow, 3); + } } void ChartModifier::changeStyle() @@ -164,34 +251,34 @@ void ChartModifier::changeStyle() static int model = 0; switch (model) { case 0: - m_chart->setBarType(Cylinders, false); + m_chart->setBarType(QDataVis::Cylinders, false); break; case 1: - m_chart->setBarType(Cylinders, true); + m_chart->setBarType(QDataVis::Cylinders, true); break; case 2: - m_chart->setBarType(Cones, false); + m_chart->setBarType(QDataVis::Cones, false); break; case 3: - m_chart->setBarType(Cones, true); + m_chart->setBarType(QDataVis::Cones, true); break; case 4: - m_chart->setBarType(Bars, false); + m_chart->setBarType(QDataVis::Bars, false); break; case 5: - m_chart->setBarType(Bars, true); + m_chart->setBarType(QDataVis::Bars, true); break; case 6: - m_chart->setBarType(Pyramids, false); + m_chart->setBarType(QDataVis::Pyramids, false); break; case 7: - m_chart->setBarType(Pyramids, true); + m_chart->setBarType(QDataVis::Pyramids, true); break; case 8: - m_chart->setBarType(BevelBars, false); + m_chart->setBarType(QDataVis::BevelBars, false); break; case 9: - m_chart->setBarType(BevelBars, true); + m_chart->setBarType(QDataVis::BevelBars, true); break; } model++; @@ -201,42 +288,42 @@ void ChartModifier::changeStyle() void ChartModifier::changePresetCamera() { - static int preset = PresetFrontLow; + static int preset = QDataVis::PresetFrontLow; - m_chart->setCameraPreset((CameraPreset)preset); + m_chart->setCameraPreset((QDataVis::CameraPreset)preset); - if (++preset > PresetDirectlyBelow) - preset = PresetFrontLow; + if (++preset > QDataVis::PresetDirectlyBelow) + preset = QDataVis::PresetFrontLow; } void ChartModifier::changeTheme() { - static int theme = ThemeSystem; + static int theme = QDataVis::ThemeSystem; - m_chart->setTheme((ColorTheme)theme); + m_chart->setTheme((QDataVis::ColorTheme)theme); - if (++theme > ThemeLight) - theme = ThemeSystem; + if (++theme > QDataVis::ThemeLight) + theme = QDataVis::ThemeSystem; } void ChartModifier::changeTransparency() { - static int transparency = TransparencyNone; + static int transparency = QDataVis::TransparencyNone; - m_chart->setLabelTransparency((LabelTransparency)transparency); + m_chart->setLabelTransparency((QDataVis::LabelTransparency)transparency); - if (++transparency > TransparencyNoBackground) - transparency = TransparencyFromTheme; + if (++transparency > QDataVis::TransparencyNoBackground) + transparency = QDataVis::TransparencyFromTheme; } void ChartModifier::changeSelectionMode() { - static int selectionMode = ModeNone; + static int selectionMode = QDataVis::ModeNone; - m_chart->setSelectionMode((SelectionMode)selectionMode); + m_chart->setSelectionMode((QDataVis::SelectionMode)selectionMode); - if (++selectionMode > ModeZoomColumn) - selectionMode = ModeNone; + if (++selectionMode > QDataVis::ModeZoomColumn) + selectionMode = QDataVis::ModeNone; } void ChartModifier::changeFont(const QFont &font) @@ -253,31 +340,51 @@ void ChartModifier::changeFontSize(int fontsize) m_chart->setFontSize((GLfloat)m_fontSize); } +void ChartModifier::shadowQualityUpdatedByVisual(QDataVis::ShadowQuality sq) +{ + int quality = 0; + switch (sq) { + case QDataVis::ShadowLow: + quality = 1; + break; + case QDataVis::ShadowMedium: + quality = 2; + break; + case QDataVis::ShadowHigh: + quality = 3; + break; + } + + // Updates the UI component to show correct shadow quality + emit shadowQualityChanged(quality); +} + void ChartModifier::changeShadowQuality(int quality) { - ShadowQuality sq = ShadowNone; + QDataVis::ShadowQuality sq = QDataVis::ShadowNone; switch (quality) { case 1: - sq = ShadowLow; + sq = QDataVis::ShadowLow; break; case 2: - sq = ShadowMedium; + sq = QDataVis::ShadowMedium; break; case 3: - sq = ShadowHigh; + sq = QDataVis::ShadowHigh; break; } m_chart->setShadowQuality(sq); + emit shadowQualityChanged(quality); } void ChartModifier::setBackgroundEnabled(int enabled) { - m_chart->setBackgroundEnabled((bool)enabled); + m_chart->setBackgroundVisible((bool)enabled); } void ChartModifier::setGridEnabled(int enabled) { - m_chart->setGridEnabled((bool)enabled); + m_chart->setGridVisible((bool)enabled); } void ChartModifier::rotateX(int rotation) @@ -319,11 +426,15 @@ void ChartModifier::setSpacingSpecsZ(int spacing) void ChartModifier::setSampleCountX(int samples) { m_columnCount = samples; - m_chart->setupSampleSpace(m_columnCount, m_rowCount); + m_chart->setupSampleSpace(m_rowCount, m_columnCount); + if (m_chart->columnAxis()->labels().size() < m_columnCount) + m_chart->columnAxis()->setCategoryLabels(m_genericColumnLabels.mid(0, m_columnCount)); } void ChartModifier::setSampleCountZ(int samples) { m_rowCount = samples; - m_chart->setupSampleSpace(m_columnCount, m_rowCount); + m_chart->setupSampleSpace(m_rowCount, m_columnCount); + if (m_chart->rowAxis()->labels().size() < m_rowCount) + m_chart->rowAxis()->setCategoryLabels(m_genericRowLabels.mid(0, m_rowCount)); } diff --git a/examples/widget/chart.h b/examples/widget/chart.h index f4ef747b..67280e13 100644 --- a/examples/widget/chart.h +++ b/examples/widget/chart.h @@ -1,51 +1,29 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #ifndef CHARTMODIFIER_H #define CHARTMODIFIER_H -#include "q3dbars.h" -#include "qdataset.h" +#include <QtDataVis3D/q3dbars.h> #include <QFont> #include <QDebug> +#include <QStringList> using namespace QtDataVis3D; @@ -57,7 +35,13 @@ public: ~ChartModifier(); void addDataSet(); - void addBars(); + void addRow(); + void addRows(); + void changeItem(); + void changeRow(); + void changeRows(); + void removeRow(); + void removeRows(); void changeStyle(); void changePresetCamera(); void changeTheme(); @@ -80,6 +64,10 @@ public: public slots: void changeShadowQuality(int quality); + void shadowQualityUpdatedByVisual(QDataVis::ShadowQuality shadowQuality); + +signals: + void shadowQualityChanged(int quality); private: Q3DBars *m_chart; @@ -93,9 +81,12 @@ private: float m_barSpacingX; float m_barSpacingZ; int m_fontSize; - int m_ticks; - float m_tickStep; - float m_minval; + int m_segments; + int m_subSegments; + qreal m_minval; + qreal m_maxval; + QStringList m_genericRowLabels; + QStringList m_genericColumnLabels; }; #endif diff --git a/examples/widget/doc/src/widget.qdoc b/examples/widget/doc/src/widget.qdoc index d8790a60..6645d356 100644 --- a/examples/widget/doc/src/widget.qdoc +++ b/examples/widget/doc/src/widget.qdoc @@ -1,27 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of the QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/examples/widget/main.cpp b/examples/widget/main.cpp index 1b33b177..47892484 100644 --- a/examples/widget/main.cpp +++ b/examples/widget/main.cpp @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -75,9 +53,33 @@ int main(int argc, char **argv) hLayout->addLayout(vLayout); QPushButton *dataButton = new QPushButton(widget); - dataButton->setText(QStringLiteral("Add a row of random data")); + dataButton->setText(QStringLiteral("Insert a row of data")); dataButton->setEnabled(false); + QPushButton *multiDataButton = new QPushButton(widget); + multiDataButton->setText(QStringLiteral("Insert many rows of data")); + multiDataButton->setEnabled(false); + + QPushButton *changeSingleDataButton = new QPushButton(widget); + changeSingleDataButton->setText(QStringLiteral("Change selected bar value")); + changeSingleDataButton->setEnabled(false); + + QPushButton *changeRowButton = new QPushButton(widget); + changeRowButton->setText(QStringLiteral("Change selected row values")); + changeRowButton->setEnabled(false); + + QPushButton *changeRowsButton = new QPushButton(widget); + changeRowsButton->setText(QStringLiteral("Change three rows from selected")); + changeRowsButton->setEnabled(false); + + QPushButton *removeRowButton = new QPushButton(widget); + removeRowButton->setText(QStringLiteral("Remove selected row")); + removeRowButton->setEnabled(false); + + QPushButton *removeRowsButton = new QPushButton(widget); + removeRowsButton->setText(QStringLiteral("remove three rows from selected")); + removeRowsButton->setEnabled(false); + QPushButton *themeButton = new QPushButton(widget); themeButton->setText(QStringLiteral("Change theme")); @@ -147,13 +149,13 @@ int main(int argc, char **argv) sampleSliderX->setTickInterval(1); sampleSliderX->setMinimum(2); sampleSliderX->setValue(10); - sampleSliderX->setMaximum(100); + sampleSliderX->setMaximum(200); sampleSliderX->setEnabled(false); QSlider *sampleSliderZ = new QSlider(Qt::Horizontal, widget); sampleSliderZ->setTickInterval(1); sampleSliderZ->setMinimum(2); sampleSliderZ->setValue(10); - sampleSliderZ->setMaximum(100); + sampleSliderZ->setMaximum(200); sampleSliderZ->setEnabled(false); QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, widget); @@ -185,6 +187,12 @@ int main(int argc, char **argv) vLayout->addWidget(sampleSliderX, 0, Qt::AlignTop); vLayout->addWidget(sampleSliderZ, 1, Qt::AlignTop); vLayout->addWidget(dataButton, 0, Qt::AlignTop); + vLayout->addWidget(multiDataButton, 0, Qt::AlignTop); + vLayout->addWidget(changeSingleDataButton, 0, Qt::AlignTop); + vLayout->addWidget(changeRowButton, 0, Qt::AlignTop); + vLayout->addWidget(changeRowsButton, 0, Qt::AlignTop); + vLayout->addWidget(removeRowButton, 0, Qt::AlignTop); + vLayout->addWidget(removeRowsButton, 0, Qt::AlignTop); vLayout->addWidget(themeButton, 0, Qt::AlignTop); vLayout->addWidget(labelButton, 0, Qt::AlignTop); vLayout->addWidget(styleButton, 0, Qt::AlignTop); @@ -222,6 +230,10 @@ int main(int argc, char **argv) QObject::connect(shadowQuality, SIGNAL(currentIndexChanged(int)), modifier, SLOT(changeShadowQuality(int))); + QObject::connect(modifier, &ChartModifier::shadowQualityChanged, shadowQuality, + &QComboBox::setCurrentIndex); + QObject::connect(widgetchart, &Q3DBars::shadowQualityChanged, modifier, + &ChartModifier::shadowQualityUpdatedByVisual); QObject::connect(fontSizeSlider, &QSlider::valueChanged, modifier, &ChartModifier::changeFontSize); @@ -232,7 +244,13 @@ int main(int argc, char **argv) QObject::connect(themeButton, &QPushButton::clicked, modifier, &ChartModifier::changeTheme); QObject::connect(labelButton, &QPushButton::clicked, modifier, &ChartModifier::changeTransparency); - QObject::connect(dataButton, &QPushButton::clicked, modifier, &ChartModifier::addBars); + QObject::connect(dataButton, &QPushButton::clicked, modifier, &ChartModifier::addRow); + QObject::connect(multiDataButton, &QPushButton::clicked, modifier, &ChartModifier::addRows); + QObject::connect(changeSingleDataButton, &QPushButton::clicked, modifier, &ChartModifier::changeItem); + QObject::connect(changeRowButton, &QPushButton::clicked, modifier, &ChartModifier::changeRow); + QObject::connect(changeRowsButton, &QPushButton::clicked, modifier, &ChartModifier::changeRows); + QObject::connect(removeRowButton, &QPushButton::clicked, modifier, &ChartModifier::removeRow); + QObject::connect(removeRowsButton, &QPushButton::clicked, modifier, &ChartModifier::removeRows); QObject::connect(selectionButton, &QPushButton::clicked, modifier, &ChartModifier::changeSelectionMode); @@ -255,6 +273,18 @@ int main(int argc, char **argv) QObject::connect(staticCheckBox, &QCheckBox::stateChanged, dataButton, &QPushButton::setEnabled); + QObject::connect(staticCheckBox, &QCheckBox::stateChanged, multiDataButton, + &QPushButton::setEnabled); + QObject::connect(staticCheckBox, &QCheckBox::stateChanged, changeSingleDataButton, + &QPushButton::setEnabled); + QObject::connect(staticCheckBox, &QCheckBox::stateChanged, changeRowButton, + &QPushButton::setEnabled); + QObject::connect(staticCheckBox, &QCheckBox::stateChanged, changeRowsButton, + &QPushButton::setEnabled); + QObject::connect(staticCheckBox, &QCheckBox::stateChanged, removeRowButton, + &QPushButton::setEnabled); + QObject::connect(staticCheckBox, &QCheckBox::stateChanged, removeRowsButton, + &QPushButton::setEnabled); QObject::connect(staticCheckBox, &QCheckBox::stateChanged, sampleSliderX, &QSlider::setEnabled); QObject::connect(staticCheckBox, &QCheckBox::stateChanged, sampleSliderZ, diff --git a/examples/widget/widget.pro b/examples/widget/widget.pro index 1d7e91be..2b4078a4 100644 --- a/examples/widget/widget.pro +++ b/examples/widget/widget.pro @@ -5,6 +5,6 @@ SOURCES += main.cpp chart.cpp HEADERS += chart.h -QT += datavis3d widgets +QT += widgets INSTALLS += target diff --git a/src/datavis3d/Doxyfile b/src/datavis3d/Doxyfile deleted file mode 100644 index e5d78895..00000000 --- a/src/datavis3d/Doxyfile +++ /dev/null @@ -1,1196 +0,0 @@ -# Doxyfile 1.4.5 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = QtDataVis3D - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = internal-docs - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, -# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, -# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, -# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, -# Swedish, and Ukrainian. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an -# explicit @brief command for a brief description. - -JAVADOC_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for Java. -# For instance, namespaces will be presented as packages, qualified scopes -# will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to -# include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = yes - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = YES - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = YES - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = YES - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is YES. - -SHOW_DIRECTORIES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from the -# version control system). Doxygen will invoke the program by executing (via -# popen()) the command <command> <input-file>, where <command> is the value of -# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -# Having it set to not, output a lot of status messages to stdout, we still -# get the warning into the log file -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = NO - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = internal-docs/doxygen.log - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = . ../../tests/auto/xmlpatternsxqts/ ../../tests/auto/xmlpatternsview - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: - -FILE_PATTERNS = *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.dox *.gperf - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -# The Qt API uses qdoc and Doxygen doesn't like its tags, so exclude the q* files. -EXCLUDE_PATTERNS = *.moc *.moc.cpp moc_*.cpp ui_*.h - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = YES - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command <filter> <input-file>, where <filter> -# is the value of the INPUT_FILTER tag, and <input-file> is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = YES - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = YES - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = Q_SLOTS="slots" \ - Q_SIGNALS="signals" - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = YES - -CALLER_GRAPH = NO - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will -# generate a call dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = schema/doc/ - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, which results in a white background. -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). - -DOT_TRANSPARENT = YES - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = YES - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO diff --git a/src/datavis3d/Mainpage.dox b/src/datavis3d/Mainpage.dox deleted file mode 100644 index 973bc46f..00000000 --- a/src/datavis3d/Mainpage.dox +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtXmlPatterns module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt 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. - -/** - * @mainpage QtXmlPatterns -- an implementation of XML technologies - * - * - @ref Patternist_info - * - @ref Patternist_writingDoxygen - * - * @section Patternist_info Overview - * - * This is the internal developer documentation for QtXmlPatterns. Please refer - * to Qt Assistant for usage documentation. - * - * The documentation that you are reading right now, can be generated by - * running <tt>doxygen</tt> in this directory without arguments. The generated - * documentation can subsequently be browsed from - * <tt>internal-docs/html/index.html</tt>. - * - * @subsection Patternist_writingDoxygen Doxygen Conventions - * - * Doxygen conventions, are as follows. - * - * - <tt>@@returns</tt> and <tt>@@param</tt> paragraphs are terminated with a period. - * - When XPath or XQuery expressions/queries appears in the Doxygen comments, wrap them - * in the @c tt HTML tag. - * - Classes and free standing functions should have an <tt>@@author</tt> tag, specifying who - * is the main author of it. - * - No code examples should appear directly in the Doxygen comments, they should be included with - * <tt>@@include</tt> or <tt>@@dontinclude</tt>. - * - The following terms are marked with <tt>@@c</tt> or the @c tt HTML tag: - * - @c NaN - * - @c true and @c false, when referred to as boolean values - * - All QNames and item types. For example, <tt>item\()</tt> and <tt>xs:string</tt>. Remember - * to use the @c tt HTML tag in these cases in order to include non-trivial characters - * such as paranteses - * - @c null - * - @c stderr, @c stdout, and @c stdin - * - * - * The current Doxygen comments does in some cases not adhere to this, but the - * idea is to harmonize in that direction over time. - * - * PatternistSDK, located in the test sources, is documented in the - * PatternistSDK Doxygen module. - * - * @author Frans Englich <frans.englich@nokia.com> - */ diff --git a/src/datavis3d/axis/axis.pri b/src/datavis3d/axis/axis.pri new file mode 100644 index 00000000..7d5a1c6f --- /dev/null +++ b/src/datavis3d/axis/axis.pri @@ -0,0 +1,12 @@ +HEADERS += \ + $$PWD/qabstractaxis.h \ + $$PWD/qabstractaxis_p.h \ + $$PWD/qvalueaxis.h \ + $$PWD/qvalueaxis_p.h \ + $$PWD/qcategoryaxis.h \ + $$PWD/qcategoryaxis_p.h + +SOURCES += \ + $$PWD/qabstractaxis.cpp \ + $$PWD/qvalueaxis.cpp \ + $$PWD/qcategoryaxis.cpp diff --git a/src/datavis3d/axis/qabstractaxis.cpp b/src/datavis3d/axis/qabstractaxis.cpp new file mode 100644 index 00000000..71b9effd --- /dev/null +++ b/src/datavis3d/axis/qabstractaxis.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qabstractaxis.h" +#include "qabstractaxis_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QAbstractAxis::QAbstractAxis(QAbstractAxisPrivate *d) : + QObject(0), + d_ptr(d) +{ +} + +QAbstractAxis::~QAbstractAxis() +{ +} + +QString QAbstractAxis::title() const +{ + return d_ptr->m_title; +} + +QStringList QAbstractAxis::labels() const +{ + return d_ptr->m_labels; +} + +QAbstractAxis::AxisOrientation QAbstractAxis::orientation() const +{ + return d_ptr->m_orientation; +} + +QAbstractAxis::AxisType QAbstractAxis::type() const +{ + return d_ptr->m_type; +} + +void QAbstractAxis::setTitle(QString title) +{ + if (d_ptr->m_title != title) { + d_ptr->m_title = title; + emit titleChanged(title); + } +} + +// QAbstractAxisPrivate + +QAbstractAxisPrivate::QAbstractAxisPrivate(QAbstractAxis *q, QAbstractAxis::AxisType type) + : QObject(0), + q_ptr(q), + m_orientation(QAbstractAxis::AxisOrientationNone), + m_type(type) +{ +} + +QAbstractAxisPrivate::~QAbstractAxisPrivate() +{ +} + +void QAbstractAxisPrivate::setOrientation(QAbstractAxis::AxisOrientation orientation) +{ + if (m_orientation == QAbstractAxis::AxisOrientationNone) + m_orientation = orientation; + else + Q_ASSERT("Attempted to reset axis orientation."); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qabstractaxis.h b/src/datavis3d/axis/qabstractaxis.h new file mode 100644 index 00000000..4bc0ac16 --- /dev/null +++ b/src/datavis3d/axis/qabstractaxis.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QABSTRACTAXIS_H +#define QABSTRACTAXIS_H + +#include <QtDataVis3D/qdatavis3denums.h> +#include <QObject> +#include <QScopedPointer> +#include <QVector> +#include <QStringList> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QAbstractAxisPrivate; + +class QT_DATAVIS3D_EXPORT QAbstractAxis : public QObject +{ + Q_OBJECT + Q_ENUMS(AxisOrientation) + Q_ENUMS(AxisType) + Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) + Q_PROPERTY(QStringList labels READ labels NOTIFY labelsChanged) + Q_PROPERTY(AxisOrientation orientation READ orientation) + Q_PROPERTY(AxisType type READ type) + +public: + enum AxisOrientation { + AxisOrientationNone = 0, + AxisOrientationX = 1, + AxisOrientationY = 2, + AxisOrientationZ = 4 + }; + + enum AxisType { + AxisTypeNone = 0, + AxisTypeCategory = 1, + AxisTypeValue = 2 + //AxisTypeLogValue = 6 // inherits valueaxis (4 + 2) // TODO + }; + +protected: + explicit QAbstractAxis(QAbstractAxisPrivate *d); +public: + virtual ~QAbstractAxis(); + + QString title() const; + QStringList labels() const; + + AxisOrientation orientation() const; + AxisType type() const; + +public slots: + void setTitle(QString title); + +signals: + void titleChanged(QString newTitle); + void labelsChanged(); + +protected: + QScopedPointer<QAbstractAxisPrivate> d_ptr; + +private: + Q_DISABLE_COPY(QAbstractAxis) + + friend class Abstract3DController; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QABSTRACTAXIS_H diff --git a/src/datavis3d/axis/qabstractaxis_p.h b/src/datavis3d/axis/qabstractaxis_p.h new file mode 100644 index 00000000..3866ee75 --- /dev/null +++ b/src/datavis3d/axis/qabstractaxis_p.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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. + +#include "datavis3dglobal_p.h" +#include "qabstractaxis.h" + +#ifndef QABSTRACTAXIS_P_H +#define QABSTRACTAXIS_P_H + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QAbstractAxisPrivate : public QObject +{ + Q_OBJECT +public: + QAbstractAxisPrivate(QAbstractAxis *q, QAbstractAxis::AxisType type); + virtual ~QAbstractAxisPrivate(); + + void setOrientation(QAbstractAxis::AxisOrientation orientation); + +protected: + QAbstractAxis *q_ptr; + + QString m_title; + QStringList m_labels; + QAbstractAxis::AxisOrientation m_orientation; + QAbstractAxis::AxisType m_type; + + friend class QAbstractAxis; + friend class QValueAxis; + friend class QCategoryAxis; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QABSTRACTAXIS_P_H diff --git a/src/datavis3d/axis/qcategoryaxis.cpp b/src/datavis3d/axis/qcategoryaxis.cpp new file mode 100644 index 00000000..c20eb80f --- /dev/null +++ b/src/datavis3d/axis/qcategoryaxis.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qcategoryaxis.h" +#include "qcategoryaxis_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QCategoryAxis::QCategoryAxis() : + QAbstractAxis(new QCategoryAxisPrivate(this)) +{ +} + +QCategoryAxis::~QCategoryAxis() +{ +} + +QStringList QCategoryAxis::categoryLabels() const +{ + return labels(); +} + +void QCategoryAxis::setCategoryLabels(const QStringList &labels) +{ + if (d_ptr->m_labels != labels) { + d_ptr->m_labels = labels; + emit labelsChanged(); + } +} + +QCategoryAxisPrivate *QCategoryAxis::dptr() +{ + return static_cast<QCategoryAxisPrivate *>(d_ptr.data()); +} + +QCategoryAxisPrivate::QCategoryAxisPrivate(QCategoryAxis *q) + : QAbstractAxisPrivate(q, QAbstractAxis::AxisTypeCategory) +{ +} + +QCategoryAxisPrivate::~QCategoryAxisPrivate() +{ +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qcategoryaxis.h b/src/datavis3d/axis/qcategoryaxis.h new file mode 100644 index 00000000..8d1e3f57 --- /dev/null +++ b/src/datavis3d/axis/qcategoryaxis.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QCATEGORYAXIS_H +#define QCATEGORYAXIS_H + +#include <QtDataVis3D/qabstractaxis.h> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QCategoryAxisPrivate; + +class QT_DATAVIS3D_EXPORT QCategoryAxis : public QAbstractAxis +{ + Q_OBJECT + // Note: categoryLabels actually reads/writes the labels property in abstract axis, + // which is read only there. Since subclass cannot have property with same name, + // this partially duplicate property is necessary. + Q_PROPERTY(QStringList categoryLabels READ categoryLabels WRITE setCategoryLabels) +public: + explicit QCategoryAxis(); + ~QCategoryAxis(); + + QStringList categoryLabels() const; + +public slots: + void setCategoryLabels(const QStringList &labels); + +protected: + QCategoryAxisPrivate *dptr(); + +private: + + Q_DISABLE_COPY(QCategoryAxis) +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QCATEGORYAXIS_H diff --git a/src/datavis3d/axis/qcategoryaxis_p.h b/src/datavis3d/axis/qcategoryaxis_p.h new file mode 100644 index 00000000..3ca79c64 --- /dev/null +++ b/src/datavis3d/axis/qcategoryaxis_p.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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. + +#include "qcategoryaxis.h" +#include "qabstractaxis_p.h" +#include "qbardataitem.h" + +#ifndef QCATEGORYAXIS_P_H +#define QCATEGORYAXIS_P_H + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QCategoryAxisPrivate : public QAbstractAxisPrivate +{ + Q_OBJECT + +public: + QCategoryAxisPrivate(QCategoryAxis *q); + virtual ~QCategoryAxisPrivate(); +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QCATEGORYAXIS_P_H diff --git a/src/datavis3d/axis/qvalueaxis.cpp b/src/datavis3d/axis/qvalueaxis.cpp new file mode 100644 index 00000000..cee8a5c7 --- /dev/null +++ b/src/datavis3d/axis/qvalueaxis.cpp @@ -0,0 +1,235 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qvalueaxis.h" +#include "qvalueaxis_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QValueAxis::QValueAxis() : + QAbstractAxis(new QValueAxisPrivate(this)) +{ +} + +QValueAxis::~QValueAxis() +{ +} + +void QValueAxis::setRange(qreal min, qreal max) +{ + dptr()->setRange(min, max); + setAutoAdjustRange(false); +} + +void QValueAxis::setMin(qreal min) +{ + dptr()->setMin(min); + setAutoAdjustRange(false); +} + +void QValueAxis::setMax(qreal max) +{ + dptr()->setMax(max); + setAutoAdjustRange(false); +} + +qreal QValueAxis::min() const +{ + return dptrc()->m_min; +} + +qreal QValueAxis::max() const +{ + return dptrc()->m_max; +} + +void QValueAxis::setSegmentCount(int count) +{ + if (count <= 0) { + qWarning() << "Warning: Illegal segment count automatically adjusted to a legal one:" + << count << "-> 1"; + count = 1; + } + if (dptr()->m_segmentCount != count){ + dptr()->m_segmentCount = count; + dptr()->recreateLabels(); + emit segmentCountChanged(count); + } +} + +int QValueAxis::segmentCount() const +{ + return dptrc()->m_segmentCount; +} + +void QValueAxis::setSubSegmentCount(int count) +{ + if (count <= 0) { + qWarning() << "Warning: Illegal subsegment count automatically adjusted to a legal one:" + << count << "-> 1"; + count = 1; + } + if (dptr()->m_subSegmentCount != count) { + dptr()->m_subSegmentCount = count; + emit subSegmentCountChanged(count); + } +} + +int QValueAxis::subSegmentCount() const +{ + return dptrc()->m_subSegmentCount; +} + +void QValueAxis::setAutoAdjustRange(bool autoAdjust) +{ + if (dptr()->m_autoAdjust != autoAdjust) { + dptr()->m_autoAdjust = autoAdjust; + emit autoAdjustRangeChanged(autoAdjust); + } +} + +bool QValueAxis::isAutoAdjustRange() const +{ + return dptrc()->m_autoAdjust; +} + +void QValueAxis::setLabelFormat(const QString &format) +{ + if (dptr()->m_labelFormat != format) { + dptr()->m_labelFormat = format; + dptr()->recreateLabels(); + emit labelFormatChanged(format); + } +} + +QString QValueAxis::labelFormat() const +{ + return dptrc()->m_labelFormat; +} + +QValueAxisPrivate *QValueAxis::dptr() +{ + return static_cast<QValueAxisPrivate *>(d_ptr.data()); +} + +const QValueAxisPrivate *QValueAxis::dptrc() const +{ + return static_cast<const QValueAxisPrivate *>(d_ptr.data()); +} + +QValueAxisPrivate::QValueAxisPrivate(QValueAxis *q) + : QAbstractAxisPrivate(q, QAbstractAxis::AxisTypeValue), + m_min(0.0), + m_max(10.0), + m_segmentCount(5), + m_subSegmentCount(1), + m_autoAdjust(true) +{ +} + +QValueAxisPrivate::~QValueAxisPrivate() +{ +} + +void QValueAxisPrivate::setRange(qreal min, qreal max) +{ + // If min >= max, we adjust ranges so that + // m_max becomes (min + 1.0) + // as axes need some kind of valid range. + // TODO: Make "reverse" axes work (i.e. min > max) + bool dirty = false; + if (m_min != min) { + m_min = min; + dirty = true; + } + if (m_max != max) { + if (min >= max) { + m_max = min + 1.0; + qWarning() << "Warning: Tried to set invalid range for value axis." + " Range automatically adjusted to a valid one:" + << min << "-" << max << "-->" << m_min << "-" << m_max; + } else { + m_max = max; + } + dirty = true; + } + if (dirty) { + recreateLabels(); + emit qptr()->rangeChanged(min, max); + } +} + +void QValueAxisPrivate::setMin(qreal min) +{ + if (m_min != min) { + if (min >= m_max) { + qreal oldMax = m_max; + m_max = min + 1.0; + qWarning() << "Warning: Tried to set minimum to equal or larger than maximum for" + " value axis. Maximum automatically adjusted to a valid one:" + << oldMax << "-->" << m_max; + } + m_min = min; + recreateLabels(); + emit qptr()->rangeChanged(m_min, m_max); + } +} + +void QValueAxisPrivate::setMax(qreal max) +{ + if (m_max != max) { + if (max <= m_min) { + qreal oldMin = m_min; + m_min = max - 1.0; + qWarning() << "Warning: Tried to set maximum to equal or smaller than minimum for" + " value axis. Minimum automatically adjusted to a valid one:" + << oldMin << "-->" << m_min; + } + m_max = max; + recreateLabels(); + emit qptr()->rangeChanged(m_min, m_max); + } +} + +void QValueAxisPrivate::recreateLabels() +{ + QStringList newLabels; + newLabels.reserve(m_segmentCount + 1); + + // First label is at axis min, which is an extra segment + qreal segmentStep = (m_max - m_min) / m_segmentCount; + + for (int i = 0; i < m_segmentCount; i++) { + // TODO Actually do proper formatting + newLabels.append(QString::number(m_min + (segmentStep * i))); + } + // Ensure max label doesn't suffer from any rounding errors + newLabels.append(QString::number(m_max)); + + if (m_labels != newLabels) { + m_labels = newLabels; + emit q_ptr->labelsChanged(); + } +} + +QValueAxis *QValueAxisPrivate::qptr() +{ + return static_cast<QValueAxis *>(q_ptr); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qvalueaxis.h b/src/datavis3d/axis/qvalueaxis.h new file mode 100644 index 00000000..c9658f37 --- /dev/null +++ b/src/datavis3d/axis/qvalueaxis.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QVALUEAXIS_H +#define QVALUEAXIS_H + +#include <QtDataVis3D/qabstractaxis.h> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QValueAxisPrivate; + +class QT_DATAVIS3D_EXPORT QValueAxis : public QAbstractAxis +{ + Q_OBJECT + Q_PROPERTY(qreal min READ min WRITE setMin NOTIFY rangeChanged) + Q_PROPERTY(qreal max READ max WRITE setMax NOTIFY rangeChanged) + Q_PROPERTY(int segmentCount READ segmentCount WRITE setSegmentCount NOTIFY segmentCountChanged) + Q_PROPERTY(int subSegmentCount READ subSegmentCount WRITE setSubSegmentCount NOTIFY subSegmentCountChanged) + Q_PROPERTY(bool autoAdjustRange READ isAutoAdjustRange WRITE setAutoAdjustRange NOTIFY autoAdjustRangeChanged) + Q_PROPERTY(QString labelFormat READ labelFormat WRITE setLabelFormat NOTIFY labelFormatChanged) + +public: + explicit QValueAxis(); + ~QValueAxis(); + + qreal min() const; + qreal max() const; + int segmentCount() const; + int subSegmentCount() const; + bool isAutoAdjustRange() const; + QString labelFormat() const; + +public slots: + void setRange(qreal min, qreal max); + void setMin(qreal min); + void setMax(qreal max); + void setSegmentCount(int count); + void setSubSegmentCount(int count); + void setAutoAdjustRange(bool autoAdjust); + void setLabelFormat(const QString &format); + +signals: + void rangeChanged(qreal min, qreal max); + void segmentCountChanged(int count); + void subSegmentCountChanged(int count); + void autoAdjustRangeChanged(bool autoAdjust); + void labelFormatChanged(QString format); + +protected: + QValueAxisPrivate *dptr(); + const QValueAxisPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QValueAxis) + friend class Bars3dController; + friend class Scatter3DController; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QVALUEAXIS_H diff --git a/src/datavis3d/axis/qvalueaxis_p.h b/src/datavis3d/axis/qvalueaxis_p.h new file mode 100644 index 00000000..f730d0c0 --- /dev/null +++ b/src/datavis3d/axis/qvalueaxis_p.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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. + +#include "qvalueaxis.h" +#include "qabstractaxis_p.h" + +#ifndef QVALUEAXIS_P_H +#define QVALUEAXIS_P_H + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QValueAxisPrivate : public QAbstractAxisPrivate +{ + Q_OBJECT + +public: + QValueAxisPrivate(QValueAxis *q); + virtual ~QValueAxisPrivate(); + + void setRange(qreal min, qreal max); + void setMin(qreal min); + void setMax (qreal max); + +protected: + void recreateLabels(); + + qreal m_min; + qreal m_max; + int m_segmentCount; + int m_subSegmentCount; + bool m_autoAdjust; + QString m_labelFormat; + +private: + QValueAxis *qptr(); + + friend class QValueAxis; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QVALUEAXIS_P_H diff --git a/src/datavis3d/common.pri b/src/datavis3d/common.pri index 8532fc77..57948697 100644 --- a/src/datavis3d/common.pri +++ b/src/datavis3d/common.pri @@ -3,5 +3,6 @@ INCLUDEPATH += $$PWD/engine \ $$PWD/global \ - $$PWD/utils - + $$PWD/utils \ + $$PWD/axis \ + $$PWD/data diff --git a/src/datavis3d/data/abstractrenderitem.cpp b/src/datavis3d/data/abstractrenderitem.cpp new file mode 100644 index 00000000..004fb598 --- /dev/null +++ b/src/datavis3d/data/abstractrenderitem.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "abstractrenderitem_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +AbstractRenderItem::AbstractRenderItem() + : m_labelItem(0), + m_selectionLabel(0) +{ +} + +AbstractRenderItem::~AbstractRenderItem() +{ + delete m_labelItem; + delete m_selectionLabel; +} + +LabelItem &AbstractRenderItem::labelItem() +{ + if (!m_labelItem) + m_labelItem = new LabelItem; + return *m_labelItem; +} + +LabelItem &AbstractRenderItem::selectionLabel() +{ + if (!m_selectionLabel) + m_selectionLabel = new LabelItem; + return *m_selectionLabel; +} + +QString &AbstractRenderItem::label() +{ + if (m_label.isNull()) + formatLabel(); + return m_label; +} + +void AbstractRenderItem::setLabel(const QString &label) +{ + if (m_labelItem) + m_labelItem->clear(); + if (m_selectionLabel) + m_selectionLabel->clear(); + m_label = label; +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/abstractrenderitem_p.h b/src/datavis3d/data/abstractrenderitem_p.h new file mode 100644 index 00000000..4bf4df71 --- /dev/null +++ b/src/datavis3d/data/abstractrenderitem_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 ABSTRACTRENDERITEM_P_H +#define ABSTRACTRENDERITEM_P_H + +#include "datavis3dglobal_p.h" +#include "labelitem_p.h" + +#include <QOpenGLFunctions> +#include <QString> +#include <QVector3D> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class AbstractRenderItem +{ +public: + AbstractRenderItem(); + virtual ~AbstractRenderItem(); + + // Position in 3D scene + inline void setTranslation(const QVector3D &translation) { m_translation = translation; } + inline const QVector3D &translation() const {return m_translation; } + + // Label item for formatted label + LabelItem &labelItem(); + + // Selection label item (containing special selection texture, if mode is activated) + LabelItem &selectionLabel(); + + // Formatted label for item. + void setLabel(const QString &label); + QString &label(); // Formats label if not previously formatted + +protected: + virtual void formatLabel() = 0; + + QString m_label; + QVector3D m_translation; + LabelItem *m_labelItem; + LabelItem *m_selectionLabel; + + friend class QAbstractDataItem; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/barrenderitem.cpp b/src/datavis3d/data/barrenderitem.cpp new file mode 100644 index 00000000..db377aa3 --- /dev/null +++ b/src/datavis3d/data/barrenderitem.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "barrenderitem_p.h" +#include "bars3drenderer_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +BarRenderItem::BarRenderItem() + : AbstractRenderItem(), + m_renderer(0), + m_value(0) +{ +} + +BarRenderItem::~BarRenderItem() +{ +} + +void BarRenderItem::formatLabel() +{ + // Format the string on first access + QString numStr; + numStr.setNum(m_value); + // TODO actually format instead of just prepending the value + m_label.clear(); // Just in case + m_label.append(numStr); + m_label.append(m_renderer->itemLabelFormat()); // TODO format needs to be cached +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/barrenderitem_p.h b/src/datavis3d/data/barrenderitem_p.h new file mode 100644 index 00000000..babab795 --- /dev/null +++ b/src/datavis3d/data/barrenderitem_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 BARRENDERITEM_P_H +#define BARRENDERITEM_P_H + +#include "abstractrenderitem_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class Bars3dRenderer; + +class BarRenderItem : public AbstractRenderItem +{ +public: + BarRenderItem(); + virtual ~BarRenderItem(); + + // Position relative to data window (for bar label generation) + inline void setPosition(const QPoint &pos) { m_position = pos; } + inline const QPoint &position() const { return m_position; } + + // Actual cached data value of the bar (needed to trigger label reformats) + inline void setValue(qreal value); + inline qreal value() const { return m_value; } + + // Normalized bar height + inline void setHeight(GLfloat height) { m_height = height; } + inline GLfloat height() const { return m_height; } + + // TODO should be in abstract, but currently there is no abstract renderer + inline void setRenderer(Bars3dRenderer *renderer) { m_renderer = renderer; } + +protected: + virtual void formatLabel(); + + Bars3dRenderer *m_renderer; + qreal m_value; + QPoint m_position; // x = row, y = column + GLfloat m_height; + + friend class QBarDataItem; +}; + +void BarRenderItem::setValue(qreal value) +{ + if (m_value != value) { + m_value = value; + if (!m_label.isNull()) + setLabel(QString()); // Forces reformatting on next access + } +} + +typedef QVector<BarRenderItem> BarRenderItemRow; +typedef QVector<BarRenderItemRow> BarRenderItemArray; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/data.pri b/src/datavis3d/data/data.pri new file mode 100644 index 00000000..a3b28e6e --- /dev/null +++ b/src/datavis3d/data/data.pri @@ -0,0 +1,52 @@ +HEADERS += \ + $$PWD/labelitem_p.h \ + $$PWD/qabstractdataproxy.h \ + $$PWD/qabstractdataproxy_p.h \ + $$PWD/qbardataproxy.h \ + $$PWD/qbardataproxy_p.h \ + $$PWD/abstractrenderitem_p.h \ + $$PWD/barrenderitem_p.h \ + $$PWD/qbardataitem.h \ + $$PWD/qbardataitem_p.h \ + $$PWD/qitemmodelbardatamapping.h \ + $$PWD/qitemmodelbardatamapping_p.h \ + $$PWD/qitemmodelbardataproxy_p.h \ + $$PWD/qitemmodelbardataproxy.h \ + $$PWD/maprenderitem_p.h \ + $$PWD/qmapdataitem.h \ + $$PWD/qmapdataitem_p.h \ + $$PWD/qmapdataproxy.h \ + $$PWD/qmapdataproxy_p.h \ + $$PWD/scatterrenderitem_p.h \ + $$PWD/qscatterdataitem.h \ + $$PWD/qscatterdataitem_p.h \ + $$PWD/qscatterdataproxy.h \ + $$PWD/qscatterdataproxy_p.h \ + $$PWD/qitemmodelmapdatamapping.h \ + $$PWD/qitemmodelmapdatamapping_p.h \ + $$PWD/qitemmodelmapdataproxy.h \ + $$PWD/qitemmodelmapdataproxy_p.h \ + $$PWD/qitemmodelscatterdatamapping.h \ + $$PWD/qitemmodelscatterdatamapping_p.h \ + $$PWD/qitemmodelscatterdataproxy.h \ + $$PWD/qitemmodelscatterdataproxy_p.h + +SOURCES += \ + $$PWD/labelitem.cpp \ + $$PWD/qabstractdataproxy.cpp \ + $$PWD/qbardataproxy.cpp \ + $$PWD/abstractrenderitem.cpp \ + $$PWD/barrenderitem.cpp \ + $$PWD/qbardataitem.cpp \ + $$PWD/qitemmodelbardatamapping.cpp \ + $$PWD/qitemmodelbardataproxy.cpp \ + $$PWD/maprenderitem.cpp \ + $$PWD/qmapdataitem.cpp \ + $$PWD/qmapdataproxy.cpp \ + $$PWD/scatterrenderitem.cpp \ + $$PWD/qscatterdataitem.cpp \ + $$PWD/qscatterdataproxy.cpp \ + $$PWD/qitemmodelmapdatamapping.cpp \ + $$PWD/qitemmodelmapdataproxy.cpp \ + $$PWD/qitemmodelscatterdatamapping.cpp \ + $$PWD/qitemmodelscatterdataproxy.cpp diff --git a/src/datavis3d/data/labelitem.cpp b/src/datavis3d/data/labelitem.cpp new file mode 100644 index 00000000..1d1bf6f7 --- /dev/null +++ b/src/datavis3d/data/labelitem.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "labelitem_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +LabelItem::LabelItem() + : m_size(QSize(0, 0)), + m_textureId(0) +{ +} + +LabelItem::~LabelItem() +{ + glDeleteTextures(1, &m_textureId); +} + +void LabelItem::setSize(const QSize &size) +{ + m_size = size; +} + +QSize LabelItem::size() const +{ + return m_size; +} + +void LabelItem::setTextureId(GLuint textureId) +{ + glDeleteTextures(1, &m_textureId); + m_textureId = textureId; +} + +GLuint LabelItem::textureId() const +{ + return m_textureId; +} + +void LabelItem::clear() +{ + if (m_textureId) { + glDeleteTextures(1, &m_textureId); + m_textureId = 0; + } + m_size = QSize(0, 0); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/labelitem_p.h b/src/datavis3d/data/labelitem_p.h new file mode 100644 index 00000000..84625002 --- /dev/null +++ b/src/datavis3d/data/labelitem_p.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 LABELITEM_P_H +#define LABELITEM_P_H + +#include "datavis3dglobal_p.h" +#include <QOpenGLFunctions> +#include <QSize> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class LabelItem +{ +public: + explicit LabelItem(); + ~LabelItem(); + + void setSize(const QSize &size); + QSize size() const; + void setTextureId(GLuint textureId); + GLuint textureId() const; + void clear(); + +private: + Q_DISABLE_COPY(LabelItem); + + QSize m_size; + GLuint m_textureId; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/maprenderitem.cpp b/src/datavis3d/data/maprenderitem.cpp new file mode 100644 index 00000000..c7165104 --- /dev/null +++ b/src/datavis3d/data/maprenderitem.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "maprenderitem_p.h" +#include "maps3drenderer_p.h" // TODO remove when maps refactored +#include "maps3dcontroller_p.h" // TODO should be renderer +#include "qmapdataproxy.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +MapRenderItem::MapRenderItem() + : BarRenderItem() +{ +} + +MapRenderItem::~MapRenderItem() +{ +} + +void MapRenderItem::formatLabel() +{ + // TODO The label format specified in proxy should probably have additional custom formatting + // TODO specifiers in addition to standard printf specifiers for placement of item labels + // TODO and selection data (like row/column in bar selection) + + // Format the string on first access + QString numStr; + numStr.setNum(m_value); + // TODO actually format instead of just prepending the value + m_label.clear(); // Just in case + m_label.append(m_itemLabel); + m_label.append(QStringLiteral(" ")); + m_label.append(numStr); + m_label.append(m_renderer->dataProxy()->itemLabelFormat()); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/maprenderitem_p.h b/src/datavis3d/data/maprenderitem_p.h new file mode 100644 index 00000000..f1e7290e --- /dev/null +++ b/src/datavis3d/data/maprenderitem_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 MAPRENDERITEM_P_H +#define MAPRENDERITEM_P_H + +#include "barrenderitem_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class Maps3DRenderer; +class Maps3DController; // TODO remove when maps refactored + +class MapRenderItem : public BarRenderItem +{ +public: + MapRenderItem(); + virtual ~MapRenderItem(); + + inline const QPointF &mapPosition() const { return m_mapPosition; } + inline void setMapPosition(const QPointF &pos) { m_mapPosition = pos; } + + inline const QString &itemLabel() const { return m_itemLabel; } + inline void setItemLabel(const QString &label) { m_itemLabel = label; } + + // TODO should be in abstract, but currently there is no abstract renderer + // TODO change when maps refactored + inline void setRenderer(Maps3DController *renderer) { m_renderer = renderer; } + +protected: + virtual void formatLabel(); + + Maps3DController *m_renderer; + QPointF m_mapPosition; + QString m_itemLabel; // from QMapDataItem::label() - unformatted item label + + friend class QMapDataItem; +}; + +typedef QVector<MapRenderItem> MapRenderItemArray; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qabstractdataproxy.cpp b/src/datavis3d/data/qabstractdataproxy.cpp new file mode 100644 index 00000000..11874edb --- /dev/null +++ b/src/datavis3d/data/qabstractdataproxy.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qabstractdataproxy.h" +#include "qabstractdataproxy_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QAbstractDataProxy::QAbstractDataProxy(QAbstractDataProxyPrivate *d) : + QObject(0), + d_ptr(d) +{ +} + +QAbstractDataProxy::~QAbstractDataProxy() +{ +} + +QAbstractDataProxy::DataType QAbstractDataProxy::type() const +{ + return d_ptr->m_type; +} + +void QAbstractDataProxy::setItemLabelFormat(const QString &format) +{ + d_ptr->setItemLabelFormat(format); + emit itemLabelFormatChanged(); +} + +QString QAbstractDataProxy::itemLabelFormat() const +{ + return d_ptr->m_itemLabelFormat; +} + +// QAbstractDataProxyPrivate + +QAbstractDataProxyPrivate::QAbstractDataProxyPrivate(QAbstractDataProxy *q, QAbstractDataProxy::DataType type) + : QObject(0), + q_ptr(q), + m_type(type) +{ +} + +QAbstractDataProxyPrivate::~QAbstractDataProxyPrivate() +{ +} + +void QAbstractDataProxyPrivate::setItemLabelFormat(const QString &format) +{ + m_itemLabelFormat = format; +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qabstractdataproxy.h b/src/datavis3d/data/qabstractdataproxy.h new file mode 100644 index 00000000..0e717dbb --- /dev/null +++ b/src/datavis3d/data/qabstractdataproxy.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QABSTRACTDATAPROXY_H +#define QABSTRACTDATAPROXY_H + +#include <QtDataVis3D/qdatavis3denums.h> +#include <QObject> +#include <QScopedPointer> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QAbstractDataProxyPrivate; + +class QT_DATAVIS3D_EXPORT QAbstractDataProxy : public QObject +{ + Q_OBJECT + Q_ENUMS(DataType) + Q_PROPERTY(DataType type READ type) + +public: + enum DataType { + DataTypeNone = 0, + DataTypeBar = 1, + DataTypeMap = 2, + DataTypeScatter = 4, + DataTypeSurface = 8 + }; + +protected: + explicit QAbstractDataProxy(QAbstractDataProxyPrivate *d); +public: + virtual ~QAbstractDataProxy(); + + DataType type() const; + + // Items use this string to format single item labels, unless custom proxy initializes + // item labels with something else. + void setItemLabelFormat(const QString &format); + QString itemLabelFormat() const; + +signals: + void itemLabelFormatChanged(); + +protected: + QScopedPointer<QAbstractDataProxyPrivate> d_ptr; + +private: + Q_DISABLE_COPY(QAbstractDataProxy) +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QABSTRACTDATAPROXY_H diff --git a/src/datavis3d/data/qabstractdataproxy_p.h b/src/datavis3d/data/qabstractdataproxy_p.h new file mode 100644 index 00000000..eda13b86 --- /dev/null +++ b/src/datavis3d/data/qabstractdataproxy_p.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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. + +#include "datavis3dglobal_p.h" +#include "qabstractdataproxy.h" +#include <QString> + +#ifndef QABSTRACTDATAPROXY_P_H +#define QABSTRACTDATAPROXY_P_H + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QAbstractDataProxyPrivate : public QObject +{ + Q_OBJECT +public: + QAbstractDataProxyPrivate(QAbstractDataProxy *q, QAbstractDataProxy::DataType type); + virtual ~QAbstractDataProxyPrivate(); + + void setItemLabelFormat(const QString &format); + +protected: + QAbstractDataProxy *q_ptr; + QAbstractDataProxy::DataType m_type; + QString m_itemLabelFormat; + +private: + friend class QAbstractDataProxy; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QABSTRACTDATAPROXY_P_H diff --git a/src/datavis3d/data/qbardataitem.cpp b/src/datavis3d/data/qbardataitem.cpp new file mode 100644 index 00000000..1e8f3d95 --- /dev/null +++ b/src/datavis3d/data/qbardataitem.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qbardataitem_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +/*! + * \class QBarDataItem + * \inmodule QtDataVis3D + * \brief The QBarDataItem class provides a container for resolved data to be added to bar graphs. + * \since 1.0.0 + * + * A QBarDataItem holds data for a single rendered bar in a graph. + * Bar data proxies parse data into QBarDataItem instances for visualizing. + * + * \sa QBarDataProxy, {Qt Data Visualization 3D C++ Classes} + */ + +/*! + * Constructs QBarDataItem. + */ +QBarDataItem::QBarDataItem() + : d_ptr(0), // private data doesn't exist by default (optimization) + m_value(0.0) +{ +} + +QBarDataItem::QBarDataItem(qreal value) + : d_ptr(0), + m_value(value) +{ +} + +QBarDataItem::QBarDataItem(const QBarDataItem &other) +{ + operator=(other); +} + +/*! + * Destroys QBarDataItem. + */ +QBarDataItem::~QBarDataItem() +{ + delete d_ptr; +} + +QBarDataItem &QBarDataItem::operator=(const QBarDataItem &other) +{ + m_value = other.m_value; + if (other.d_ptr) + createExtraData(); + else + d_ptr = 0; + // TODO set extra data + return *this; +} + +void QBarDataItem::setValue(qreal value) +{ + m_value = value; +} + +qreal QBarDataItem::value() const +{ + return m_value; +} + +void QBarDataItem::createExtraData() +{ + if (!d_ptr) + d_ptr = new QBarDataItemPrivate; +} + + +QBarDataItemPrivate::QBarDataItemPrivate() +{ +} + +QBarDataItemPrivate::~QBarDataItemPrivate() +{ +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qbardataitem.h b/src/datavis3d/data/qbardataitem.h new file mode 100644 index 00000000..d7062b66 --- /dev/null +++ b/src/datavis3d/data/qbardataitem.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QBARDATAITEM_H +#define QBARDATAITEM_H + +#include <QtDataVis3D/qdatavis3denums.h> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QBarDataItemPrivate; + +class QT_DATAVIS3D_EXPORT QBarDataItem +{ +public: + QBarDataItem(); + QBarDataItem(qreal value); + QBarDataItem(const QBarDataItem &other); + ~QBarDataItem(); + + QBarDataItem &operator=(const QBarDataItem &other); + + void setValue(qreal value); + qreal value() const; + + // TODO Set color, label format, ...? + +protected: + virtual void createExtraData(); + + QBarDataItemPrivate *d_ptr; + +private: + qreal m_value; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qbardataitem_p.h b/src/datavis3d/data/qbardataitem_p.h new file mode 100644 index 00000000..e63ce787 --- /dev/null +++ b/src/datavis3d/data/qbardataitem_p.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 QBARDATAITEM_P_H +#define QBARDATAITEM_P_H + +#include "datavis3dglobal_p.h" +#include "qbardataitem.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QBarDataItemPrivate +{ +public: + QBarDataItemPrivate(); + virtual ~QBarDataItemPrivate(); + + // TODO stores other data for bars besides value + +protected: + friend class QBarDataItem; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qbardataproxy.cpp b/src/datavis3d/data/qbardataproxy.cpp new file mode 100644 index 00000000..589ed37a --- /dev/null +++ b/src/datavis3d/data/qbardataproxy.cpp @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qbardataproxy.h" +#include "qbardataproxy_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QBarDataProxy::QBarDataProxy() : + QAbstractDataProxy(new QBarDataProxyPrivate(this)) +{ +} + +QBarDataProxy::QBarDataProxy(QBarDataProxyPrivate *d) : + QAbstractDataProxy(d) +{ +} + +QBarDataProxy::~QBarDataProxy() +{ +} + +void QBarDataProxy::resetArray(QBarDataArray *newArray) +{ + if (dptr()->resetArray(newArray)) + emit arrayReset(); +} + +void QBarDataProxy::setRow(int rowIndex, QBarDataRow *row) +{ + dptr()->setRow(rowIndex, row); + emit rowsChanged(rowIndex, 1); +} + +void QBarDataProxy::setRows(int rowIndex, const QBarDataArray &rows) +{ + dptr()->setRows(rowIndex, rows); + emit rowsChanged(rowIndex, rows.size()); +} + +void QBarDataProxy::setItem(int rowIndex, int columnIndex, const QBarDataItem &item) +{ + dptr()->setItem(rowIndex, columnIndex, item); + emit itemChanged(rowIndex, columnIndex); +} + +int QBarDataProxy::addRow(QBarDataRow *row) +{ + int addIndex = dptr()->addRow(row); + emit rowsAdded(addIndex, 1); + return addIndex; +} + +int QBarDataProxy::addRows(const QBarDataArray &rows) +{ + int addIndex = dptr()->addRows(rows); + emit rowsAdded(addIndex, rows.size()); + return addIndex; +} + +void QBarDataProxy::insertRow(int rowIndex, QBarDataRow *row) +{ + dptr()->insertRow(rowIndex, row); + emit rowsInserted(rowIndex, 1); +} + +void QBarDataProxy::insertRows(int rowIndex, const QBarDataArray &rows) +{ + dptr()->insertRows(rowIndex, rows); + emit rowsInserted(rowIndex, rows.size()); +} + +void QBarDataProxy::removeRows(int rowIndex, int removeCount) +{ + if (rowIndex < rowCount()) { + dptr()->removeRows(rowIndex, removeCount); + emit rowsRemoved(rowIndex, removeCount); + } +} + +int QBarDataProxy::rowCount() const +{ + return dptrc()->m_dataArray->size(); +} + +const QBarDataArray *QBarDataProxy::array() const +{ + return dptrc()->m_dataArray; +} + +const QBarDataRow *QBarDataProxy::rowAt(int rowIndex) const +{ + const QBarDataArray &dataArray = *dptrc()->m_dataArray; + Q_ASSERT(rowIndex >= 0 && rowIndex < dataArray.size()); + return dataArray[rowIndex]; +} + +const QBarDataItem *QBarDataProxy::itemAt(int rowIndex, int columnIndex) const +{ + const QBarDataArray &dataArray = *dptrc()->m_dataArray; + Q_ASSERT(rowIndex >= 0 && rowIndex < dataArray.size()); + const QBarDataRow &dataRow = *dataArray[rowIndex]; + Q_ASSERT(columnIndex >= 0 && columnIndex < dataRow.size()); + return &dataRow.at(columnIndex); +} + +QBarDataProxyPrivate *QBarDataProxy::dptr() +{ + return static_cast<QBarDataProxyPrivate *>(d_ptr.data()); +} + +const QBarDataProxyPrivate *QBarDataProxy::dptrc() const +{ + return static_cast<const QBarDataProxyPrivate *>(d_ptr.data()); +} + +// QBarDataProxyPrivate + +QBarDataProxyPrivate::QBarDataProxyPrivate(QBarDataProxy *q) + : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeBar), + m_dataArray(new QBarDataArray) +{ +} + +QBarDataProxyPrivate::~QBarDataProxyPrivate() +{ + clearArray(); +} + +bool QBarDataProxyPrivate::resetArray(QBarDataArray *newArray) +{ + if (!m_dataArray->size() && (!newArray || !newArray->size())) + return false; + + clearArray(); + + if (newArray) + m_dataArray = newArray; + else + m_dataArray = new QBarDataArray; + + return true; +} + +void QBarDataProxyPrivate::setRow(int rowIndex, QBarDataRow *row) +{ + Q_ASSERT(rowIndex >= 0 && rowIndex < m_dataArray->size()); + clearRow(rowIndex); + (*m_dataArray)[rowIndex] = row; +} + +void QBarDataProxyPrivate::setRows(int rowIndex, const QBarDataArray &rows) +{ + QBarDataArray &dataArray = *m_dataArray; + Q_ASSERT(rowIndex >= 0 && (rowIndex + rows.size()) <= dataArray.size()); + for (int i = 0; i < rows.size(); i++) { + clearRow(rowIndex); + dataArray[rowIndex] = rows.at(i); + rowIndex++; + } +} + +void QBarDataProxyPrivate::setItem(int rowIndex, int columnIndex, const QBarDataItem &item) +{ + Q_ASSERT(rowIndex >= 0 && rowIndex < m_dataArray->size()); + QBarDataRow &row = *(*m_dataArray)[rowIndex]; + Q_ASSERT(columnIndex < row.size()); + row[columnIndex] = item; +} + +int QBarDataProxyPrivate::addRow(QBarDataRow *row) +{ + int currentSize = m_dataArray->size(); + m_dataArray->append(row); + return currentSize; +} + +int QBarDataProxyPrivate::addRows(const QBarDataArray &rows) +{ + int currentSize = m_dataArray->size(); + for (int i = 0; i < rows.size(); i++) + m_dataArray->append(rows.at(i)); + return currentSize; +} + +void QBarDataProxyPrivate::insertRow(int rowIndex, QBarDataRow *row) +{ + Q_ASSERT(rowIndex >= 0 && rowIndex <= m_dataArray->size()); + m_dataArray->insert(rowIndex, row); +} + +void QBarDataProxyPrivate::insertRows(int rowIndex, const QBarDataArray &rows) +{ + Q_ASSERT(rowIndex >= 0 && rowIndex <= m_dataArray->size()); + for (int i = 0; i < rows.size(); i++) + m_dataArray->insert(rowIndex++, rows.at(i)); +} + +void QBarDataProxyPrivate::removeRows(int rowIndex, int removeCount) +{ + Q_ASSERT(rowIndex >= 0); + int maxRemoveCount = m_dataArray->size() - rowIndex; + removeCount = qMin(removeCount, maxRemoveCount); + for (int i = 0; i < removeCount; i++) { + clearRow(rowIndex); + m_dataArray->removeAt(rowIndex); + } +} + +void QBarDataProxyPrivate::clearRow(int rowIndex) +{ + if (m_dataArray->at(rowIndex)) { + delete m_dataArray->at(rowIndex); + (*m_dataArray)[rowIndex] = 0; + } +} + +void QBarDataProxyPrivate::clearArray() +{ + for (int i = 0; i < m_dataArray->size(); i++) + clearRow(i); + m_dataArray->clear(); + delete m_dataArray; +} + +QPair<GLfloat, GLfloat> QBarDataProxyPrivate::limitValues(int startRow, int endRow, int startColumn, int endColumn) +{ + QPair<GLfloat, GLfloat> limits = qMakePair(0.0f, 0.0f); + endRow = qMin(endRow, m_dataArray->size() - 1); + for (int i = startRow; i <= endRow; i++) { + QBarDataRow *row = m_dataArray->at(i); + if (row) { + endColumn = qMin(endColumn, row->size() - 1); + for (int j = startColumn; j <= endColumn; j++) { + const QBarDataItem &item = m_dataArray->at(i)->at(j); + qreal itemValue = item.value(); + if (limits.second < itemValue) + limits.second = itemValue; + if (limits.first > itemValue) + limits.first = itemValue; + } + } + } + return limits; +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qbardataproxy.h b/src/datavis3d/data/qbardataproxy.h new file mode 100644 index 00000000..e28f8ff0 --- /dev/null +++ b/src/datavis3d/data/qbardataproxy.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QBARDATAPROXY_H +#define QBARDATAPROXY_H + +#include <QtDataVis3D/qabstractdataproxy.h> +#include <QtDataVis3D/qbardataitem.h> +#include <QVector> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +typedef QVector<QBarDataItem> QBarDataRow; +typedef QList<QBarDataRow *> QBarDataArray; + +class QBarDataProxyPrivate; + +class QT_DATAVIS3D_EXPORT QBarDataProxy : public QAbstractDataProxy +{ + Q_OBJECT + +public: + explicit QBarDataProxy(); + explicit QBarDataProxy(QBarDataProxyPrivate *d); + virtual ~QBarDataProxy(); + + // BarDataProxy is optimized for adding, inserting, and removing rows of data. + // Adding a column essentially means modifying every row, which is comparatively very inefficient. + // Proxy is also optimized to use cases where the only defining characteristic of an individual + // bar is its value. Modifying other data that might be added in the future such as color of + // individual bar requires allocating additional data object for the bar. + + // Row and item pointers are guaranteed to be valid only until next call that modifies data. + // Array pointer is guaranteed to be valid for lifetime of proxy. + int rowCount() const; + const QBarDataArray *array() const; + const QBarDataRow *rowAt(int rowIndex) const; + const QBarDataItem *itemAt(int rowIndex, int columnIndex) const; + + // The data array is a list of vectors (rows) of QBarDataItem instances. + // Each row can contain different amount of items or even be null. + + // QBarDataProxy takes ownership of all QBarDataRows passed to it, whether directly or + // in a QBarDataArray container. + // QBarDataRow pointers should not be used to modify data further after they have been passed to + // the proxy, as such modifications will not trigger proper signals. + + // Clears the existing array and takes ownership of the new array. + // Passing null array clears all data. + void resetArray(QBarDataArray *newArray); + + // Change existing rows + void setRow(int rowIndex, QBarDataRow *row); + void setRows(int rowIndex, const QBarDataArray &rows); + + // Setting a column is comparatively inefficient as it changes all rows. + // Can resize rows that are shorter than columnIndex. + // TODO void setColumn(int columnIndex, const QBarDataRow &column); + // TODO void setColumns(int columnIndex, const QBarDataArray &columns); + + // Change single item + void setItem(int rowIndex, int columnIndex, const QBarDataItem &item); + // Change block of items + // TODO setItems(int rowIndex, int columnIndex, QBarDataArray *items); + + int addRow(QBarDataRow *row); // returns the index of added row + int addRows(const QBarDataArray &rows); // returns the index of first added row + // TODO int addColumn(const QBarDataRow &column); // returns the index of the added column + // TODO int addColumns(const QBarDataArray &columns); // returns the index of the first added column + + // If rowIndex is equal to array size, rows are added to end of the array. + void insertRow(int rowIndex, QBarDataRow *row); + void insertRows(int rowIndex, const QBarDataArray &rows); + // TODO void insertColumn(int columnIndex, const QBarDataRow &column); + // TODO void insertColumns(int columnIndex, const QBarDataArray &columns); + + // Attempting to remove rows past the end of the array does nothing. + void removeRows(int rowIndex, int removeCount); + // TODO void removeColumns(int columnIndex, int removeCount); + +signals: + void arrayReset(); + void rowsAdded(int startIndex, int count); + void rowsChanged(int startIndex, int count); + // Index is the current array size if rows were removed from the end of the array + void rowsRemoved(int startIndex, int count); + void rowsInserted(int startIndex, int count); + // TODO void columnsChanged(int startIndex, int count); + // TODO void columnsAdded(int startIndex, int count); + // TODO void columnsRemoved(int startIndex, int count); + // TODO void columnsInserted(int startIndex, int count); + void itemChanged(int rowIndex, int columnIndex); // TODO remove once itemsChanged is added? + // TODO void itemsChanged(int rowIndex, int columnIndex, int rowCount, int columnCount); + +protected: + QBarDataProxyPrivate *dptr(); + const QBarDataProxyPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QBarDataProxy) + + friend class Bars3dController; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QBARDATAPROXY_H diff --git a/src/datavis3d/data/qbardataproxy_p.h b/src/datavis3d/data/qbardataproxy_p.h new file mode 100644 index 00000000..fa6ccd0d --- /dev/null +++ b/src/datavis3d/data/qbardataproxy_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 QBARDATAPROXY_P_H +#define QBARDATAPROXY_P_H + +#include "qbardataproxy.h" +#include "qabstractdataproxy_p.h" +#include "qbardataitem.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QBarDataProxyPrivate : public QAbstractDataProxyPrivate +{ + Q_OBJECT +public: + QBarDataProxyPrivate(QBarDataProxy *q); + virtual ~QBarDataProxyPrivate(); + + bool resetArray(QBarDataArray *newArray); + void setRow(int rowIndex, QBarDataRow *row); + void setRows(int rowIndex, const QBarDataArray &rows); + void setItem(int rowIndex, int columnIndex, const QBarDataItem &item); + int addRow(QBarDataRow *row); + int addRows(const QBarDataArray &rows); + void insertRow(int rowIndex, QBarDataRow *row); + void insertRows(int rowIndex, const QBarDataArray &rows); + void removeRows(int rowIndex, int removeCount); + + QPair<GLfloat, GLfloat> limitValues(int startRow, int startColumn, int rowCount, int columnCount); + +private: + void clearRow(int rowIndex); + void clearArray(); + + QBarDataArray *m_dataArray; + +private: + friend class QBarDataProxy; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QBARDATAPROXY_P_H diff --git a/src/datavis3d/data/qitemmodelbardatamapping.cpp b/src/datavis3d/data/qitemmodelbardatamapping.cpp new file mode 100644 index 00000000..0aecb082 --- /dev/null +++ b/src/datavis3d/data/qitemmodelbardatamapping.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qitemmodelbardatamapping_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QItemModelBarDataMapping::QItemModelBarDataMapping() + : QObject(0), + d_ptr(new QItemModelBarDataMappingPrivate(this)) +{ +} + +QItemModelBarDataMapping::QItemModelBarDataMapping(const QItemModelBarDataMapping &other) + : QObject(0), + d_ptr(new QItemModelBarDataMappingPrivate(this)) +{ + operator=(other); +} + +QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &valueRole) + : QObject(0), + d_ptr(new QItemModelBarDataMappingPrivate(this)) +{ + d_ptr->m_valueRole = valueRole; +} + +QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &rowRole, + const QString &columnRole, + const QString &valueRole, + const QStringList &rowCategories, + const QStringList &columnCategories) + : QObject(0), + d_ptr(new QItemModelBarDataMappingPrivate(this)) +{ + d_ptr->m_rowRole = rowRole; + d_ptr->m_columnRole = columnRole; + d_ptr->m_valueRole = valueRole; + d_ptr->m_rowCategories = rowCategories; + d_ptr->m_columnCategories = columnCategories; +} + +QItemModelBarDataMapping::~QItemModelBarDataMapping() +{ +} + +QItemModelBarDataMapping &QItemModelBarDataMapping::operator=(const QItemModelBarDataMapping &other) +{ + d_ptr->m_rowRole = other.d_ptr->m_rowRole; + d_ptr->m_columnRole = other.d_ptr->m_columnRole; + d_ptr->m_valueRole = other.d_ptr->m_valueRole; + d_ptr->m_rowCategories = other.d_ptr->m_rowCategories; + d_ptr->m_columnCategories = other.d_ptr->m_columnCategories; + + return *this; +} + +void QItemModelBarDataMapping::setRowRole(const QString &role) +{ + d_ptr->m_rowRole = role; + emit mappingChanged(); +} + +QString QItemModelBarDataMapping::rowRole() const +{ + return d_ptr->m_rowRole; +} + +void QItemModelBarDataMapping::setColumnRole(const QString &role) +{ + d_ptr->m_columnRole = role; + emit mappingChanged(); +} + +QString QItemModelBarDataMapping::columnRole() const +{ + return d_ptr->m_columnRole; +} + +void QItemModelBarDataMapping::setValueRole(const QString &role) +{ + d_ptr->m_valueRole = role; + emit mappingChanged(); +} + +QString QItemModelBarDataMapping::valueRole() const +{ + return d_ptr->m_valueRole; +} + +void QItemModelBarDataMapping::setRowCategories(const QStringList &categories) +{ + d_ptr->m_rowCategories = categories; + emit mappingChanged(); +} + +const QStringList &QItemModelBarDataMapping::rowCategories() const +{ + return d_ptr->m_rowCategories; +} + +void QItemModelBarDataMapping::setColumnCategories(const QStringList &categories) +{ + d_ptr->m_columnCategories = categories; + emit mappingChanged(); +} + +const QStringList &QItemModelBarDataMapping::columnCategories() const +{ + return d_ptr->m_columnCategories; +} + +void QItemModelBarDataMapping::remap(const QString &rowRole, + const QString &columnRole, + const QString &valueRole, + const QStringList &rowCategories, + const QStringList &columnCategories) +{ + d_ptr->m_rowRole = rowRole; + d_ptr->m_columnRole = columnRole; + d_ptr->m_valueRole = valueRole; + d_ptr->m_rowCategories = rowCategories; + d_ptr->m_columnCategories = columnCategories; + + emit mappingChanged(); +} + +// QItemModelBarDataMappingPrivate + +QItemModelBarDataMappingPrivate::QItemModelBarDataMappingPrivate(QItemModelBarDataMapping *q) + : QObject(0), + q_ptr(q) +{ +} + +QItemModelBarDataMappingPrivate::~QItemModelBarDataMappingPrivate() +{ +} + +QT_DATAVIS3D_END_NAMESPACE + diff --git a/src/datavis3d/data/qitemmodelbardatamapping.h b/src/datavis3d/data/qitemmodelbardatamapping.h new file mode 100644 index 00000000..d9f74152 --- /dev/null +++ b/src/datavis3d/data/qitemmodelbardatamapping.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QITEMMODELBARDATAMAPPING_H +#define QITEMMODELBARDATAMAPPING_H + +#include <QtDataVis3D/qdatavis3denums.h> +#include <QStringList> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelBarDataMappingPrivate; + +class QT_DATAVIS3D_EXPORT QItemModelBarDataMapping : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString rowRole READ rowRole WRITE setRowRole) + Q_PROPERTY(QString columnRole READ columnRole WRITE setColumnRole) + Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole) + Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories) + Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories) +public: + explicit QItemModelBarDataMapping(); + QItemModelBarDataMapping(const QItemModelBarDataMapping &other); + QItemModelBarDataMapping(const QString &valueRole); + QItemModelBarDataMapping(const QString &rowRole, const QString &columnRole, + const QString &valueRole, const QStringList &rowCategories, + const QStringList &columnCategories); + virtual ~QItemModelBarDataMapping(); + + QItemModelBarDataMapping &operator=(const QItemModelBarDataMapping &other); + + // If row categories or column categories is an empty list, use item models's rows and columns for rows and columns. + // If the categories are both defined, ignore item model's rows and columns and figure out the rows and columns from + // the values of the set roles for each item. + + void setRowRole(const QString &role); + QString rowRole() const; + void setColumnRole(const QString &role); + QString columnRole() const; + void setValueRole(const QString &role); + QString valueRole() const; + + void setRowCategories(const QStringList &categories); + const QStringList &rowCategories() const; + void setColumnCategories(const QStringList &categories); + const QStringList &columnCategories() const; + + void remap(const QString &rowRole, const QString &columnRole, + const QString &valueRole, const QStringList &rowCategories, + const QStringList &columnCategories); +signals: + void mappingChanged(); + +private: + QScopedPointer<QItemModelBarDataMappingPrivate> d_ptr; +}; + + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qitemmodelbardatamapping_p.h b/src/datavis3d/data/qitemmodelbardatamapping_p.h new file mode 100644 index 00000000..fa1728e0 --- /dev/null +++ b/src/datavis3d/data/qitemmodelbardatamapping_p.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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. + +#include "qitemmodelbardatamapping.h" + +#ifndef QITEMMODELBARDATAMAPPING_P_H +#define QITEMMODELBARDATAMAPPING_P_H + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelBarDataMappingPrivate : public QObject +{ + Q_OBJECT +public: + QItemModelBarDataMappingPrivate(QItemModelBarDataMapping *q); + virtual ~QItemModelBarDataMappingPrivate(); + +private: + QString m_rowRole; + QString m_columnRole; + QString m_valueRole; + + // For row/column items, sort items into these categories. Other categories are ignored. + QStringList m_rowCategories; + QStringList m_columnCategories; + + QItemModelBarDataMapping *q_ptr; + + friend class QItemModelBarDataMapping; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qitemmodelbardataproxy.cpp b/src/datavis3d/data/qitemmodelbardataproxy.cpp new file mode 100644 index 00000000..4b3ed020 --- /dev/null +++ b/src/datavis3d/data/qitemmodelbardataproxy.cpp @@ -0,0 +1,290 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qitemmodelbardataproxy_p.h" +#include <QTimer> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QItemModelBarDataProxy::QItemModelBarDataProxy() : + QBarDataProxy(new QItemModelBarDataProxyPrivate(this)) +{ +} + +QItemModelBarDataProxy::QItemModelBarDataProxy(QAbstractItemModel *itemModel, + QItemModelBarDataMapping *mapping) : + QBarDataProxy(new QItemModelBarDataProxyPrivate(this)) +{ + dptr()->setItemModel(itemModel); + dptr()->setMapping(mapping); +} + +QItemModelBarDataProxy::~QItemModelBarDataProxy() +{ +} + +void QItemModelBarDataProxy::setItemModel(QAbstractItemModel *itemModel) +{ + dptr()->setItemModel(itemModel); +} + +QAbstractItemModel *QItemModelBarDataProxy::itemModel() +{ + return dptr()->m_itemModel.data(); +} + +void QItemModelBarDataProxy::setMapping(QItemModelBarDataMapping *mapping) +{ + dptr()->setMapping(mapping); +} + +QItemModelBarDataMapping *QItemModelBarDataProxy::mapping() +{ + return dptr()->m_mapping.data(); +} + +QItemModelBarDataProxyPrivate *QItemModelBarDataProxy::dptr() +{ + return static_cast<QItemModelBarDataProxyPrivate *>(d_ptr.data()); +} + +// QItemModelBarDataProxyPrivate + +QItemModelBarDataProxyPrivate::QItemModelBarDataProxyPrivate(QItemModelBarDataProxy *q) + : QBarDataProxyPrivate(q), + resolvePending(0) +{ + m_resolveTimer.setSingleShot(true); + QObject::connect(&m_resolveTimer, &QTimer::timeout, this, &QItemModelBarDataProxyPrivate::handlePendingResolve); +} + +QItemModelBarDataProxyPrivate::~QItemModelBarDataProxyPrivate() +{ +} + +void QItemModelBarDataProxyPrivate::setItemModel(QAbstractItemModel *itemModel) +{ + if (!m_itemModel.isNull()) + QObject::disconnect(m_itemModel, 0, this, 0); + + m_itemModel = itemModel; + + if (!m_itemModel.isNull()) { + QObject::connect(m_itemModel, &QAbstractItemModel::columnsInserted, this, &QItemModelBarDataProxyPrivate::handleColumnsInserted); + QObject::connect(m_itemModel, &QAbstractItemModel::columnsMoved, this, &QItemModelBarDataProxyPrivate::handleColumnsMoved); + QObject::connect(m_itemModel, &QAbstractItemModel::columnsRemoved, this, &QItemModelBarDataProxyPrivate::handleColumnsRemoved); + QObject::connect(m_itemModel, &QAbstractItemModel::dataChanged, this, &QItemModelBarDataProxyPrivate::handleDataChanged); + QObject::connect(m_itemModel, &QAbstractItemModel::layoutChanged, this, &QItemModelBarDataProxyPrivate::handleLayoutChanged); + QObject::connect(m_itemModel, &QAbstractItemModel::modelReset, this, &QItemModelBarDataProxyPrivate::handleModelReset); + QObject::connect(m_itemModel, &QAbstractItemModel::rowsInserted, this, &QItemModelBarDataProxyPrivate::handleRowsInserted); + QObject::connect(m_itemModel, &QAbstractItemModel::rowsMoved, this, &QItemModelBarDataProxyPrivate::handleRowsMoved); + QObject::connect(m_itemModel, &QAbstractItemModel::rowsRemoved, this, &QItemModelBarDataProxyPrivate::handleRowsRemoved); + } + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QItemModelBarDataProxyPrivate::setMapping(QItemModelBarDataMapping *mapping) +{ + if (!m_mapping.isNull()) + QObject::disconnect(m_mapping.data(), &QItemModelBarDataMapping::mappingChanged, this, &QItemModelBarDataProxyPrivate::handleMappingChanged); + + m_mapping = mapping; + + if (!m_mapping.isNull()) + QObject::connect(m_mapping.data(), &QItemModelBarDataMapping::mappingChanged, this, &QItemModelBarDataProxyPrivate::handleMappingChanged); + + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QItemModelBarDataProxyPrivate::handleColumnsInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve new items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelBarDataProxyPrivate::handleColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn) +{ + Q_UNUSED(sourceParent) + Q_UNUSED(sourceStart) + Q_UNUSED(sourceEnd) + Q_UNUSED(destinationParent) + Q_UNUSED(destinationColumn) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelBarDataProxyPrivate::handleColumnsRemoved(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Remove old items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelBarDataProxyPrivate::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + Q_UNUSED(roles) + + // Resolve changed items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelBarDataProxyPrivate::handleLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint) +{ + Q_UNUSED(parents) + Q_UNUSED(hint) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelBarDataProxyPrivate::handleModelReset() +{ + // Data cleared, reset array + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelBarDataProxyPrivate::handleRowsInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve new items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelBarDataProxyPrivate::handleRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) +{ + Q_UNUSED(sourceParent) + Q_UNUSED(sourceStart) + Q_UNUSED(sourceEnd) + Q_UNUSED(destinationParent) + Q_UNUSED(destinationRow) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelBarDataProxyPrivate::handleRowsRemoved(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve removed items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelBarDataProxyPrivate::handleMappingChanged() +{ + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QItemModelBarDataProxyPrivate::handlePendingResolve() +{ + resolveModel(); +} + +// Resolve entire item model into QBarDataArray. +void QItemModelBarDataProxyPrivate::resolveModel() +{ + if (m_itemModel.isNull() || m_mapping.isNull()) { + qptr()->resetArray(0); + return; + } + + bool useModelRows(false); + if (!m_mapping->rowCategories().size() || !m_mapping->columnCategories().size()) { + useModelRows = true; + } else if (m_mapping->rowRole().isEmpty() || m_mapping->columnRole().isEmpty()) { + qptr()->resetArray(0); + return; + } + + QBarDataArray *newProxyArray = new QBarDataArray; + QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); + // Default to display role if no mapping + int valueRole = roleHash.key(m_mapping->valueRole().toLatin1(), Qt::DisplayRole); + int rowCount = m_itemModel->rowCount(); + int columnCount = m_itemModel->columnCount(); + + if (useModelRows) { + for (int i = 0; i < rowCount; i++) { + QBarDataRow *newProxyRow = new QBarDataRow(columnCount); + for (int j = 0; j < columnCount; j++) + (*newProxyRow)[j].setValue(m_itemModel->index(i, j).data(valueRole).toReal()); + newProxyArray->append(newProxyRow); + } + } else { + int rowRole = roleHash.key(m_mapping->rowRole().toLatin1()); + int columnRole = roleHash.key(m_mapping->columnRole().toLatin1()); + const QStringList &rowList = m_mapping->rowCategories(); + const QStringList &columnList = m_mapping->columnCategories(); + + // Sort values into rows and columns + typedef QHash<QString, qreal> ColumnValueMap; + QHash <QString, ColumnValueMap> itemValueMap; + for (int i = 0; i < rowCount; i++) { + for (int j = 0; j < columnCount; j++) { + QModelIndex index = m_itemModel->index(i, j); + itemValueMap[index.data(rowRole).toString()][index.data(columnRole).toString()] + = index.data(valueRole).toReal(); + } + } + + // Create new data array from itemValueMap + foreach (QString rowKey, rowList) { + QBarDataRow *newProxyRow = new QBarDataRow(columnList.size()); + for (int i = 0; i < columnList.size(); i++) + (*newProxyRow)[i].setValue(itemValueMap[rowKey][columnList.at(i)]); + newProxyArray->append(newProxyRow); + } + } + qDebug() << __FUNCTION__ << "RowCount:" << newProxyArray->size() << "Column count:" << (newProxyArray->size() ? newProxyArray->at(0)->size() : 0); + + qptr()->resetArray(newProxyArray); +} + +QItemModelBarDataProxy *QItemModelBarDataProxyPrivate::qptr() +{ + return static_cast<QItemModelBarDataProxy *>(q_ptr); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qitemmodelbardataproxy.h b/src/datavis3d/data/qitemmodelbardataproxy.h new file mode 100644 index 00000000..1d60bed6 --- /dev/null +++ b/src/datavis3d/data/qitemmodelbardataproxy.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QITEMMODELBARDATAPROXY_H +#define QITEMMODELBARDATAPROXY_H + +#include <QtDataVis3D/qbardataproxy.h> +#include <QtDataVis3D/qitemmodelbardatamapping.h> +#include <QAbstractItemModel> +#include <QStringList> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelBarDataProxyPrivate; + +class QT_DATAVIS3D_EXPORT QItemModelBarDataProxy : public QBarDataProxy +{ + Q_OBJECT + +public: + explicit QItemModelBarDataProxy(); + explicit QItemModelBarDataProxy(QAbstractItemModel *itemModel, QItemModelBarDataMapping *mapping); + virtual ~QItemModelBarDataProxy(); + + // Doesn't gain ownership of the model, but does connect to it to listen for data changes. + void setItemModel(QAbstractItemModel *itemModel); + QAbstractItemModel *itemModel(); + + // Map bars role (row, column, value) to role in model. + // Doesn't gain ownership of mapping, but does connect to it to listen for mapping changes. + // Modifying mapping that is set to proxy will trigger dataset re-resolving. + void setMapping(QItemModelBarDataMapping *mapping); + QItemModelBarDataMapping *mapping(); + +protected: + QItemModelBarDataProxyPrivate *dptr(); + +private: + Q_DISABLE_COPY(QItemModelBarDataProxy) +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qitemmodelbardataproxy_p.h b/src/datavis3d/data/qitemmodelbardataproxy_p.h new file mode 100644 index 00000000..c69b1679 --- /dev/null +++ b/src/datavis3d/data/qitemmodelbardataproxy_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 QITEMMODELBARDATAPROXY_P_H +#define QITEMMODELBARDATAPROXY_P_H + +#include "qitemmodelbardataproxy.h" +#include "qbardataproxy_p.h" +#include <QPointer> +#include <QTimer> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelBarDataProxyPrivate : public QBarDataProxyPrivate +{ + Q_OBJECT +public: + QItemModelBarDataProxyPrivate(QItemModelBarDataProxy *q); + virtual ~QItemModelBarDataProxyPrivate(); + + void setItemModel(QAbstractItemModel *itemModel); + void setMapping(QItemModelBarDataMapping *mapping); + +public slots: + void handleColumnsInserted(const QModelIndex & parent, int start, int end); + void handleColumnsMoved(const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationColumn); + void handleColumnsRemoved(const QModelIndex & parent, int start, int end); + void handleDataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector<int> & roles = QVector<int> ()); + void handleLayoutChanged(const QList<QPersistentModelIndex> & parents = QList<QPersistentModelIndex> (), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); + void handleModelReset(); + void handleRowsInserted(const QModelIndex & parent, int start, int end); + void handleRowsMoved(const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationRow); + void handleRowsRemoved(const QModelIndex & parent, int start, int end); + + void handleMappingChanged(); + void handlePendingResolve(); + +private: + void resolveModel(); + QItemModelBarDataProxy *qptr(); + + QPointer<QAbstractItemModel> m_itemModel; // Not owned + QPointer<QItemModelBarDataMapping> m_mapping; // Not owned + bool resolvePending; + QTimer m_resolveTimer; + + friend class QItemModelBarDataProxy; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qitemmodelmapdatamapping.cpp b/src/datavis3d/data/qitemmodelmapdatamapping.cpp new file mode 100644 index 00000000..a59be94b --- /dev/null +++ b/src/datavis3d/data/qitemmodelmapdatamapping.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qitemmodelmapdatamapping_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QItemModelMapDataMapping::QItemModelMapDataMapping() + : QObject(0), + d_ptr(new QItemModelMapDataMappingPrivate(this)) +{ +} + +QItemModelMapDataMapping::QItemModelMapDataMapping(const QItemModelMapDataMapping &other) + : QObject(0), + d_ptr(new QItemModelMapDataMappingPrivate(this)) +{ + operator=(other); +} + +QItemModelMapDataMapping::QItemModelMapDataMapping(const QString &labelRole, const QString &xPosRole, + const QString &yPosRole, const QString &valueRole) + : QObject(0), + d_ptr(new QItemModelMapDataMappingPrivate(this)) +{ + d_ptr->m_labelRole = labelRole; + d_ptr->m_xPosRole = xPosRole; + d_ptr->m_yPosRole = yPosRole; + d_ptr->m_valueRole = valueRole; +} + +QItemModelMapDataMapping::~QItemModelMapDataMapping() +{ +} + +QItemModelMapDataMapping &QItemModelMapDataMapping::operator=(const QItemModelMapDataMapping &other) +{ + d_ptr->m_labelRole = other.d_ptr->m_labelRole; + d_ptr->m_xPosRole = other.d_ptr->m_xPosRole; + d_ptr->m_yPosRole = other.d_ptr->m_yPosRole; + d_ptr->m_valueRole = other.d_ptr->m_valueRole; + + return *this; +} + +void QItemModelMapDataMapping::setLabelRole(const QString &role) +{ + d_ptr->m_labelRole = role; + emit mappingChanged(); +} + +QString QItemModelMapDataMapping::labelRole() const +{ + return d_ptr->m_labelRole; +} + +void QItemModelMapDataMapping::setXPosRole(const QString &role) +{ + d_ptr->m_xPosRole = role; + emit mappingChanged(); +} + +QString QItemModelMapDataMapping::xPosRole() const +{ + return d_ptr->m_xPosRole; +} + +void QItemModelMapDataMapping::setYPosRole(const QString &role) +{ + d_ptr->m_yPosRole = role; + emit mappingChanged(); +} + +QString QItemModelMapDataMapping::yPosRole() const +{ + return d_ptr->m_yPosRole; +} + +void QItemModelMapDataMapping::setValueRole(const QString &role) +{ + d_ptr->m_valueRole = role; + emit mappingChanged(); +} + +QString QItemModelMapDataMapping::valueRole() const +{ + return d_ptr->m_valueRole; +} + + +void QItemModelMapDataMapping::remap(const QString &labelRole, const QString &xPosRole, + const QString &yPosRole, const QString &valueRole) +{ + d_ptr->m_labelRole = labelRole; + d_ptr->m_xPosRole = xPosRole; + d_ptr->m_yPosRole = yPosRole; + d_ptr->m_valueRole = valueRole; + + emit mappingChanged(); +} + +// QItemModelMapDataMappingPrivate + +QItemModelMapDataMappingPrivate::QItemModelMapDataMappingPrivate(QItemModelMapDataMapping *q) + : QObject(0), + q_ptr(q) +{ +} + +QItemModelMapDataMappingPrivate::~QItemModelMapDataMappingPrivate() +{ +} + +QT_DATAVIS3D_END_NAMESPACE + diff --git a/src/datavis3d/data/qitemmodelmapdatamapping.h b/src/datavis3d/data/qitemmodelmapdatamapping.h new file mode 100644 index 00000000..79080a65 --- /dev/null +++ b/src/datavis3d/data/qitemmodelmapdatamapping.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QITEMMODELMAPDATAMAPPING_H +#define QITEMMODELMAPDATAMAPPING_H + +#include <QtDataVis3D/qdatavis3denums.h> +#include <QStringList> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelMapDataMappingPrivate; + +class QT_DATAVIS3D_EXPORT QItemModelMapDataMapping : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString labelRole READ labelRole WRITE setLabelRole) + Q_PROPERTY(QString xPosRole READ xPosRole WRITE setXPosRole) + Q_PROPERTY(QString yPosRole READ yPosRole WRITE setYPosRole) + Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole) +public: + explicit QItemModelMapDataMapping(); + QItemModelMapDataMapping(const QItemModelMapDataMapping &other); + QItemModelMapDataMapping(const QString &labelRole, const QString &xPosRole, + const QString &yPosRole, const QString &valueRole); + virtual ~QItemModelMapDataMapping(); + + QItemModelMapDataMapping &operator=(const QItemModelMapDataMapping &other); + + void setLabelRole(const QString &role); + QString labelRole() const; + void setXPosRole(const QString &role); + QString xPosRole() const; + void setYPosRole(const QString &role); + QString yPosRole() const; + void setValueRole(const QString &role); + QString valueRole() const; + + void remap(const QString &labelRole, const QString &xPosRole, + const QString &yPosRole, const QString &valueRole); +signals: + void mappingChanged(); + +private: + QScopedPointer<QItemModelMapDataMappingPrivate> d_ptr; +}; + + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qitemmodelmapdatamapping_p.h b/src/datavis3d/data/qitemmodelmapdatamapping_p.h new file mode 100644 index 00000000..99618942 --- /dev/null +++ b/src/datavis3d/data/qitemmodelmapdatamapping_p.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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. + +#include "qitemmodelmapdatamapping.h" + +#ifndef QITEMMODELMAPDATAMAPPING_P_H +#define QITEMMODELMAPDATAMAPPING_P_H + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelMapDataMappingPrivate : public QObject +{ + Q_OBJECT +public: + QItemModelMapDataMappingPrivate(QItemModelMapDataMapping *q); + virtual ~QItemModelMapDataMappingPrivate(); + +private: + QString m_labelRole; + QString m_xPosRole; + QString m_yPosRole; + QString m_valueRole; + + QItemModelMapDataMapping *q_ptr; + + friend class QItemModelMapDataMapping; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qitemmodelmapdataproxy.cpp b/src/datavis3d/data/qitemmodelmapdataproxy.cpp new file mode 100644 index 00000000..b41384e9 --- /dev/null +++ b/src/datavis3d/data/qitemmodelmapdataproxy.cpp @@ -0,0 +1,275 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qitemmodelmapdataproxy_p.h" +#include <QTimer> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QItemModelMapDataProxy::QItemModelMapDataProxy() : + QMapDataProxy(new QItemModelMapDataProxyPrivate(this)) +{ +} + +QItemModelMapDataProxy::QItemModelMapDataProxy(QAbstractItemModel *itemModel, + QItemModelMapDataMapping *mapping) : + QMapDataProxy(new QItemModelMapDataProxyPrivate(this)) +{ + dptr()->setItemModel(itemModel); + dptr()->setMapping(mapping); +} + +QItemModelMapDataProxy::~QItemModelMapDataProxy() +{ +} + +void QItemModelMapDataProxy::setItemModel(QAbstractItemModel *itemModel) +{ + dptr()->setItemModel(itemModel); +} + +QAbstractItemModel *QItemModelMapDataProxy::itemModel() +{ + return dptr()->m_itemModel.data(); +} + +void QItemModelMapDataProxy::setMapping(QItemModelMapDataMapping *mapping) +{ + dptr()->setMapping(mapping); +} + +QItemModelMapDataMapping *QItemModelMapDataProxy::mapping() +{ + return dptr()->m_mapping.data(); +} + +QItemModelMapDataProxyPrivate *QItemModelMapDataProxy::dptr() +{ + return static_cast<QItemModelMapDataProxyPrivate *>(d_ptr.data()); +} + +// QItemModelMapDataProxyPrivate + +QItemModelMapDataProxyPrivate::QItemModelMapDataProxyPrivate(QItemModelMapDataProxy *q) + : QMapDataProxyPrivate(q), + resolvePending(0) +{ + m_resolveTimer.setSingleShot(true); + QObject::connect(&m_resolveTimer, &QTimer::timeout, this, &QItemModelMapDataProxyPrivate::handlePendingResolve); +} + +QItemModelMapDataProxyPrivate::~QItemModelMapDataProxyPrivate() +{ +} + +void QItemModelMapDataProxyPrivate::setItemModel(QAbstractItemModel *itemModel) +{ + if (!m_itemModel.isNull()) + QObject::disconnect(m_itemModel, 0, this, 0); + + m_itemModel = itemModel; + + if (!m_itemModel.isNull()) { + QObject::connect(m_itemModel, &QAbstractItemModel::columnsInserted, this, &QItemModelMapDataProxyPrivate::handleColumnsInserted); + QObject::connect(m_itemModel, &QAbstractItemModel::columnsMoved, this, &QItemModelMapDataProxyPrivate::handleColumnsMoved); + QObject::connect(m_itemModel, &QAbstractItemModel::columnsRemoved, this, &QItemModelMapDataProxyPrivate::handleColumnsRemoved); + QObject::connect(m_itemModel, &QAbstractItemModel::dataChanged, this, &QItemModelMapDataProxyPrivate::handleDataChanged); + QObject::connect(m_itemModel, &QAbstractItemModel::layoutChanged, this, &QItemModelMapDataProxyPrivate::handleLayoutChanged); + QObject::connect(m_itemModel, &QAbstractItemModel::modelReset, this, &QItemModelMapDataProxyPrivate::handleModelReset); + QObject::connect(m_itemModel, &QAbstractItemModel::rowsInserted, this, &QItemModelMapDataProxyPrivate::handleRowsInserted); + QObject::connect(m_itemModel, &QAbstractItemModel::rowsMoved, this, &QItemModelMapDataProxyPrivate::handleRowsMoved); + QObject::connect(m_itemModel, &QAbstractItemModel::rowsRemoved, this, &QItemModelMapDataProxyPrivate::handleRowsRemoved); + } + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QItemModelMapDataProxyPrivate::setMapping(QItemModelMapDataMapping *mapping) +{ + if (!m_mapping.isNull()) + QObject::disconnect(m_mapping.data(), &QItemModelMapDataMapping::mappingChanged, this, &QItemModelMapDataProxyPrivate::handleMappingChanged); + + m_mapping = mapping; + + if (!m_mapping.isNull()) + QObject::connect(m_mapping.data(), &QItemModelMapDataMapping::mappingChanged, this, &QItemModelMapDataProxyPrivate::handleMappingChanged); + + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QItemModelMapDataProxyPrivate::handleColumnsInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve new items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn) +{ + Q_UNUSED(sourceParent) + Q_UNUSED(sourceStart) + Q_UNUSED(sourceEnd) + Q_UNUSED(destinationParent) + Q_UNUSED(destinationColumn) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleColumnsRemoved(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Remove old items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + Q_UNUSED(roles) + + // Resolve changed items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint) +{ + Q_UNUSED(parents) + Q_UNUSED(hint) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleModelReset() +{ + // Data cleared, reset array + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleRowsInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve new items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) +{ + Q_UNUSED(sourceParent) + Q_UNUSED(sourceStart) + Q_UNUSED(sourceEnd) + Q_UNUSED(destinationParent) + Q_UNUSED(destinationRow) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleRowsRemoved(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve removed items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelMapDataProxyPrivate::handleMappingChanged() +{ + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QItemModelMapDataProxyPrivate::handlePendingResolve() +{ + resolveModel(); +} + +// Resolve entire item model into QMapDataArray. +void QItemModelMapDataProxyPrivate::resolveModel() +{ + if (m_itemModel.isNull() || m_mapping.isNull()) { + qptr()->resetArray(0); + return; + } + + static const int noRoleIndex = -1; + + QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); + const int labelRole = roleHash.key(m_mapping->labelRole().toLatin1(), noRoleIndex); + const int xPosRole = roleHash.key(m_mapping->xPosRole().toLatin1(), noRoleIndex); + const int yPosRole = roleHash.key(m_mapping->yPosRole().toLatin1(), noRoleIndex); + // Default valueRole to display role if no mapping + const int valueRole = roleHash.key(m_mapping->valueRole().toLatin1(), Qt::DisplayRole); + const int columnCount = m_itemModel->columnCount(); + const int rowCount = m_itemModel->rowCount(); + const int totalCount = rowCount * columnCount; + int runningCount = 0; + + // Parse data into newProxyArray + QMapDataArray *newProxyArray = new QMapDataArray(totalCount); + for (int i = 0; i < rowCount; i++) { + for (int j = 0; j < columnCount; j++) { + QModelIndex index = m_itemModel->index(i, j); + if (labelRole != noRoleIndex) + (*newProxyArray)[runningCount].setLabel(index.data(labelRole).toString()); + qreal xPos(qreal(0.0)); + qreal yPos(qreal(0.0)); + if (xPosRole != noRoleIndex) + xPos = index.data(xPosRole).toReal(); + if (yPosRole != noRoleIndex) + yPos = index.data(yPosRole).toReal(); + (*newProxyArray)[runningCount].setMapPosition(QPointF(xPos, yPos)); + (*newProxyArray)[runningCount].setValue(index.data(valueRole).toReal()); + runningCount++; + } + } + + qDebug() << __FUNCTION__ << "Total count:" << newProxyArray->size(); + + qptr()->resetArray(newProxyArray); +} + +QItemModelMapDataProxy *QItemModelMapDataProxyPrivate::qptr() +{ + return static_cast<QItemModelMapDataProxy *>(q_ptr); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qitemmodelmapdataproxy.h b/src/datavis3d/data/qitemmodelmapdataproxy.h new file mode 100644 index 00000000..784ee162 --- /dev/null +++ b/src/datavis3d/data/qitemmodelmapdataproxy.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QITEMMODELMAPDATAPROXY_H +#define QITEMMODELMAPDATAPROXY_H + +#include <QtDataVis3D/qmapdataproxy.h> +#include <QtDataVis3D/qitemmodelmapdatamapping.h> +#include <QAbstractItemModel> +#include <QStringList> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelMapDataProxyPrivate; + +class QT_DATAVIS3D_EXPORT QItemModelMapDataProxy : public QMapDataProxy +{ + Q_OBJECT + +public: + explicit QItemModelMapDataProxy(); + explicit QItemModelMapDataProxy(QAbstractItemModel *itemModel, QItemModelMapDataMapping *mapping); + virtual ~QItemModelMapDataProxy(); + + // Doesn't gain ownership of the model, but does connect to it to listen for data changes. + void setItemModel(QAbstractItemModel *itemModel); + QAbstractItemModel *itemModel(); + + // Map maps role (label, xPos, yPos, value) to role in model + // Doesn't gain ownership of mapping, but does connect to it to listen for mapping changes. + // Modifying mapping that is set to proxy will trigger dataset re-resolving. + void setMapping(QItemModelMapDataMapping *mapping); + QItemModelMapDataMapping *mapping(); + +protected: + QItemModelMapDataProxyPrivate *dptr(); + +private: + Q_DISABLE_COPY(QItemModelMapDataProxy) +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qitemmodelmapdataproxy_p.h b/src/datavis3d/data/qitemmodelmapdataproxy_p.h new file mode 100644 index 00000000..64b16c7f --- /dev/null +++ b/src/datavis3d/data/qitemmodelmapdataproxy_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 QITEMMODELMAPDATAPROXY_P_H +#define QITEMMODELMAPDATAPROXY_P_H + +#include "qitemmodelmapdataproxy.h" +#include "qMapDataProxy_p.h" +#include <QPointer> +#include <QTimer> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelMapDataProxyPrivate : public QMapDataProxyPrivate +{ + Q_OBJECT +public: + QItemModelMapDataProxyPrivate(QItemModelMapDataProxy *q); + virtual ~QItemModelMapDataProxyPrivate(); + + void setItemModel(QAbstractItemModel *itemModel); + void setMapping(QItemModelMapDataMapping *mapping); + +public slots: + void handleColumnsInserted(const QModelIndex &parent, int start, int end); + void handleColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, + const QModelIndex &destinationParent, int destinationColumn); + void handleColumnsRemoved(const QModelIndex &parent, int start, int end); + void handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, + const QVector<int> &roles = QVector<int> ()); + void handleLayoutChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex> (), + QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); + void handleModelReset(); + void handleRowsInserted(const QModelIndex &parent, int start, int end); + void handleRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, + const QModelIndex &destinationParent, int destinationRow); + void handleRowsRemoved(const QModelIndex &parent, int start, int end); + + void handleMappingChanged(); + void handlePendingResolve(); + +private: + void resolveModel(); + QItemModelMapDataProxy *qptr(); + + QPointer<QAbstractItemModel> m_itemModel; // Not owned + QPointer<QItemModelMapDataMapping> m_mapping; // Not owned + bool resolvePending; + QTimer m_resolveTimer; + + friend class QItemModelMapDataProxy; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qitemmodelscatterdatamapping.cpp b/src/datavis3d/data/qitemmodelscatterdatamapping.cpp new file mode 100644 index 00000000..0b430b79 --- /dev/null +++ b/src/datavis3d/data/qitemmodelscatterdatamapping.cpp @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qitemmodelscatterdatamapping_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QItemModelScatterDataMapping::QItemModelScatterDataMapping() + : QObject(0), + d_ptr(new QItemModelScatterDataMappingPrivate(this)) +{ +} + +QItemModelScatterDataMapping::QItemModelScatterDataMapping( + const QItemModelScatterDataMapping &other) + : QObject(0), + d_ptr(new QItemModelScatterDataMappingPrivate(this)) +{ + operator=(other); +} + +QItemModelScatterDataMapping::QItemModelScatterDataMapping(const QString &labelRole, + const QString &xPosRole, + const QString &yPosRole, + const QString &zPosRole, + const QString &valueRole) + : QObject(0), + d_ptr(new QItemModelScatterDataMappingPrivate(this)) +{ + Q_UNUSED(labelRole); + Q_UNUSED(valueRole); + //d_ptr->m_labelRole = labelRole; + d_ptr->m_xPosRole = xPosRole; + d_ptr->m_yPosRole = yPosRole; + d_ptr->m_zPosRole = zPosRole; + //d_ptr->m_valueRole = valueRole; +} + +QItemModelScatterDataMapping::~QItemModelScatterDataMapping() +{ +} + +QItemModelScatterDataMapping &QItemModelScatterDataMapping::operator=( + const QItemModelScatterDataMapping &other) +{ + //d_ptr->m_labelRole = other.d_ptr->m_labelRole; + d_ptr->m_xPosRole = other.d_ptr->m_xPosRole; + d_ptr->m_yPosRole = other.d_ptr->m_yPosRole; + d_ptr->m_zPosRole = other.d_ptr->m_zPosRole; + //d_ptr->m_valueRole = other.d_ptr->m_valueRole; + + return *this; +} + +//void QItemModelScatterDataMapping::setLabelRole(const QString &role) +//{ +// d_ptr->m_labelRole = role; +// emit mappingChanged(); +//} + +//QString QItemModelScatterDataMapping::labelRole() const +//{ +// return d_ptr->m_labelRole; +//} + +void QItemModelScatterDataMapping::setXPosRole(const QString &role) +{ + d_ptr->m_xPosRole = role; + emit mappingChanged(); +} + +QString QItemModelScatterDataMapping::xPosRole() const +{ + return d_ptr->m_xPosRole; +} + +void QItemModelScatterDataMapping::setYPosRole(const QString &role) +{ + d_ptr->m_yPosRole = role; + emit mappingChanged(); +} + +QString QItemModelScatterDataMapping::yPosRole() const +{ + return d_ptr->m_yPosRole; +} + +void QItemModelScatterDataMapping::setZPosRole(const QString &role) +{ + d_ptr->m_zPosRole = role; + emit mappingChanged(); +} + +QString QItemModelScatterDataMapping::zPosRole() const +{ + return d_ptr->m_zPosRole; +} + +//void QItemModelScatterDataMapping::setValueRole(const QString &role) +//{ +// d_ptr->m_valueRole = role; +// emit mappingChanged(); +//} + +//QString QItemModelScatterDataMapping::valueRole() const +//{ +// return d_ptr->m_valueRole; +//} + +void QItemModelScatterDataMapping::remap(const QString &labelRole, const QString &xPosRole, + const QString &yPosRole, const QString &zPosRole, + const QString &valueRole) +{ + Q_UNUSED(labelRole); + Q_UNUSED(valueRole); + //d_ptr->m_labelRole = labelRole; + d_ptr->m_xPosRole = xPosRole; + d_ptr->m_yPosRole = yPosRole; + d_ptr->m_zPosRole = zPosRole; + //d_ptr->m_valueRole = valueRole; + + emit mappingChanged(); +} + +// QItemModelScatterDataMappingPrivate + +QItemModelScatterDataMappingPrivate::QItemModelScatterDataMappingPrivate( + QItemModelScatterDataMapping *q) + : QObject(0), + q_ptr(q) +{ +} + +QItemModelScatterDataMappingPrivate::~QItemModelScatterDataMappingPrivate() +{ +} + +QT_DATAVIS3D_END_NAMESPACE + diff --git a/src/datavis3d/data/qitemmodelscatterdatamapping.h b/src/datavis3d/data/qitemmodelscatterdatamapping.h new file mode 100644 index 00000000..f4a2cfe6 --- /dev/null +++ b/src/datavis3d/data/qitemmodelscatterdatamapping.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QITEMMODELSCATTERDATAMAPPING_H +#define QITEMMODELSCATTERDATAMAPPING_H + +#include <QtDataVis3D/qdatavis3denums.h> +#include <QObject> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelScatterDataMappingPrivate; + +class QT_DATAVIS3D_EXPORT QItemModelScatterDataMapping : public QObject +{ + Q_OBJECT + //Q_PROPERTY(QString labelRole READ labelRole WRITE setLabelRole) + Q_PROPERTY(QString xPosRole READ xPosRole WRITE setXPosRole) + Q_PROPERTY(QString yPosRole READ yPosRole WRITE setYPosRole) + Q_PROPERTY(QString zPosRole READ zPosRole WRITE setZPosRole) + //Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole) +public: + explicit QItemModelScatterDataMapping(); + QItemModelScatterDataMapping(const QItemModelScatterDataMapping &other); + QItemModelScatterDataMapping(const QString &labelRole, const QString &xPosRole, + const QString &yPosRole, const QString &zPosRole, + const QString &valueRole); + virtual ~QItemModelScatterDataMapping(); + + QItemModelScatterDataMapping &operator=(const QItemModelScatterDataMapping &other); + + //void setLabelRole(const QString &role); + //QString labelRole() const; + void setXPosRole(const QString &role); + QString xPosRole() const; + void setYPosRole(const QString &role); + QString yPosRole() const; + void setZPosRole(const QString &role); + QString zPosRole() const; + //void setValueRole(const QString &role); + //QString valueRole() const; + + void remap(const QString &labelRole, const QString &xPosRole, + const QString &yPosRole, const QString &zPosRole, const QString &valueRole); +signals: + void mappingChanged(); + +private: + QScopedPointer<QItemModelScatterDataMappingPrivate> d_ptr; +}; + + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qitemmodelscatterdatamapping_p.h b/src/datavis3d/data/qitemmodelscatterdatamapping_p.h new file mode 100644 index 00000000..90a826c0 --- /dev/null +++ b/src/datavis3d/data/qitemmodelscatterdatamapping_p.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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. + +#include "qitemmodelscatterdatamapping.h" + +#ifndef QITEMMODELSCATTERDATAMAPPING_P_H +#define QITEMMODELSCATTERDATAMAPPING_P_H + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelScatterDataMappingPrivate : public QObject +{ + Q_OBJECT +public: + QItemModelScatterDataMappingPrivate(QItemModelScatterDataMapping *q); + virtual ~QItemModelScatterDataMappingPrivate(); + +private: + //QString m_labelRole; + QString m_xPosRole; + QString m_yPosRole; + QString m_zPosRole; + //QString m_valueRole; + + QItemModelScatterDataMapping *q_ptr; + + friend class QItemModelScatterDataMapping; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qitemmodelscatterdataproxy.cpp b/src/datavis3d/data/qitemmodelscatterdataproxy.cpp new file mode 100644 index 00000000..c4f4f0a7 --- /dev/null +++ b/src/datavis3d/data/qitemmodelscatterdataproxy.cpp @@ -0,0 +1,305 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qitemmodelscatterdataproxy_p.h" +#include <QTimer> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QItemModelScatterDataProxy::QItemModelScatterDataProxy() : + QScatterDataProxy(new QItemModelScatterDataProxyPrivate(this)) +{ +} + +QItemModelScatterDataProxy::QItemModelScatterDataProxy(QAbstractItemModel *itemModel, + QItemModelScatterDataMapping *mapping) : + QScatterDataProxy(new QItemModelScatterDataProxyPrivate(this)) +{ + dptr()->setItemModel(itemModel); + dptr()->setMapping(mapping); +} + +QItemModelScatterDataProxy::~QItemModelScatterDataProxy() +{ +} + +void QItemModelScatterDataProxy::setItemModel(QAbstractItemModel *itemModel) +{ + dptr()->setItemModel(itemModel); +} + +QAbstractItemModel *QItemModelScatterDataProxy::itemModel() +{ + return dptr()->m_itemModel.data(); +} + +void QItemModelScatterDataProxy::setMapping(QItemModelScatterDataMapping *mapping) +{ + dptr()->setMapping(mapping); +} + +QItemModelScatterDataMapping *QItemModelScatterDataProxy::mapping() +{ + return dptr()->m_mapping.data(); +} + +QItemModelScatterDataProxyPrivate *QItemModelScatterDataProxy::dptr() +{ + return static_cast<QItemModelScatterDataProxyPrivate *>(d_ptr.data()); +} + +// QItemModelScatterDataProxyPrivate + +QItemModelScatterDataProxyPrivate::QItemModelScatterDataProxyPrivate(QItemModelScatterDataProxy *q) + : QScatterDataProxyPrivate(q), + resolvePending(0) +{ + m_resolveTimer.setSingleShot(true); + QObject::connect(&m_resolveTimer, &QTimer::timeout, this, + &QItemModelScatterDataProxyPrivate::handlePendingResolve); +} + +QItemModelScatterDataProxyPrivate::~QItemModelScatterDataProxyPrivate() +{ +} + +void QItemModelScatterDataProxyPrivate::setItemModel(QAbstractItemModel *itemModel) +{ + if (!m_itemModel.isNull()) + QObject::disconnect(m_itemModel, 0, this, 0); + + m_itemModel = itemModel; + + if (!m_itemModel.isNull()) { + QObject::connect(m_itemModel, &QAbstractItemModel::columnsInserted, this, + &QItemModelScatterDataProxyPrivate::handleColumnsInserted); + QObject::connect(m_itemModel, &QAbstractItemModel::columnsMoved, this, + &QItemModelScatterDataProxyPrivate::handleColumnsMoved); + QObject::connect(m_itemModel, &QAbstractItemModel::columnsRemoved, this, + &QItemModelScatterDataProxyPrivate::handleColumnsRemoved); + QObject::connect(m_itemModel, &QAbstractItemModel::dataChanged, this, + &QItemModelScatterDataProxyPrivate::handleDataChanged); + QObject::connect(m_itemModel, &QAbstractItemModel::layoutChanged, this, + &QItemModelScatterDataProxyPrivate::handleLayoutChanged); + QObject::connect(m_itemModel, &QAbstractItemModel::modelReset, this, + &QItemModelScatterDataProxyPrivate::handleModelReset); + QObject::connect(m_itemModel, &QAbstractItemModel::rowsInserted, this, + &QItemModelScatterDataProxyPrivate::handleRowsInserted); + QObject::connect(m_itemModel, &QAbstractItemModel::rowsMoved, this, + &QItemModelScatterDataProxyPrivate::handleRowsMoved); + QObject::connect(m_itemModel, &QAbstractItemModel::rowsRemoved, this, + &QItemModelScatterDataProxyPrivate::handleRowsRemoved); + } + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QItemModelScatterDataProxyPrivate::setMapping(QItemModelScatterDataMapping *mapping) +{ + if (!m_mapping.isNull()) + QObject::disconnect(m_mapping.data(), &QItemModelScatterDataMapping::mappingChanged, this, + &QItemModelScatterDataProxyPrivate::handleMappingChanged); + + m_mapping = mapping; + + if (!m_mapping.isNull()) + QObject::connect(m_mapping.data(), &QItemModelScatterDataMapping::mappingChanged, this, + &QItemModelScatterDataProxyPrivate::handleMappingChanged); + + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QItemModelScatterDataProxyPrivate::handleColumnsInserted(const QModelIndex &parent, + int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve new items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelScatterDataProxyPrivate::handleColumnsMoved(const QModelIndex &sourceParent, + int sourceStart, int sourceEnd, + const QModelIndex &destinationParent, + int destinationColumn) +{ + Q_UNUSED(sourceParent) + Q_UNUSED(sourceStart) + Q_UNUSED(sourceEnd) + Q_UNUSED(destinationParent) + Q_UNUSED(destinationColumn) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelScatterDataProxyPrivate::handleColumnsRemoved(const QModelIndex &parent, + int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Remove old items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelScatterDataProxyPrivate::handleDataChanged(const QModelIndex &topLeft, + const QModelIndex &bottomRight, + const QVector<int> &roles) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + Q_UNUSED(roles) + + // Resolve changed items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelScatterDataProxyPrivate::handleLayoutChanged( + const QList<QPersistentModelIndex> &parents, + QAbstractItemModel::LayoutChangeHint hint) +{ + Q_UNUSED(parents) + Q_UNUSED(hint) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelScatterDataProxyPrivate::handleModelReset() +{ + // Data cleared, reset array + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelScatterDataProxyPrivate::handleRowsInserted(const QModelIndex &parent, + int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve new items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelScatterDataProxyPrivate::handleRowsMoved(const QModelIndex &sourceParent, + int sourceStart, int sourceEnd, + const QModelIndex &destinationParent, + int destinationRow) +{ + Q_UNUSED(sourceParent) + Q_UNUSED(sourceStart) + Q_UNUSED(sourceEnd) + Q_UNUSED(destinationParent) + Q_UNUSED(destinationRow) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelScatterDataProxyPrivate::handleRowsRemoved(const QModelIndex &parent, + int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve removed items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void QItemModelScatterDataProxyPrivate::handleMappingChanged() +{ + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QItemModelScatterDataProxyPrivate::handlePendingResolve() +{ + resolveModel(); +} + +// Resolve entire item model into QScatterDataArray. +void QItemModelScatterDataProxyPrivate::resolveModel() +{ + if (m_itemModel.isNull() || m_mapping.isNull()) { + qptr()->resetArray(0); + return; + } + + static const int noRoleIndex = -1; + + QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); + //const int labelRole = roleHash.key(m_mapping->labelRole().toLatin1(), noRoleIndex); + const int xPosRole = roleHash.key(m_mapping->xPosRole().toLatin1(), noRoleIndex); + const int yPosRole = roleHash.key(m_mapping->yPosRole().toLatin1(), noRoleIndex); + const int zPosRole = roleHash.key(m_mapping->zPosRole().toLatin1(), noRoleIndex); + // Default valueRole to display role if no mapping + //const int valueRole = roleHash.key(m_mapping->valueRole().toLatin1(), Qt::DisplayRole); + const int columnCount = m_itemModel->columnCount(); + const int rowCount = m_itemModel->rowCount(); + const int totalCount = rowCount * columnCount; + int runningCount = 0; + + // Parse data into newProxyArray + QScatterDataArray *newProxyArray = new QScatterDataArray(totalCount); + for (int i = 0; i < rowCount; i++) { + for (int j = 0; j < columnCount; j++) { + QModelIndex index = m_itemModel->index(i, j); + //if (labelRole != noRoleIndex) + // (*newProxyArray)[runningCount].setLabel(index.data(labelRole).toString()); + float xPos(0.0f); + float yPos(0.0f); + float zPos(0.0f); + if (xPosRole != noRoleIndex) + xPos = index.data(xPosRole).toFloat(); + if (yPosRole != noRoleIndex) + yPos = index.data(yPosRole).toFloat(); + if (zPosRole != noRoleIndex) + zPos = index.data(zPosRole).toFloat(); + (*newProxyArray)[runningCount].setPosition(QVector3D(xPos, yPos, zPos)); + //(*newProxyArray)[runningCount].setValue(index.data(valueRole).toReal()); + runningCount++; + } + } + + qDebug() << __FUNCTION__ << "Total count:" << newProxyArray->size(); + + qptr()->resetArray(newProxyArray); +} + +QItemModelScatterDataProxy *QItemModelScatterDataProxyPrivate::qptr() +{ + return static_cast<QItemModelScatterDataProxy *>(q_ptr); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qitemmodelscatterdataproxy.h b/src/datavis3d/data/qitemmodelscatterdataproxy.h new file mode 100644 index 00000000..f609e84b --- /dev/null +++ b/src/datavis3d/data/qitemmodelscatterdataproxy.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QITEMMODELSCATTERDATAPROXY_H +#define QITEMMODELSCATTERDATAPROXY_H + +#include <QtDataVis3D/qscatterdataproxy.h> +#include <QtDataVis3D/qitemmodelscatterdatamapping.h> +#include <QAbstractItemModel> +#include <QStringList> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelScatterDataProxyPrivate; + +class QT_DATAVIS3D_EXPORT QItemModelScatterDataProxy : public QScatterDataProxy +{ + Q_OBJECT + +public: + explicit QItemModelScatterDataProxy(); + explicit QItemModelScatterDataProxy(QAbstractItemModel *itemModel, + QItemModelScatterDataMapping *mapping); + virtual ~QItemModelScatterDataProxy(); + + // Doesn't gain ownership of the model, but does connect to it to listen for data changes. + void setItemModel(QAbstractItemModel *itemModel); + QAbstractItemModel *itemModel(); + + // Map scatter role (xPos, yPos, zPos) to role in model + // Doesn't gain ownership of mapping, but does connect to it to listen for mapping changes. + // Modifying mapping that is set to proxy will trigger dataset re-resolving. + void setMapping(QItemModelScatterDataMapping *mapping); + QItemModelScatterDataMapping *mapping(); + +protected: + QItemModelScatterDataProxyPrivate *dptr(); + +private: + Q_DISABLE_COPY(QItemModelScatterDataProxy) +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qitemmodelscatterdataproxy_p.h b/src/datavis3d/data/qitemmodelscatterdataproxy_p.h new file mode 100644 index 00000000..aed3d974 --- /dev/null +++ b/src/datavis3d/data/qitemmodelscatterdataproxy_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 QITEMMODELSCATTERDATAPROXY_P_H +#define QITEMMODELSCATTERDATAPROXY_P_H + +#include "qitemmodelscatterdataproxy.h" +#include "qscatterdataproxy_p.h" +#include <QPointer> +#include <QTimer> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QItemModelScatterDataProxyPrivate : public QScatterDataProxyPrivate +{ + Q_OBJECT +public: + QItemModelScatterDataProxyPrivate(QItemModelScatterDataProxy *q); + virtual ~QItemModelScatterDataProxyPrivate(); + + void setItemModel(QAbstractItemModel *itemModel); + void setMapping(QItemModelScatterDataMapping *mapping); + +public slots: + void handleColumnsInserted(const QModelIndex &parent, int start, int end); + void handleColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, + const QModelIndex &destinationParent, int destinationColumn); + void handleColumnsRemoved(const QModelIndex &parent, int start, int end); + void handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, + const QVector<int> &roles = QVector<int> ()); + void handleLayoutChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex> (), + QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); + void handleModelReset(); + void handleRowsInserted(const QModelIndex &parent, int start, int end); + void handleRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, + const QModelIndex &destinationParent, int destinationRow); + void handleRowsRemoved(const QModelIndex &parent, int start, int end); + + void handleMappingChanged(); + void handlePendingResolve(); + +private: + void resolveModel(); + QItemModelScatterDataProxy *qptr(); + + QPointer<QAbstractItemModel> m_itemModel; // Not owned + QPointer<QItemModelScatterDataMapping> m_mapping; // Not owned + bool resolvePending; + QTimer m_resolveTimer; + + friend class QItemModelScatterDataProxy; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qmapdataitem.cpp b/src/datavis3d/data/qmapdataitem.cpp new file mode 100644 index 00000000..2fe9b6e8 --- /dev/null +++ b/src/datavis3d/data/qmapdataitem.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qmapdataitem_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +/*! + * \class QMapDataItem + * \inmodule QtDataVis3D + * \brief The QMapDataItem class provides a container for resolved data to be added to maps graphs. + * \since 1.0.0 + * + * A QMapDataItem holds data for a single rendered bar in a maps graph. + * Maps data proxies parse data into QMapDataItem instances for visualizing. + * + * \sa QMapDataProxy, {Qt Data Visualization 3D C++ Classes} + */ + +/*! + * Constructs QMapDataItem. + */ +QMapDataItem::QMapDataItem() + : QBarDataItem() +{ +} + +QMapDataItem::QMapDataItem(const QMapDataItem &other) + : QBarDataItem(other) +{ + operator=(other); +} + +/*! + * Destroys QMapDataItem. + */ +QMapDataItem::~QMapDataItem() +{ +} + +QMapDataItem &QMapDataItem::operator=(const QMapDataItem &other) +{ + QBarDataItem::operator =(other); + m_mapPosition = other.m_mapPosition; + m_label = other.m_label; + + return *this; +} + +void QMapDataItem::setMapPosition(const QPointF &position) +{ + m_mapPosition = position; +} + +QPointF QMapDataItem::mapPosition() const +{ + return m_mapPosition; +} + +void QMapDataItem::setLabel(const QString &label) +{ + m_label = label; +} + +QString QMapDataItem::label() const +{ + return m_label; +} + +void QMapDataItem::createExtraData() +{ + if (!d_ptr) + d_ptr = new QMapDataItemPrivate; +} + +QMapDataItemPrivate::QMapDataItemPrivate() + : QBarDataItemPrivate() +{ +} + +QMapDataItemPrivate::~QMapDataItemPrivate() +{ +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qmapdataitem.h b/src/datavis3d/data/qmapdataitem.h new file mode 100644 index 00000000..240b03dd --- /dev/null +++ b/src/datavis3d/data/qmapdataitem.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QMAPDATAITEM_H +#define QMAPDATAITEM_H + +#include <QtDataVis3D/qdatavis3denums.h> +#include <QtDataVis3D/qbardataitem.h> +#include <QPointF> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QMapDataItemPrivate; + +class QT_DATAVIS3D_EXPORT QMapDataItem : public QBarDataItem +{ +public: + QMapDataItem(); + QMapDataItem(const QMapDataItem &other); + ~QMapDataItem(); + + QMapDataItem &operator=(const QMapDataItem &other); + + void setMapPosition(const QPointF &position); + QPointF mapPosition() const; + + void setLabel(const QString &label); + QString label() const; + +protected: + virtual void createExtraData(); + + QMapDataItemPrivate *d_ptr; + +private: + QPointF m_mapPosition; + QString m_label; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qmapdataitem_p.h b/src/datavis3d/data/qmapdataitem_p.h new file mode 100644 index 00000000..2926e3ef --- /dev/null +++ b/src/datavis3d/data/qmapdataitem_p.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 QMAPDATAITEM_P_H +#define QMAPDATAITEM_P_H + +#include "datavis3dglobal_p.h" +#include "qmapdataitem.h" +#include "qbardataitem_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QMapDataItemPrivate : public QBarDataItemPrivate +{ +public: + QMapDataItemPrivate(); + virtual ~QMapDataItemPrivate(); + + // TODO stores other data for map items besides position + +protected: + friend class QMapDataItem; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qmapdataproxy.cpp b/src/datavis3d/data/qmapdataproxy.cpp new file mode 100644 index 00000000..a7a0e9d5 --- /dev/null +++ b/src/datavis3d/data/qmapdataproxy.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qmapdataproxy.h" +#include "qmapdataproxy_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QMapDataProxy::QMapDataProxy() : + QAbstractDataProxy(new QMapDataProxyPrivate(this)) +{ +} + +QMapDataProxy::QMapDataProxy(QMapDataProxyPrivate *d) : + QAbstractDataProxy(d) +{ +} + +QMapDataProxy::~QMapDataProxy() +{ +} + +void QMapDataProxy::resetArray(QMapDataArray *newArray) +{ + if (dptr()->resetArray(newArray)) + emit arrayReset(); +} + + +int QMapDataProxy::itemCount() const +{ + return dptrc()->m_dataArray.size(); +} + +const QMapDataArray *QMapDataProxy::array() const +{ + return &dptrc()->m_dataArray; +} + +const QMapDataItem *QMapDataProxy::itemAt(int index) const +{ + return &dptrc()->m_dataArray.at(index); +} + +QMapDataProxyPrivate *QMapDataProxy::dptr() +{ + return static_cast<QMapDataProxyPrivate *>(d_ptr.data()); +} + +const QMapDataProxyPrivate *QMapDataProxy::dptrc() const +{ + return static_cast<const QMapDataProxyPrivate *>(d_ptr.data()); +} + +// QBarDataProxyPrivate + +QMapDataProxyPrivate::QMapDataProxyPrivate(QMapDataProxy *q) + : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeMap) +{ +} + +QMapDataProxyPrivate::~QMapDataProxyPrivate() +{ + m_dataArray.clear(); +} + +bool QMapDataProxyPrivate::resetArray(QMapDataArray *newArray) +{ + if (!m_dataArray.size() && (!newArray || !newArray->size())) + return false; + + m_dataArray.clear(); + + if (newArray) { + m_dataArray = *newArray; + delete newArray; + } + + return true; +} + +QPair<GLfloat, GLfloat> QMapDataProxyPrivate::limitValues() +{ + QPair<GLfloat, GLfloat> limits = qMakePair(0.0f, 0.0f); + for (int i = 0; i < m_dataArray.size(); i++) { + const QMapDataItem &item = m_dataArray.at(i); + qreal itemValue = item.value(); + if (limits.second < itemValue) + limits.second = itemValue; + if (limits.first > itemValue) + limits.first = itemValue; + } + return limits; +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qmapdataproxy.h b/src/datavis3d/data/qmapdataproxy.h new file mode 100644 index 00000000..45bb95d5 --- /dev/null +++ b/src/datavis3d/data/qmapdataproxy.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QMAPDATAPROXY_H +#define QMAPDATAPROXY_H + +#include <QtDataVis3D/qabstractdataproxy.h> +#include <QtDataVis3D/qmapdataitem.h> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +typedef QVector<QMapDataItem> QMapDataArray; + +class QMapDataProxyPrivate; + +class QT_DATAVIS3D_EXPORT QMapDataProxy : public QAbstractDataProxy +{ + Q_OBJECT + +public: + explicit QMapDataProxy(); + explicit QMapDataProxy(QMapDataProxyPrivate *d); + virtual ~QMapDataProxy(); + + // QMapDataProxy is also optimized to use cases where the only defining characteristics of an individual + // map item are it's value and position. Modifying other data such as color or mesh of individual bar + // requires allocating additional data object for the bar. + + // Item pointers are guaranteed to be valid only until next call that modifies data. + // Array pointer is guaranteed to be valid for lifetime of proxy. + int itemCount() const; + const QMapDataArray *array() const; + const QMapDataItem *itemAt(int index) const; // Index needs to exist or this crashes + + // TODO Should data manipulation/access methods be protected rather than public to enforce subclassing use of proxy? + // TODO Leaving them public gives user more options. + + // QMapDataProxy takes ownership of all QMapDataArrays and QMapDataItems passed to it. + + // Clears the existing array and sets it data to new array. + void resetArray(QMapDataArray *newArray); + + // TODO void setItem(int index, QMapDataItem *item); + // TODO void setItems(int index, QMapDataArray *items); + + // TODO int addItem(QMapDataItem *item); // returns the index of added item + // TODO int addItems(QMapDataArray *items); // returns the index of added item + + // TODO void insertItem(int index, QMapDataItem *item); + // TODO void insertItems(int index, QMapDataArray *items); + + // TODO void removeItems(int index, int removeCount); + +signals: + void arrayReset(); + void itemsAdded(int startIndex, int count); + void itemsChanged(int startIndex, int count); + void itemsRemoved(int startIndex, int count); // Index may be over current array size if removed from end + void itemsInserted(int startIndex, int count); + +protected: + QMapDataProxyPrivate *dptr(); + const QMapDataProxyPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QMapDataProxy) + + friend class Maps3DController; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qmapdataproxy_p.h b/src/datavis3d/data/qmapdataproxy_p.h new file mode 100644 index 00000000..bf3d1d2c --- /dev/null +++ b/src/datavis3d/data/qmapdataproxy_p.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 QMAPDATAPROXY_P_H +#define QMAPDATAPROXY_P_H + +#include "qmapdataproxy.h" +#include "qabstractdataproxy_p.h" +#include "qmapdataitem.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QMapDataProxyPrivate : public QAbstractDataProxyPrivate +{ + Q_OBJECT +public: + QMapDataProxyPrivate(QMapDataProxy *q); + virtual ~QMapDataProxyPrivate(); + + bool resetArray(QMapDataArray *newArray); + + QPair<GLfloat, GLfloat> limitValues(); + +private: + QMapDataArray m_dataArray; + +private: + friend class QMapDataProxy; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QBARDATAPROXY_P_H diff --git a/src/datavis3d/data/qscatterdataitem.cpp b/src/datavis3d/data/qscatterdataitem.cpp new file mode 100644 index 00000000..e2580339 --- /dev/null +++ b/src/datavis3d/data/qscatterdataitem.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qscatterdataitem_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +/*! + * \class QScatterDataItem + * \inmodule QtDataVis3D + * \brief The QScatterDataItem class provides a container for resolved data to be added to scatter + * graphs. + * \since 1.0.0 + * + * A QScatterDataItem holds data for a single rendered item in a scatter graph. + * Scatter data proxies parse data into QScatterDataItem instances for visualizing. + * + * \sa QScatterDataProxy, {Qt Data Visualization 3D C++ Classes} + */ + +/*! + * Constructs QScatterDataItem. + */ +QScatterDataItem::QScatterDataItem() + : d_ptr(0) // private data doesn't exist by default (optimization) + +{ +} + +QScatterDataItem::QScatterDataItem(const QVector3D &position) + : d_ptr(0), + m_position(position) +{ +} + +QScatterDataItem::QScatterDataItem(const QScatterDataItem &other) +{ + operator=(other); +} + +/*! + * Destroys QScatterDataItem. + */ +QScatterDataItem::~QScatterDataItem() +{ +} + +QScatterDataItem &QScatterDataItem::operator=(const QScatterDataItem &other) +{ + m_position = other.m_position; + //m_size = other.m_size; + + if (other.d_ptr) + createExtraData(); + else + d_ptr = 0; + // TODO set extra data + + return *this; +} + +void QScatterDataItem::setPosition(const QVector3D &position) +{ + m_position = position; +} + +const QVector3D &QScatterDataItem::position() const +{ + return m_position; +} + +//void QScatterDataItem::setSize(qreal size) +//{ +// m_size = size; +//} + +//const qreal &QScatterDataItem::size() const +//{ +// return m_size; +//} + +void QScatterDataItem::createExtraData() +{ + if (!d_ptr) + d_ptr = new QScatterDataItemPrivate; +} + +QScatterDataItemPrivate::QScatterDataItemPrivate() +{ +} + +QScatterDataItemPrivate::~QScatterDataItemPrivate() +{ +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qscatterdataitem.h b/src/datavis3d/data/qscatterdataitem.h new file mode 100644 index 00000000..82383ae6 --- /dev/null +++ b/src/datavis3d/data/qscatterdataitem.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QSCATTERDATAITEM_H +#define QSCATTERDATAITEM_H + +#include <QtDataVis3D/qdatavis3denums.h> +#include <QVector3D> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QScatterDataItemPrivate; + +class QT_DATAVIS3D_EXPORT QScatterDataItem +{ +public: + QScatterDataItem(); + QScatterDataItem(const QVector3D &position); + QScatterDataItem(const QScatterDataItem &other); + ~QScatterDataItem(); + + QScatterDataItem &operator=(const QScatterDataItem &other); + + void setPosition(const QVector3D &position); + const QVector3D &position() const; + + //void setSize(qreal size); + //qreal size() const; + +protected: + virtual void createExtraData(); + + QScatterDataItemPrivate *d_ptr; + +private: + QVector3D m_position; + //qreal m_size; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qscatterdataitem_p.h b/src/datavis3d/data/qscatterdataitem_p.h new file mode 100644 index 00000000..3718a185 --- /dev/null +++ b/src/datavis3d/data/qscatterdataitem_p.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 QSCATTERDATAITEM_P_H +#define QSCATTERDATAITEM_P_H + +#include "datavis3dglobal_p.h" +#include "qscatterdataitem.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QScatterDataItemPrivate +{ +public: + QScatterDataItemPrivate(); + virtual ~QScatterDataItemPrivate(); + + // TODO stores other data for scatter items besides position + +protected: + friend class QScatterDataItem; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qscatterdataproxy.cpp b/src/datavis3d/data/qscatterdataproxy.cpp new file mode 100644 index 00000000..d2f544ef --- /dev/null +++ b/src/datavis3d/data/qscatterdataproxy.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qscatterdataproxy.h" +#include "qscatterdataproxy_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +QScatterDataProxy::QScatterDataProxy() : + QAbstractDataProxy(new QScatterDataProxyPrivate(this)) +{ +} + +QScatterDataProxy::QScatterDataProxy(QScatterDataProxyPrivate *d) : + QAbstractDataProxy(d) +{ +} + +QScatterDataProxy::~QScatterDataProxy() +{ +} + +void QScatterDataProxy::resetArray(QScatterDataArray *newArray) +{ + if (dptr()->resetArray(newArray)) + emit arrayReset(); +} + +void QScatterDataProxy::setItem(int index, const QScatterDataItem &item) +{ + dptr()->setItem(index, item); + emit itemsChanged(index, 1); +} + +void QScatterDataProxy::setItems(int index, const QScatterDataArray &items) +{ + dptr()->setItems(index, items); + emit itemsChanged(index, items.size()); +} + +int QScatterDataProxy::addItem(const QScatterDataItem &item) +{ + int addIndex = dptr()->addItem(item); + emit itemsAdded(addIndex, 1); + return addIndex; +} + +int QScatterDataProxy::addItems(const QScatterDataArray &items) +{ + int addIndex = dptr()->addItems(items); + emit itemsAdded(addIndex, items.size()); + return addIndex; +} + +void QScatterDataProxy::insertItem(int index, const QScatterDataItem &item) +{ + dptr()->insertItem(index, item); + emit itemsInserted(index, 1); +} + +void QScatterDataProxy::insertItems(int index, const QScatterDataArray &items) +{ + dptr()->insertItems(index, items); + emit itemsInserted(index, items.size()); +} + +void QScatterDataProxy::removeItems(int index, int removeCount) +{ + dptr()->removeItems(index, removeCount); + emit itemsRemoved(index, removeCount); +} + +int QScatterDataProxy::itemCount() const +{ + return dptrc()->m_dataArray->size(); +} + +const QScatterDataArray *QScatterDataProxy::array() const +{ + return dptrc()->m_dataArray; +} + +const QScatterDataItem *QScatterDataProxy::itemAt(int index) const +{ + return &dptrc()->m_dataArray->at(index); +} + +QScatterDataProxyPrivate *QScatterDataProxy::dptr() +{ + return static_cast<QScatterDataProxyPrivate *>(d_ptr.data()); +} + +const QScatterDataProxyPrivate *QScatterDataProxy::dptrc() const +{ + return static_cast<const QScatterDataProxyPrivate *>(d_ptr.data()); +} + +// QScatterDataProxyPrivate + +QScatterDataProxyPrivate::QScatterDataProxyPrivate(QScatterDataProxy *q) + : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeScatter), + m_dataArray(new QScatterDataArray) +{ +} + +QScatterDataProxyPrivate::~QScatterDataProxyPrivate() +{ + m_dataArray->clear(); + delete m_dataArray; +} + +bool QScatterDataProxyPrivate::resetArray(QScatterDataArray *newArray) +{ + if (!m_dataArray->size() && (!newArray || !newArray->size())) + return false; + + m_dataArray->clear(); + delete m_dataArray; + + if (newArray) + m_dataArray = newArray; + else + m_dataArray = new QScatterDataArray; + + return true; +} + +void QScatterDataProxyPrivate::setItem(int index, const QScatterDataItem &item) +{ + Q_ASSERT(index >= 0 && index < m_dataArray->size()); + (*m_dataArray)[index] = item; +} + +void QScatterDataProxyPrivate::setItems(int index, const QScatterDataArray &items) +{ + Q_ASSERT(index >= 0 && (index + items.size()) <= m_dataArray->size()); + for (int i = 0; i < items.size(); i++) + (*m_dataArray)[index++] = items[i]; +} + +int QScatterDataProxyPrivate::addItem(const QScatterDataItem &item) +{ + int currentSize = m_dataArray->size(); + m_dataArray->append(item); + return currentSize; +} + +int QScatterDataProxyPrivate::addItems(const QScatterDataArray &items) +{ + int currentSize = m_dataArray->size(); + (*m_dataArray) += items; + return currentSize; +} + +void QScatterDataProxyPrivate::insertItem(int index, const QScatterDataItem &item) +{ + Q_ASSERT(index >= 0 && index <= m_dataArray->size()); + m_dataArray->insert(index, item); +} + +void QScatterDataProxyPrivate::insertItems(int index, const QScatterDataArray &items) +{ + Q_ASSERT(index >= 0 && index <= m_dataArray->size()); + for (int i = 0; i < items.size(); i++) + m_dataArray->insert(index++, items.at(i)); +} + +void QScatterDataProxyPrivate::removeItems(int index, int removeCount) +{ + Q_ASSERT(index >= 0); + int maxRemoveCount = m_dataArray->size() - index; + removeCount = qMin(removeCount, maxRemoveCount); + m_dataArray->remove(index, removeCount); +} + +QVector3D QScatterDataProxyPrivate::limitValues() +{ + QVector3D limits; + for (int i = 0; i < m_dataArray->size(); i++) { + const QScatterDataItem &item = m_dataArray->at(i); + float xValue = qAbs(item.position().x()); + if (limits.x() < xValue) + limits.setX(xValue); + float yValue = qAbs(item.position().y()); + if (limits.y() < yValue) + limits.setY(yValue); + float zValue = qAbs(item.position().z()); + if (limits.z() < zValue) + limits.setZ(zValue); + } + //qDebug() << __FUNCTION__ << limits << m_dataArray.size(); + return limits; +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qscatterdataproxy.h b/src/datavis3d/data/qscatterdataproxy.h new file mode 100644 index 00000000..9e139c00 --- /dev/null +++ b/src/datavis3d/data/qscatterdataproxy.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QSCATTERDATAPROXY_H +#define QSCATTERDATAPROXY_H + +#include <QtDataVis3D/qabstractdataproxy.h> +#include <QtDataVis3D/qscatterdataitem.h> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +typedef QVector<QScatterDataItem> QScatterDataArray; + +class QScatterDataProxyPrivate; + +class QT_DATAVIS3D_EXPORT QScatterDataProxy : public QAbstractDataProxy +{ + Q_OBJECT + +public: + explicit QScatterDataProxy(); + explicit QScatterDataProxy(QScatterDataProxyPrivate *d); + virtual ~QScatterDataProxy(); + + // QScatterDataProxy is optimized to use cases where the only defining characteristics of an + // individual scatter item are it's position and size. Modifying other data that might be + // added in the future such as color requires allocating additional data object for the bar. + + // Item pointers are guaranteed to be valid only until next call that modifies data. + // Array pointer is guaranteed to be valid for lifetime of proxy. + int itemCount() const; + const QScatterDataArray *array() const; + const QScatterDataItem *itemAt(int index) const; + + // Clears the existing array and takes ownership of the new array. + // Passing null array clears all data. + void resetArray(QScatterDataArray *newArray); + + // Change existing items + void setItem(int index, const QScatterDataItem &item); + void setItems(int index, const QScatterDataArray &items); + + int addItem(const QScatterDataItem &item); // returns the index of added item + int addItems(const QScatterDataArray &items); // returns the index of first added item + + // If index is equal to data array size, item(s) are added to the array. + void insertItem(int index, const QScatterDataItem &item); + void insertItems(int index, const QScatterDataArray &items); + + // Attempting to remove items past the end of the array does nothing. + void removeItems(int index, int removeCount); + +signals: + void arrayReset(); + void itemsAdded(int startIndex, int count); + void itemsChanged(int startIndex, int count); + void itemsRemoved(int startIndex, int count); // Index may be over current array size if removed from end + void itemsInserted(int startIndex, int count); + +protected: + QScatterDataProxyPrivate *dptr(); + const QScatterDataProxyPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QScatterDataProxy) + + friend class Scatter3DController; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/data/qscatterdataproxy_p.h b/src/datavis3d/data/qscatterdataproxy_p.h new file mode 100644 index 00000000..526845fd --- /dev/null +++ b/src/datavis3d/data/qscatterdataproxy_p.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 QSCATTERDATAPROXY_P_H +#define QSCATTERDATAPROXY_P_H + +#include "qscatterdataproxy.h" +#include "qabstractdataproxy_p.h" +#include "qscatterdataitem.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QScatterDataProxyPrivate : public QAbstractDataProxyPrivate +{ + Q_OBJECT +public: + QScatterDataProxyPrivate(QScatterDataProxy *q); + virtual ~QScatterDataProxyPrivate(); + + bool resetArray(QScatterDataArray *newArray); + void setItem(int index, const QScatterDataItem &item); + void setItems(int index, const QScatterDataArray &items); + int addItem(const QScatterDataItem &item); + int addItems(const QScatterDataArray &items); + void insertItem(int index, const QScatterDataItem &item); + void insertItems(int index, const QScatterDataArray &items); + void removeItems(int index, int removeCount); + + QVector3D limitValues(); + +private: + QScatterDataArray *m_dataArray; + QString m_itemLabelFormat; + + friend class QScatterDataProxy; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // QBARDATAPROXY_P_H diff --git a/src/datavis3d/data/scatterrenderitem.cpp b/src/datavis3d/data/scatterrenderitem.cpp new file mode 100644 index 00000000..15281c0a --- /dev/null +++ b/src/datavis3d/data/scatterrenderitem.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "scatterrenderitem_p.h" +#include "scatter3drenderer_p.h" +#include "qscatterdataproxy.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +ScatterRenderItem::ScatterRenderItem() + : BarRenderItem() +{ +} + +ScatterRenderItem::~ScatterRenderItem() +{ +} + +void ScatterRenderItem::formatLabel() +{ + // TODO The label format specified in proxy should probably have additional custom formatting + // TODO specifiers in addition to standard printf specifiers for placement of item labels + // TODO and selection data (like row/column in bar selection) + + // Format the string on first access + QString numStr; + numStr.setNum(m_value); + // TODO actually format instead of just prepending the value + m_label.clear(); // Just in case + //m_label.append(m_itemLabel); + //m_label.append(QStringLiteral(" ")); + m_label.append(numStr); + m_label.append(m_renderer->itemLabelFormat()); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/scatterrenderitem_p.h b/src/datavis3d/data/scatterrenderitem_p.h new file mode 100644 index 00000000..47cfeed2 --- /dev/null +++ b/src/datavis3d/data/scatterrenderitem_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 SCATTERRENDERITEM_P_H +#define SCATTERRENDERITEM_P_H + +#include "barrenderitem_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class Scatter3DRenderer; + +class ScatterRenderItem : public BarRenderItem +{ +public: + ScatterRenderItem(); + virtual ~ScatterRenderItem(); + + inline const QVector3D &position() const { return m_position; } + inline void setPosition(const QVector3D &pos) { m_position = pos; } + + //inline void setSize(qreal size); + //inline qreal size() const { return m_size; } + + // TODO should be in abstract, but currently there is no abstract renderer + // TODO change when maps refactored + inline void setRenderer(Scatter3DRenderer *renderer) { m_renderer = renderer; } + +protected: + virtual void formatLabel(); + + Scatter3DRenderer *m_renderer; + QVector3D m_position; + //qreal m_size; // TODO in case we need a fourth variable that adjusts scatter item size + + friend class QScatterDataItem; +}; + +typedef QVector<ScatterRenderItem> ScatterRenderItemArray; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/datavis3d.pro b/src/datavis3d/datavis3d.pro index 63091c55..fa548c22 100644 --- a/src/datavis3d/datavis3d.pro +++ b/src/datavis3d/datavis3d.pro @@ -1,7 +1,7 @@ TARGET = QtDataVis3D QT = core gui opengl #qml -DEFINES += QTENTERPRISE_DATAVIS3D_LIBRARY +DEFINES += QT_DATAVIS3D_LIBRARY QMAKE_DOCS = $$PWD/doc/qtdatavis3d.qdocconf @@ -11,6 +11,8 @@ include($$PWD/common.pri) include($$PWD/engine/engine.pri) include($$PWD/global/global.pri) include($$PWD/utils/utils.pri) +include($$PWD/axis/axis.pri) +include($$PWD/data/data.pri) wince* { # The Microsoft MIPS compiler crashes if /Og is specified. diff --git a/src/datavis3d/doc/qtdatavis3d.qdocconf b/src/datavis3d/doc/qtdatavis3d.qdocconf index c3fd9826..0e9f6d5b 100644 --- a/src/datavis3d/doc/qtdatavis3d.qdocconf +++ b/src/datavis3d/doc/qtdatavis3d.qdocconf @@ -15,7 +15,7 @@ sourcedirs += .. depends += qtcore \ qtgui -qhp.projects = QtDataVis3D +qhp.projects = qtdatavis3d qhp.qtdatavis3d.file = qtdatavis3d.qhp qhp.qtdatavis3d.namespace = org.qt-project.qtdatavis3d.1.0.0 diff --git a/src/datavis3d/doc/snippets/doc_src_q3dbars_construction.cpp b/src/datavis3d/doc/snippets/doc_src_q3dbars_construction.cpp index 0d94e0eb..09979d8c 100644 --- a/src/datavis3d/doc/snippets/doc_src_q3dbars_construction.cpp +++ b/src/datavis3d/doc/snippets/doc_src_q3dbars_construction.cpp @@ -1,40 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of the QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.cpp b/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.cpp index ac2f7f40..a3b3e8e8 100644 --- a/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.cpp +++ b/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.cpp @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.pro b/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.pro index 4b670157..ba0f320b 100644 --- a/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.pro +++ b/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.pro @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/src/datavis3d/doc/src/qtdatavis3d-index.qdoc b/src/datavis3d/doc/src/qtdatavis3d-index.qdoc index 0c9cf8cc..dae2a14d 100644 --- a/src/datavis3d/doc/src/qtdatavis3d-index.qdoc +++ b/src/datavis3d/doc/src/qtdatavis3d-index.qdoc @@ -1,27 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of the QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -61,7 +52,10 @@ \li \l{Barchart Example} \li \l{Mapdata Example} \li \l{Qt Quick 2 Barchart Example} + \li \l{Qt Quick 2 Maps Example} + \li \l{Qt Quick 2 Scatter Example} \li \l{Rainfall Example} + \li \l{Scatter Chart Example} \li \l{Spectrum Example} \li \l{Widget Example} \endlist diff --git a/src/datavis3d/doc/src/qtdatavis3d.qdoc b/src/datavis3d/doc/src/qtdatavis3d.qdoc index 37e53161..c27fe0a3 100644 --- a/src/datavis3d/doc/src/qtdatavis3d.qdoc +++ b/src/datavis3d/doc/src/qtdatavis3d.qdoc @@ -1,27 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of the QtDataVis3D module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/src/datavis3d/doc/src/qtdatavis3dlicense.qdoc b/src/datavis3d/doc/src/qtdatavis3dlicense.qdoc index 9821b26f..610fb9b7 100644 --- a/src/datavis3d/doc/src/qtdatavis3dlicense.qdoc +++ b/src/datavis3d/doc/src/qtdatavis3dlicense.qdoc @@ -1,27 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the documentation of the Qt SVG module. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/src/datavis3d/documentationGroups.dox b/src/datavis3d/documentationGroups.dox deleted file mode 100644 index ed9c3f1c..00000000 --- a/src/datavis3d/documentationGroups.dox +++ /dev/null @@ -1,150 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtXmlPatterns module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt 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. - -/** - * @file - * @short Contains Doxygen documentation for groups. - */ - -namespace QPatternist -{ - /** - * @short The abstract syntax tree nodes that implements the builtin - * functions, such as @c fn:concat(). - * - * @defgroup Patternist_functions Function Implementations - * @author Frans Englich <frans.englich@nokia.com> - */ - - /** - * @short The abstract syntax tree nodes that is generated for XPath, - * XQuery, and XSL-T code. - * - * XPath's approach of compilation is traditional. An Abstract Syntax - * Tree(AST) is built, where the Expression class is the abstract base - * class for all kinds of implementations of expressions. - * - * What perhaps can be said to be characteristic for Patternist is that the - * base class, Expression, performs a lot of work, and that sub-classes - * declares what specific behaviors they need, which the Expression's - * functions then bring into action. - * - * XPath expressions often have different amount of operands. For example, - * the 'and' expression takes two, the context item(".") none, and the - * if-expression three. To help expression implementations with that, there - * exist the abstract EmptyContainer, SingleContainer, PairContainer, - * TripleContainer, and UnlimitedContainer classes for avoiding duplicating - * code. - * - * @defgroup Patternist_expressions Expressions - * @author Frans Englich <frans.englich@nokia.com> - */ - - /** - * @short Various classes that contains small utility functions. - * - * @defgroup Patternist Utility Classes - * @author Frans Englich <frans.englich@nokia.com> - */ - - /** - * @short Classes for the type system in the XQuery & XSL-T language. - * - * @defgroup Patternist_types Type system - * @author Frans Englich <frans.englich@nokia.com> - */ - - /** - * @defgroup Patternist_xdm XQuery/XPath Data Model - * @author Frans Englich <frans.englich@nokia.com> - */ - - /** - * @short Patternist's family of iterators in one of the most central parts - * of Patternist's API, and are responsible for carrying, and typically - * also creating, data. - * - * An iterator, which always is an Iterator sub-class, is similar to a - * Java-style iterator. What signifies Patternist's iterators is that they - * almost always contains business logic(which is the cause to their - * efficiency). - * - * An example which illustrates this principle is the RangeIterator. When - * the RangeExpression is told to create a sequence of integers between 1 - * and 1000, it doesn't enter a loop that allocates 1000 Integer instances, - * but instead return an RangeIterator that incrementally creates the - * numbers when asked to do so via its RangeIterator::next() function. If - * it turns out that the expression that has the range expression as - * operand only needs three items from it, that is what gets created, not - * 1000. - * - * All iterators operates by that principle, perhaps suitably labeled as - * "pull-based", "lazy loaded" or "serialized". Central for the XPath - * language is that it filters and selects data, and the iterators supports - * this well by letting the demand of the filter expressions(the callees) - * decide how "much" source that gets computed. In this way the evaluation - * of an expression tree can lead to a chain of pipelined iterators, where - * the first asks the second for data and then performs its specific - * operations, the second subsequently asks the third, and so forth. - * - * However, the iterators are not limited to be used for representing - * sequences of items in the XPath Data Model. The Iterator is - * parameterized on one argument, meaning any type of "units" can be - * iterated, be it Item or any other. One use of this is in the - * ExpressionSequence(which implements the comma operator) where it creates - * Iterator instances over Expression instances -- its operands. The - * parameterization is often used in combination with the MappingIterator - * and the MappingCallback. - * - * @defgroup Patternist_iterators Iterators - * @author Frans Englich <frans.englich@nokia.com> - */ -} diff --git a/src/datavis3d/engine/abstract3dcontroller.cpp b/src/datavis3d/engine/abstract3dcontroller.cpp new file mode 100644 index 00000000..12f76fd1 --- /dev/null +++ b/src/datavis3d/engine/abstract3dcontroller.cpp @@ -0,0 +1,698 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "abstract3dcontroller_p.h" +#include "camerahelper_p.h" +#include "qabstractaxis_p.h" +#include "qvalueaxis.h" +#include "abstract3drenderer_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) : + QObject(parent), + m_boundingRect(boundRect.x(), boundRect.y(), boundRect.width(), boundRect.height()), + m_horizontalRotation(-45.0f), + m_verticalRotation(15.0f), + m_theme(), + m_font(QFont(QStringLiteral("Arial"))), + m_selectionMode(QDataVis::ModeItem), + m_shadowQuality(QDataVis::ShadowLow), + m_labelTransparency(QDataVis::TransparencyFromTheme), + m_isBackgroundEnabled(true), + m_isGridEnabled(true), + m_cameraHelper(new CameraHelper()), + m_zoomLevel(100), + m_axisX(0), + m_axisY(0), + m_axisZ(0), + m_renderer(0), + m_isDataDirty(false) +{ + m_theme.useColorTheme(QDataVis::ThemeSystem); +} + +Abstract3DController::~Abstract3DController() +{ + delete m_cameraHelper; + delete m_axisX; + delete m_axisY; + delete m_axisZ; +} + +void Abstract3DController::setRenderer(Abstract3DRenderer *renderer) +{ + m_renderer = renderer; +} + +void Abstract3DController::synchDataToRenderer() +{ + // If we don't have a renderer, don't do anything + if (!m_renderer) + return; + + if (m_changeTracker.positionChanged) { + m_renderer->updatePosition(m_boundingRect); + m_changeTracker.positionChanged = false; + } + + if (m_changeTracker.zoomLevelChanged) { + m_renderer->updateZoomLevel(m_zoomLevel); + m_changeTracker.zoomLevelChanged = false; + } + + if (m_changeTracker.themeChanged) { + m_renderer->updateTheme(m_theme); + m_changeTracker.themeChanged = false; + } + + if (m_changeTracker.fontChanged) { + m_renderer->updateFont(m_font); + m_changeTracker.fontChanged = false; + } + + if (m_changeTracker.labelTransparencyChanged) { + m_renderer->updateLabelTransparency(m_labelTransparency); + m_changeTracker.labelTransparencyChanged = false; + } + + if (m_changeTracker.boundingRectChanged || m_changeTracker.sizeChanged) { + m_renderer->updateBoundingRect(m_boundingRect); + m_changeTracker.boundingRectChanged = false; + m_changeTracker.sizeChanged = false; + } + + if (m_changeTracker.shadowQualityChanged) { + m_renderer->updateShadowQuality(m_shadowQuality); + m_changeTracker.shadowQualityChanged = false; + } + + if (m_changeTracker.selectionModeChanged) { + m_renderer->updateSelectionMode(m_selectionMode); + m_changeTracker.selectionModeChanged = false; + } + + if (m_changeTracker.objFileChanged) { + m_renderer->updateMeshFileName(m_objFile); + m_changeTracker.objFileChanged = false; + } + + if (m_changeTracker.gridEnabledChanged) { + m_renderer->updateGridEnabled(m_isGridEnabled); + m_changeTracker.gridEnabledChanged = false; + } + + if (m_changeTracker.backgroundEnabledChanged) { + m_renderer->updateBackgroundEnabled(m_isBackgroundEnabled); + m_changeTracker.backgroundEnabledChanged = false; + } + + if (m_changeTracker.axisXTypeChanged) { + m_renderer->updateAxisType(QAbstractAxis::AxisOrientationX, m_axisX->type()); + m_changeTracker.axisXTypeChanged = false; + } + + if (m_changeTracker.axisYTypeChanged) { + m_renderer->updateAxisType(QAbstractAxis::AxisOrientationY, m_axisY->type()); + m_changeTracker.axisYTypeChanged = false; + } + + if (m_changeTracker.axisZTypeChanged) { + m_renderer->updateAxisType(QAbstractAxis::AxisOrientationZ, m_axisZ->type()); + m_changeTracker.axisZTypeChanged = false; + } + + if (m_changeTracker.axisXTitleChanged) { + m_renderer->updateAxisTitle(QAbstractAxis::AxisOrientationX, m_axisX->title()); + m_changeTracker.axisXTitleChanged = false; + } + + if (m_changeTracker.axisYTitleChanged) { + m_renderer->updateAxisTitle(QAbstractAxis::AxisOrientationY, m_axisY->title()); + m_changeTracker.axisYTitleChanged = false; + } + + if (m_changeTracker.axisZTitleChanged) { + m_renderer->updateAxisTitle(QAbstractAxis::AxisOrientationZ, m_axisZ->title()); + m_changeTracker.axisZTitleChanged = false; + } + + if (m_changeTracker.axisXLabelsChanged) { + m_renderer->updateAxisLabels(QAbstractAxis::AxisOrientationX, m_axisX->labels()); + m_changeTracker.axisXLabelsChanged = false; + } + + if (m_changeTracker.axisYLabelsChanged) { + m_renderer->updateAxisLabels(QAbstractAxis::AxisOrientationY, m_axisY->labels()); + m_changeTracker.axisYLabelsChanged = false; + } + if (m_changeTracker.axisZLabelsChanged) { + m_renderer->updateAxisLabels(QAbstractAxis::AxisOrientationZ, m_axisZ->labels()); + m_changeTracker.axisZLabelsChanged = false; + } + + if (m_changeTracker.axisXRangeChanged) { + m_changeTracker.axisXRangeChanged = false; + if (m_axisX->type() & QAbstractAxis::AxisTypeValue) { + QValueAxis *valueAxisX = static_cast<QValueAxis *>(m_axisX); + m_renderer->updateAxisRange(QAbstractAxis::AxisOrientationX, + valueAxisX->min(), valueAxisX->max()); + } + } + + if (m_changeTracker.axisYRangeChanged) { + m_changeTracker.axisYRangeChanged = false; + if (m_axisY->type() & QAbstractAxis::AxisTypeValue) { + QValueAxis *valueAxisY = static_cast<QValueAxis *>(m_axisY); + m_renderer->updateAxisRange(QAbstractAxis::AxisOrientationY, + valueAxisY->min(), valueAxisY->max()); + } + } + + if (m_changeTracker.axisZRangeChanged) { + m_changeTracker.axisZRangeChanged = false; + if (m_axisZ->type() & QAbstractAxis::AxisTypeValue) { + QValueAxis *valueAxisZ = static_cast<QValueAxis *>(m_axisZ); + m_renderer->updateAxisRange(QAbstractAxis::AxisOrientationZ, + valueAxisZ->min(), valueAxisZ->max()); + } + } + + if (m_changeTracker.axisXSegmentCountChanged) { + m_changeTracker.axisXSegmentCountChanged = false; + if (m_axisX->type() & QAbstractAxis::AxisTypeValue) { + QValueAxis *valueAxisX = static_cast<QValueAxis *>(m_axisX); + m_renderer->updateAxisSegmentCount(QAbstractAxis::AxisOrientationX, + valueAxisX->segmentCount()); + } + } + + if (m_changeTracker.axisYSegmentCountChanged) { + m_changeTracker.axisYSegmentCountChanged = false; + if (m_axisY->type() & QAbstractAxis::AxisTypeValue) { + QValueAxis *valueAxisY = static_cast<QValueAxis *>(m_axisY); + m_renderer->updateAxisSegmentCount(QAbstractAxis::AxisOrientationY, + valueAxisY->segmentCount()); + } + } + + if (m_changeTracker.axisZSegmentCountChanged) { + m_changeTracker.axisZSegmentCountChanged = false; + if (m_axisZ->type() & QAbstractAxis::AxisTypeValue) { + QValueAxis *valueAxisZ = static_cast<QValueAxis *>(m_axisZ); + m_renderer->updateAxisSegmentCount(QAbstractAxis::AxisOrientationZ, + valueAxisZ->segmentCount()); + } + } + + if (m_changeTracker.axisXSubSegmentCountChanged) { + m_changeTracker.axisXSubSegmentCountChanged = false; + if (m_axisX->type() & QAbstractAxis::AxisTypeValue) { + QValueAxis *valueAxisX = static_cast<QValueAxis *>(m_axisX); + m_renderer->updateAxisSubSegmentCount(QAbstractAxis::AxisOrientationX, + valueAxisX->subSegmentCount()); + } + } + + if (m_changeTracker.axisYSubSegmentCountChanged) { + m_changeTracker.axisYSubSegmentCountChanged = false; + if (m_axisY->type() & QAbstractAxis::AxisTypeValue) { + QValueAxis *valueAxisY = static_cast<QValueAxis *>(m_axisY); + m_renderer->updateAxisSubSegmentCount(QAbstractAxis::AxisOrientationY, + valueAxisY->subSegmentCount()); + } + } + + if (m_changeTracker.axisZSubSegmentCountChanged) { + m_changeTracker.axisZSubSegmentCountChanged = false; + if (m_axisZ->type() & QAbstractAxis::AxisTypeValue) { + QValueAxis *valueAxisZ = static_cast<QValueAxis *>(m_axisZ); + m_renderer->updateAxisSubSegmentCount(QAbstractAxis::AxisOrientationZ, + valueAxisZ->subSegmentCount()); + } + } +} + +void Abstract3DController::render(const GLuint defaultFboHandle) +{ + // If not initialized, do nothing. + if (!m_renderer) + return; + + m_renderer->render(m_cameraHelper, defaultFboHandle); +} + +void Abstract3DController::setSize(const int width, const int height) +{ + m_boundingRect.setWidth(width); + m_boundingRect.setHeight(height); + + m_changeTracker.boundingRectChanged = true; + emit boundingRectChanged(m_boundingRect); +} + +const QSize Abstract3DController::size() +{ + return m_boundingRect.size(); +} + +const QRect Abstract3DController::boundingRect() +{ + return m_boundingRect; +} + +void Abstract3DController::setBoundingRect(const QRect boundingRect) +{ + m_boundingRect = boundingRect; + + m_changeTracker.boundingRectChanged = true; + emit boundingRectChanged(m_boundingRect); +} + +void Abstract3DController::setWidth(const int width) +{ + m_boundingRect.setWidth(width); + + m_changeTracker.sizeChanged = true; + emit sizeChanged(m_boundingRect); +} + +int Abstract3DController::width() +{ + return m_boundingRect.width(); +} + +void Abstract3DController::setHeight(const int height) +{ + m_boundingRect.setHeight(height); + + m_changeTracker.sizeChanged = true; + emit sizeChanged(m_boundingRect); +} + +int Abstract3DController::height() +{ + return m_boundingRect.height(); +} + +void Abstract3DController::setX(const int x) +{ + m_boundingRect.setX(x); + + m_changeTracker.positionChanged = true; + emit positionChanged(m_boundingRect); +} + +int Abstract3DController::x() +{ + return m_boundingRect.x(); +} + +void Abstract3DController::setY(const int y) +{ + m_boundingRect.setY(y); + + m_changeTracker.positionChanged = true; + emit positionChanged(m_boundingRect); +} + +int Abstract3DController::y() +{ + return m_boundingRect.y(); +} + +void Abstract3DController::setAxisX(QAbstractAxis *axis) +{ + setAxisHelper(QAbstractAxis::AxisOrientationX, axis, &m_axisX); +} + +QAbstractAxis *Abstract3DController::axisX() +{ + return m_axisX; +} + +void Abstract3DController::setAxisY(QAbstractAxis *axis) +{ + setAxisHelper(QAbstractAxis::AxisOrientationY, axis, &m_axisY); +} + +QAbstractAxis *Abstract3DController::axisY() +{ + return m_axisY; +} + +void Abstract3DController::setAxisZ(QAbstractAxis *axis) +{ + setAxisHelper(QAbstractAxis::AxisOrientationZ, axis, &m_axisZ); +} + +QAbstractAxis *Abstract3DController::axisZ() +{ + return m_axisZ; +} + +int Abstract3DController::zoomLevel() +{ + return m_zoomLevel; +} + +void Abstract3DController::setZoomLevel(int zoomLevel) +{ + m_zoomLevel = zoomLevel; + + m_changeTracker.zoomLevelChanged = true; + emit zoomLevelChanged(zoomLevel); +} + +void Abstract3DController::setCameraPreset(QDataVis::CameraPreset preset) +{ + m_cameraHelper->setCameraPreset(preset); +} + +void Abstract3DController::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) +{ + m_horizontalRotation = qBound(-180.0f, horizontal, 180.0f); + m_verticalRotation = qBound(0.0f, vertical, 90.0f); + m_zoomLevel = qBound(10, distance, 500); + m_cameraHelper->setCameraRotation(QPointF(m_horizontalRotation, + m_verticalRotation)); + //qDebug() << "camera rotation set to" << m_horizontalRotation << m_verticalRotation; +} + +void Abstract3DController::setObjectColor(QColor baseColor, QColor heightColor, QColor depthColor, + bool uniform) +{ + m_theme.m_baseColor = baseColor; + m_theme.m_heightColor = heightColor; + m_theme.m_depthColor = depthColor; + m_theme.m_uniformColor = uniform; + + m_changeTracker.themeChanged = true; + emit themeChanged(m_theme); +} + +void Abstract3DController::setColorTheme(QDataVis::ColorTheme colorTheme) +{ + m_theme.useColorTheme(colorTheme); + + m_changeTracker.themeChanged = true; + emit themeChanged(m_theme); +} + +Theme Abstract3DController::theme() +{ + return m_theme; +} + +void Abstract3DController::setFontSize(float fontsize) +{ + m_font.setPointSizeF(fontsize); + + m_changeTracker.fontChanged = true; + emit fontChanged(m_font); +} + +float Abstract3DController::fontSize() +{ + return m_font.pointSizeF(); +} + +void Abstract3DController::setFont(const QFont &font) +{ + m_font = font; + + m_changeTracker.fontChanged = true; + emit fontChanged(m_font); +} + +QFont Abstract3DController::font() +{ + return m_font; +} + +void Abstract3DController::setSelectionMode(QDataVis::SelectionMode mode) +{ + m_selectionMode = mode; + m_changeTracker.selectionModeChanged = true; + emit selectionModeChanged(m_selectionMode); +} + +QDataVis::SelectionMode Abstract3DController::selectionMode() +{ + return m_selectionMode; +} + +void Abstract3DController::setShadowQuality(QDataVis::ShadowQuality quality) +{ + m_shadowQuality = quality; + + m_changeTracker.shadowQualityChanged = true; + emit shadowQualityChanged(m_shadowQuality); +} + +QDataVis::ShadowQuality Abstract3DController::shadowQuality() +{ + return m_shadowQuality; +} + +void Abstract3DController::setLabelTransparency(QDataVis::LabelTransparency transparency) +{ + m_labelTransparency = transparency; + + m_changeTracker.labelTransparencyChanged = true; + emit labelTransparencyChanged(m_labelTransparency); +} + +QDataVis::LabelTransparency Abstract3DController::labelTransparency() +{ + return m_labelTransparency; +} + +void Abstract3DController::setBackgroundEnabled(bool enable) +{ + m_isBackgroundEnabled = enable; + m_changeTracker.backgroundEnabledChanged = true; + emit backgroundEnabledChanged(m_isBackgroundEnabled); +} + +bool Abstract3DController::backgroundEnabled() +{ + return m_isBackgroundEnabled; +} + +void Abstract3DController::setGridEnabled(bool enable) +{ + m_isGridEnabled = enable; + m_changeTracker.gridEnabledChanged = true; + emit gridEnabledChanged(m_isGridEnabled); +} + +bool Abstract3DController::gridEnabled() +{ + return m_isGridEnabled; +} + +void Abstract3DController::setMeshFileName(const QString &fileName) +{ + m_objFile = fileName; + m_changeTracker.objFileChanged = true; + emit meshFileNameChanged(m_objFile); +} + +QString Abstract3DController::meshFileName() +{ + return m_objFile; +} + +void Abstract3DController::handleAxisTitleChanged(const QString &title) +{ + handleAxisTitleChangedBySender(sender(), title); +} + +void Abstract3DController::handleAxisTitleChangedBySender(QObject *sender, const QString &title) +{ + if (sender == m_axisX) { + m_changeTracker.axisXTitleChanged = true; + emit axisTitleChanged(QAbstractAxis::AxisOrientationX, title); + } else if (sender == m_axisY) { + m_changeTracker.axisYTitleChanged = true; + emit axisTitleChanged(QAbstractAxis::AxisOrientationY, title); + } else if (sender == m_axisZ) { + m_changeTracker.axisZTitleChanged = true; + emit axisTitleChanged(QAbstractAxis::AxisOrientationZ, title); + } else { + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + } +} + +void Abstract3DController::handleAxisLabelsChanged() +{ + handleAxisLabelsChangedBySender(sender()); +} + +void Abstract3DController::handleAxisLabelsChangedBySender(QObject *sender) +{ + if (sender == m_axisX) { + m_changeTracker.axisXLabelsChanged = true; + emit axisLabelsChanged(QAbstractAxis::AxisOrientationX, m_axisX->labels()); + } else if (sender == m_axisY) { + m_changeTracker.axisYLabelsChanged = true; + emit axisLabelsChanged(QAbstractAxis::AxisOrientationY, m_axisY->labels()); + } else if (sender == m_axisZ) { + m_changeTracker.axisZLabelsChanged = true; + emit axisLabelsChanged(QAbstractAxis::AxisOrientationZ, m_axisZ->labels()); + } else { + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + } +} + +void Abstract3DController::handleAxisRangeChanged(qreal min, qreal max) +{ + handleAxisRangeChangedBySender(sender(), min, max); +} + +void Abstract3DController::handleAxisRangeChangedBySender(QObject *sender, qreal min, qreal max) +{ + if (sender == m_axisX) { + m_isDataDirty = true; + m_changeTracker.axisXRangeChanged = true; + emit axisRangeChanged(QAbstractAxis::AxisOrientationX, min, max); + } else if (sender == m_axisY) { + m_isDataDirty = true; + m_changeTracker.axisYRangeChanged = true; + emit axisRangeChanged(QAbstractAxis::AxisOrientationY, min, max); + } else if (sender == m_axisZ) { + m_isDataDirty = true; + + m_changeTracker.axisZRangeChanged = true; + emit axisRangeChanged(QAbstractAxis::AxisOrientationZ, min, max); + } else { + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + } +} + +void Abstract3DController::handleAxisSegmentCountChanged(int count) +{ + handleAxisSegmentCountChangedBySender(sender(), count); +} + +void Abstract3DController::handleAxisSegmentCountChangedBySender(QObject *sender, int count) +{ + if (sender == m_axisX) { + m_changeTracker.axisXSegmentCountChanged = true; + emit axisSegmentCountChanged(QAbstractAxis::AxisOrientationX, count); + } else if (sender == m_axisY) { + m_changeTracker.axisYSegmentCountChanged = true; + emit axisSegmentCountChanged(QAbstractAxis::AxisOrientationY, count); + } else if (sender == m_axisZ) { + m_changeTracker.axisZSegmentCountChanged = true; + emit axisSegmentCountChanged(QAbstractAxis::AxisOrientationZ, count); + } else { + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + } +} + +void Abstract3DController::handleAxisSubSegmentCountChanged(int count) +{ + handleAxisSubSegmentCountChangedBySender(sender(), count); +} + +void Abstract3DController::handleAxisSubSegmentCountChangedBySender(QObject *sender, int count) +{ + if (sender == m_axisX) { + m_changeTracker.axisXSubSegmentCountChanged = true; + emit axisSubSegmentCountChanged(QAbstractAxis::AxisOrientationX, count); + } else if (sender == m_axisY) { + m_changeTracker.axisYSubSegmentCountChanged = true; + emit axisSubSegmentCountChanged(QAbstractAxis::AxisOrientationY, count); + } else if (sender == m_axisZ) { + m_changeTracker.axisZSubSegmentCountChanged = true; + emit axisSubSegmentCountChanged(QAbstractAxis::AxisOrientationZ, count); + } else { + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + } +} + +void Abstract3DController::handleAxisAutoAdjustRangeChanged(bool autoAdjust) +{ + QObject *sender = QObject::sender(); + if (sender != m_axisX && sender != m_axisY && sender != m_axisZ) + return; + + QAbstractAxis *axis = static_cast<QAbstractAxis*>(sender); + handleAxisAutoAdjustRangeChangedInOrientation(axis->orientation(), autoAdjust); +} + +void Abstract3DController::setAxisHelper(QAbstractAxis::AxisOrientation orientation, + QAbstractAxis *axis, QAbstractAxis **axisPtr) +{ + Q_ASSERT(axis); + + delete *axisPtr; + *axisPtr = axis; + + axis->setParent(0); // Assume ownership + axis->d_ptr->setOrientation(orientation); + + + QObject::connect(axis, &QAbstractAxis::titleChanged, + this, &Abstract3DController::handleAxisTitleChanged); + QObject::connect(axis, &QAbstractAxis::labelsChanged, + this, &Abstract3DController::handleAxisLabelsChanged); + + + if (orientation == QAbstractAxis::AxisOrientationX) + m_changeTracker.axisXTypeChanged = true; + else if (orientation == QAbstractAxis::AxisOrientationY) + m_changeTracker.axisYTypeChanged = true; + else if (orientation == QAbstractAxis::AxisOrientationZ) + m_changeTracker.axisZTypeChanged = true; + emit axisTypeChanged(orientation, axis->type()); + + handleAxisTitleChangedBySender(axis, axis->title()); + emit axisTitleChanged(orientation, axis->title()); + + handleAxisLabelsChangedBySender(axis); + emit axisLabelsChanged(orientation, axis->labels()); + + if (axis->type() & QAbstractAxis::AxisTypeValue) { + QValueAxis *valueAxis = static_cast<QValueAxis *>(axis); + QObject::connect(valueAxis, &QValueAxis::rangeChanged, + this, &Abstract3DController::handleAxisRangeChanged); + QObject::connect(valueAxis, &QValueAxis::segmentCountChanged, + this, &Abstract3DController::handleAxisSegmentCountChanged); + QObject::connect(valueAxis, &QValueAxis::subSegmentCountChanged, + this, &Abstract3DController::handleAxisSubSegmentCountChanged); + QObject::connect(valueAxis, &QValueAxis::autoAdjustRangeChanged, + this, &Abstract3DController::handleAxisAutoAdjustRangeChanged); + + handleAxisRangeChangedBySender(valueAxis, valueAxis->min(), valueAxis->max()); + emit axisRangeChanged(orientation, valueAxis->min(), valueAxis->max()); + + handleAxisSegmentCountChangedBySender(valueAxis, valueAxis->segmentCount()); + emit axisSegmentCountChanged(orientation, valueAxis->segmentCount()); + + handleAxisSubSegmentCountChangedBySender(valueAxis, valueAxis->subSegmentCount()); + emit axisSubSegmentCountChanged(orientation, valueAxis->subSegmentCount()); + + handleAxisAutoAdjustRangeChangedInOrientation(valueAxis->orientation(), + valueAxis->isAutoAdjustRange()); + } +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/abstract3dcontroller_p.h b/src/datavis3d/engine/abstract3dcontroller_p.h new file mode 100644 index 00000000..8f21c97f --- /dev/null +++ b/src/datavis3d/engine/abstract3dcontroller_p.h @@ -0,0 +1,293 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 CONTROLLER3DBASE_H +#define CONTROLLER3DBASE_H + +#include <QObject> + +#include "datavis3dglobal_p.h" +#include "theme_p.h" +#include "qabstractaxis.h" +#include "drawer_p.h" + +class QFont; + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class CameraHelper; +class Abstract3DRenderer; + +struct Abstract3DChangeBitField { + bool positionChanged : 1; + bool zoomLevelChanged : 1; + bool themeChanged : 1; + bool fontChanged : 1; + bool labelTransparencyChanged : 1; + bool boundingRectChanged : 1; + bool sizeChanged : 1; + bool shadowQualityChanged : 1; + bool selectionModeChanged : 1; + bool objFileChanged : 1; + bool gridEnabledChanged : 1; + bool backgroundEnabledChanged : 1; + bool axisXTypeChanged : 1; + bool axisYTypeChanged : 1; + bool axisZTypeChanged : 1; + bool axisXTitleChanged : 1; + bool axisYTitleChanged : 1; + bool axisZTitleChanged : 1; + bool axisXLabelsChanged : 1; + bool axisYLabelsChanged : 1; + bool axisZLabelsChanged : 1; + bool axisXRangeChanged : 1; + bool axisYRangeChanged : 1; + bool axisZRangeChanged : 1; + bool axisXSegmentCountChanged : 1; + bool axisYSegmentCountChanged : 1; + bool axisZSegmentCountChanged : 1; + bool axisXSubSegmentCountChanged : 1; + bool axisYSubSegmentCountChanged : 1; + bool axisZSubSegmentCountChanged : 1; + + Abstract3DChangeBitField() : + positionChanged(true), + zoomLevelChanged(true), + themeChanged(true), + fontChanged(true), + labelTransparencyChanged(true), + boundingRectChanged(true), + sizeChanged(true), + shadowQualityChanged(true), + selectionModeChanged(true), + objFileChanged(true), + gridEnabledChanged(true), + backgroundEnabledChanged(true), + axisXTypeChanged(true), + axisYTypeChanged(true), + axisZTypeChanged(true), + axisXTitleChanged(true), + axisYTitleChanged(true), + axisZTitleChanged(true), + axisXLabelsChanged(true), + axisYLabelsChanged(true), + axisZLabelsChanged(true), + axisXRangeChanged(true), + axisYRangeChanged(true), + axisZRangeChanged(true), + axisXSegmentCountChanged(true), + axisYSegmentCountChanged(true), + axisZSegmentCountChanged(true), + axisXSubSegmentCountChanged(true), + axisYSubSegmentCountChanged(true), + axisZSubSegmentCountChanged(true) + { + } +}; + +class QT_DATAVIS3D_EXPORT Abstract3DController : public QObject +{ + Q_OBJECT + +public: + enum SelectionType { + SelectionNone = 0, + SelectionItem, + SelectionRow, + SelectionColumn + }; + + enum MouseState { + MouseNone = 0, + MouseOnScene, + MouseOnOverview, + MouseOnZoom, + MouseRotating, + MouseOnPinch + }; + +private: + Abstract3DChangeBitField m_changeTracker; + QRect m_boundingRect; + GLfloat m_horizontalRotation; + GLfloat m_verticalRotation; + Theme m_theme; + QFont m_font; + QDataVis::SelectionMode m_selectionMode; + QDataVis::ShadowQuality m_shadowQuality; + QDataVis::LabelTransparency m_labelTransparency; + bool m_isBackgroundEnabled; + bool m_isGridEnabled; + QString m_objFile; + +protected: + CameraHelper *m_cameraHelper; + int m_zoomLevel; + QAbstractAxis *m_axisX; + QAbstractAxis *m_axisY; + QAbstractAxis *m_axisZ; + Abstract3DRenderer *m_renderer; + bool m_isDataDirty; + + explicit Abstract3DController(QRect boundRect, QObject *parent = 0); + ~Abstract3DController(); + +public: + + inline bool isInitialized() { return (m_renderer != 0); } + + /** + * @brief synchDataToRenderer Called on the render thread while main GUI thread is blocked before rendering. + */ + virtual void synchDataToRenderer(); + + + virtual void render(const GLuint defaultFboHandle = 0); + + /** + * @brief setRenderer Sets the renderer to be used. isInitialized returns true from this point onwards. + * @param renderer Renderer to be used. + */ + void setRenderer(Abstract3DRenderer *renderer); + + // Size + virtual void setSize(const int width, const int height); + virtual const QSize size(); + virtual const QRect boundingRect(); + virtual void setBoundingRect(const QRect boundingRect); + virtual void setWidth(const int width); + virtual int width(); + virtual void setHeight(const int height); + virtual int height(); + virtual void setX(const int x); + virtual int x(); + virtual void setY(const int y); + virtual int y(); + virtual void setAxisX(QAbstractAxis *axis); + virtual QAbstractAxis *axisX(); + virtual void setAxisY(QAbstractAxis *axis); + virtual QAbstractAxis *axisY(); + virtual void setAxisZ(QAbstractAxis *axis); + virtual QAbstractAxis *axisZ(); + + virtual int zoomLevel(); + virtual void setZoomLevel(int zoomLevel); + + // Select preset camera placement + virtual void setCameraPreset(QDataVis::CameraPreset preset); + + // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and + // vertical (0...90) (or (-90...90) if there are negative values) angles and distance in + // percentage (10...500)) + virtual void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); + + // Set color if you don't want to use themes. Set uniform to false if you want the (height) + // color to change from bottom to top + virtual void setObjectColor(QColor baseColor, QColor heightColor, QColor depthColor, + bool uniform = true); + + // Set theme (bar colors, shaders, window color, background colors, light intensity and text + // colors are affected) + virtual void setColorTheme(QDataVis::ColorTheme colorTheme); + virtual Theme theme(); + + // Font size adjustment + virtual void setFontSize(float fontsize); + virtual float fontSize(); + + // Set font + virtual void setFont(const QFont &font); + virtual QFont font(); + + // Selection mode + virtual void setSelectionMode(QDataVis::SelectionMode mode); + virtual QDataVis::SelectionMode selectionMode(); + + // Adjust shadow quality + virtual void setShadowQuality(QDataVis::ShadowQuality quality); + virtual QDataVis::ShadowQuality shadowQuality(); + + // Label transparency adjustment + virtual void setLabelTransparency(QDataVis::LabelTransparency transparency); + virtual QDataVis::LabelTransparency labelTransparency(); + + // Enable or disable background mesh + virtual void setBackgroundEnabled(bool enable); + virtual bool backgroundEnabled(); + + // Enable or disable background grid + virtual void setGridEnabled(bool enable); + virtual bool gridEnabled(); + + // override bar type with own mesh + virtual void setMeshFileName(const QString &fileName); + virtual QString meshFileName(); + + virtual void handleAxisTitleChangedBySender(QObject *sender, const QString &title); + virtual void handleAxisLabelsChangedBySender(QObject *sender); + virtual void handleAxisRangeChangedBySender(QObject *sender, qreal min, qreal max); + virtual void handleAxisSegmentCountChangedBySender(QObject *sender, int count); + virtual void handleAxisSubSegmentCountChangedBySender(QObject *sender, int count); + virtual void handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust) = 0; + +public slots: + void handleAxisTitleChanged(const QString &title); + void handleAxisLabelsChanged(); + void handleAxisRangeChanged(qreal min, qreal max); + void handleAxisSegmentCountChanged(int count); + void handleAxisSubSegmentCountChanged(int count); + void handleAxisAutoAdjustRangeChanged(bool autoAdjust); + +signals: + void boundingRectChanged(QRect boundingRect); + void sizeChanged(QRect boundingRect); + void positionChanged(QRect boundingRect); + void zoomLevelChanged(int zoomLevel); + void themeChanged(Theme theme); + void fontChanged(QFont font); // TODO should be handled via axis?? What about font for selection label? + void shadowQualityChanged(QDataVis::ShadowQuality quality); + void labelTransparencyChanged(QDataVis::LabelTransparency transparency); + void axisTypeChanged(QAbstractAxis::AxisOrientation orientation, QAbstractAxis::AxisType type); + void axisTitleChanged(QAbstractAxis::AxisOrientation orientation, QString title); + void axisLabelsChanged(QAbstractAxis::AxisOrientation orientation, QStringList labels); + void axisRangeChanged(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); + void axisSegmentCountChanged(QAbstractAxis::AxisOrientation orientation, int count); + void axisSubSegmentCountChanged(QAbstractAxis::AxisOrientation orientation, int count); + void selectionModeChanged(QDataVis::SelectionMode mode); + void backgroundEnabledChanged(bool enable); + void gridEnabledChanged(bool enable); // TODO: Should be handled via axes? + void meshFileNameChanged(QString fileName); + +private: + void setAxisHelper(QAbstractAxis::AxisOrientation orientation, QAbstractAxis *axis, + QAbstractAxis **axisPtr); +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // CONTROLLER3DBASE_H diff --git a/src/datavis3d/engine/abstract3drenderer.cpp b/src/datavis3d/engine/abstract3drenderer.cpp new file mode 100644 index 00000000..b25e5a15 --- /dev/null +++ b/src/datavis3d/engine/abstract3drenderer.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "abstract3drenderer_p.h" +#include "qvalueaxis.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) + : QObject(controller), + m_controller(controller), + m_isInitialized(false), + m_hasNegativeValues(false), + m_drawer(new Drawer(m_cachedTheme, m_cachedFont, m_cachedLabelTransparency)), + m_autoScaleAdjustment(1.0f), + m_cachedZoomLevel(100) + +{ + QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Abstract3DRenderer::updateTextures); +} + +void Abstract3DRenderer::initializeOpenGL() +{ + axisCacheForOrientation(QAbstractAxis::AxisOrientationX).setDrawer(m_drawer); + axisCacheForOrientation(QAbstractAxis::AxisOrientationY).setDrawer(m_drawer); + axisCacheForOrientation(QAbstractAxis::AxisOrientationZ).setDrawer(m_drawer); +} + +void Abstract3DRenderer::updateDataModel(QAbstractDataProxy *dataProxy) +{ + m_cachedItemLabelFormat = dataProxy->itemLabelFormat(); +} + +QString Abstract3DRenderer::itemLabelFormat() const +{ + return m_cachedItemLabelFormat; +} + +void Abstract3DRenderer::updateBoundingRect(const QRect boundingRect) +{ + m_cachedBoundingRect = boundingRect; + handleResize(); +} + +void Abstract3DRenderer::updatePosition(const QRect boundingRect) +{ + m_cachedBoundingRect = boundingRect; +} + +void Abstract3DRenderer::updateTheme(Theme theme) +{ + m_cachedTheme.setFromTheme(theme); + + m_drawer->setTheme(m_cachedTheme); + // Re-initialize shaders + handleShadowQualityChange(); +} + +void Abstract3DRenderer::handleShadowQualityChange() +{ +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (!m_cachedTheme.m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } else { + if (!m_cachedTheme.m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } +#else + if (!m_cachedTheme.m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentColorOnYES2")); + } else { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); +#endif +} + +void Abstract3DRenderer::updateFont(const QFont &font) +{ + m_cachedFont = font; + m_drawer->setFont(font); +} + +void Abstract3DRenderer::updateLabelTransparency(QDataVis::LabelTransparency transparency) +{ + m_cachedLabelTransparency = transparency; + m_drawer->setTransparency(transparency); +} + +void Abstract3DRenderer::updateMeshFileName(const QString &objFileName) +{ + m_cachedObjFile = objFileName; +} + +void Abstract3DRenderer::updateSelectionMode(QDataVis::SelectionMode mode) +{ + m_cachedSelectionMode = mode; +} + +void Abstract3DRenderer::updateGridEnabled(bool enable) +{ + m_cachedIsGridEnabled = enable; +} + +void Abstract3DRenderer::updateBackgroundEnabled(bool enable) +{ + m_cachedIsBackgroundEnabled = enable; +} + +void Abstract3DRenderer::handleResize() +{ + if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) + return; + qDebug() << __FUNCTION__ << m_cachedBoundingRect.width() << "x" << m_cachedBoundingRect.height(); + // Calculate zoom level based on aspect ratio + GLfloat div; + GLfloat zoomAdjustment; + div = qMin(m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); + zoomAdjustment = defaultRatio * ((m_cachedBoundingRect.width() / div) + / (m_cachedBoundingRect.height() / div)); + //qDebug() << "zoom adjustment" << zoomAdjustment; + m_autoScaleAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f + + // Re-init selection buffer + initSelectionBuffer(); + +#if !defined(QT_OPENGL_ES_2) + // Re-init depth buffer + updateDepthBuffer(); +#endif +} + +void Abstract3DRenderer::updateZoomLevel(int newZoomLevel) +{ + m_cachedZoomLevel = newZoomLevel; +} + +void Abstract3DRenderer::updateAxisType(QAbstractAxis::AxisOrientation orientation, QAbstractAxis::AxisType type) +{ + axisCacheForOrientation(orientation).setType(type); +} + +void Abstract3DRenderer::updateAxisTitle(QAbstractAxis::AxisOrientation orientation, const QString &title) +{ + axisCacheForOrientation(orientation).setTitle(title); +} + +void Abstract3DRenderer::updateAxisLabels(QAbstractAxis::AxisOrientation orientation, const QStringList &labels) +{ + axisCacheForOrientation(orientation).setLabels(labels); +} + +void Abstract3DRenderer::updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max) +{ + AxisRenderCache &cache = axisCacheForOrientation(orientation); + cache.setMin(min); + cache.setMax(max); +} + +void Abstract3DRenderer::updateAxisSegmentCount(QAbstractAxis::AxisOrientation orientation, int count) +{ + axisCacheForOrientation(orientation).setSegmentCount(count); +} + +void Abstract3DRenderer::updateAxisSubSegmentCount(QAbstractAxis::AxisOrientation orientation, int count) +{ + axisCacheForOrientation(orientation).setSubSegmentCount(count); +} + +AxisRenderCache &Abstract3DRenderer::axisCacheForOrientation(QAbstractAxis::AxisOrientation orientation) +{ + switch (orientation) { + case QAbstractAxis::AxisOrientationX: + return m_axisCacheX; + case QAbstractAxis::AxisOrientationY: + return m_axisCacheY; + case QAbstractAxis::AxisOrientationZ: + return m_axisCacheZ; + default: + qFatal(__FUNCTION__); + return m_axisCacheX; + } +} + + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/abstract3drenderer_p.h b/src/datavis3d/engine/abstract3drenderer_p.h new file mode 100644 index 00000000..3c5d1388 --- /dev/null +++ b/src/datavis3d/engine/abstract3drenderer_p.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 ABSTRACT3DRENDERER_P_H +#define ABSTRACT3DRENDERER_P_H + +#include <QtGui/QOpenGLFunctions> +#include <QtGui/QFont> + +#include "datavis3dglobal_p.h" +#include "abstract3dcontroller_p.h" +#include "axisrendercache_p.h" +#include "qabstractdataproxy.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class Abstract3DRenderer : public QObject, protected QOpenGLFunctions +{ +protected: + Abstract3DController *m_controller; + bool m_isInitialized; + bool m_hasNegativeValues; + QRect m_cachedBoundingRect; + QDataVis::ShadowQuality m_cachedShadowQuality; + Theme m_cachedTheme; + QFont m_cachedFont; + QDataVis::LabelTransparency m_cachedLabelTransparency; + Drawer *m_drawer; + GLfloat m_autoScaleAdjustment; + QString m_cachedItemLabelFormat; + QString m_cachedObjFile; + QDataVis::SelectionMode m_cachedSelectionMode; + bool m_cachedIsGridEnabled; + bool m_cachedIsBackgroundEnabled; + int m_cachedZoomLevel; + + AxisRenderCache m_axisCacheX; + AxisRenderCache m_axisCacheY; + AxisRenderCache m_axisCacheZ; + + Abstract3DRenderer(Abstract3DController *controller); + virtual void initializeOpenGL(); + +public: + inline bool isInitialized() { return m_isInitialized; } + + virtual void updateBoundingRect(const QRect boundingRect); + virtual void updatePosition(const QRect boundingRect); + virtual void handleResize(); + + virtual void updateZoomLevel(int newZoomLevel); + virtual void updateTheme(Theme theme); + virtual void updateFont(const QFont &font); + virtual void updateLabelTransparency(QDataVis::LabelTransparency transparency); + virtual void updateSelectionMode(QDataVis::SelectionMode newMode); + virtual void updateGridEnabled(bool enable); + virtual void updateBackgroundEnabled(bool enable); + virtual void updateMeshFileName(const QString &objFileName); + + virtual void handleShadowQualityChange(); + + void updateDataModel(QAbstractDataProxy *dataProxy); + virtual QString itemLabelFormat() const; + virtual void requestSelectionAtPoint(const QPoint &point) = 0; + virtual void updateTextures() = 0; + virtual void initSelectionBuffer() = 0; +#if !defined(QT_OPENGL_ES_2) + virtual void updateDepthBuffer() = 0; +#endif + virtual void updateShadowQuality(QDataVis::ShadowQuality quality) = 0; + virtual void initShaders(const QString &vertexShader, const QString &fragmentShader) = 0; + virtual void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader) = 0; + virtual void updateAxisType(QAbstractAxis::AxisOrientation orientation, QAbstractAxis::AxisType type); + virtual void updateAxisTitle(QAbstractAxis::AxisOrientation orientation, const QString &title); + virtual void updateAxisLabels(QAbstractAxis::AxisOrientation orientation, const QStringList &labels); + virtual void updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); + virtual void updateAxisSegmentCount(QAbstractAxis::AxisOrientation orientation, int count); + virtual void updateAxisSubSegmentCount(QAbstractAxis::AxisOrientation orientation, int count); + + AxisRenderCache &axisCacheForOrientation(QAbstractAxis::AxisOrientation orientation); + +public: + /** + * @brief render Implements OpenGL rendering that occurs in the rendering thread. + * @param defaultFboHandle Defaults FBO handle (defaults to 0). + */ + virtual void render(CameraHelper *camera, const GLuint defaultFboHandle) = 0; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // ABSTRACT3DRENDERER_P_H diff --git a/src/datavis3d/engine/axisrendercache.cpp b/src/datavis3d/engine/axisrendercache.cpp new file mode 100644 index 00000000..4374d545 --- /dev/null +++ b/src/datavis3d/engine/axisrendercache.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "axisrendercache_p.h" +#include "qmath.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +AxisRenderCache::AxisRenderCache() + : m_type(QAbstractAxis::AxisTypeNone), + m_min(0.0), + m_max(10.0), + m_segmentCount(5), + m_subSegmentCount(1), + m_drawer(0), + m_segmentStep(10.0f), + m_subSegmentStep(10.0f) +{ +} + +AxisRenderCache::~AxisRenderCache() +{ + foreach (LabelItem *label, m_labelItems) + delete label; +} + +void AxisRenderCache::setDrawer(Drawer *drawer) +{ + m_drawer = drawer; + if (m_drawer) { + QObject::connect(m_drawer, &Drawer::drawerChanged, this, &AxisRenderCache::updateTextures); + updateTextures(); + } +} + +void AxisRenderCache::setType(QAbstractAxis::AxisType type) +{ + m_type = type; + + // If type is set, it means completely new axis instance, so clear all generated label items. + m_titleItem.clear(); + foreach (LabelItem *label, m_labelItems) + delete label; + m_labelItems.clear(); +} + +void AxisRenderCache::setTitle(const QString &title) +{ + if (m_title != title) { + m_title = title; + // Generate axis label texture + if (m_drawer) + m_drawer->generateLabelItem(m_titleItem, title); + } +} + +void AxisRenderCache::setLabels(const QStringList &labels) +{ + if (m_labels != labels) { + int newSize(labels.size()); + int oldSize(m_labels.size()); + + for (int i = newSize; i < oldSize; i++) + delete m_labelItems.takeLast(); + + m_labelItems.reserve(newSize); + + if (m_drawer) { + for (int i = 0; i < newSize; i++) { + if (i >= oldSize) + m_labelItems.append(new LabelItem); + if (labels.at(i).isEmpty()) + m_labelItems[i]->clear(); + else if (i >= oldSize || labels.at(i) != m_labels.at(i)) + m_drawer->generateLabelItem(*m_labelItems[i], labels.at(i)); + } + } + m_labels = labels; + } +} + +void AxisRenderCache::setMin(qreal min) +{ + m_min = min; + updateSegmentStep(); +} + +void AxisRenderCache::setMax(qreal max) +{ + m_max = max; + updateSegmentStep(); +} + +void AxisRenderCache::setSegmentCount(int count) +{ + m_segmentCount = count; + updateSegmentStep(); +} + +void AxisRenderCache::setSubSegmentCount(int count) +{ + m_subSegmentCount = count; + updateSubSegmentStep(); +} + +void AxisRenderCache::updateTextures() +{ + if (m_title.isEmpty()) + m_titleItem.clear(); + else + m_drawer->generateLabelItem(m_titleItem, m_title); + + for (int i = 0; i < m_labels.size(); i++) { + if (m_labels.at(i).isEmpty()) + m_labelItems[i]->clear(); + else + m_drawer->generateLabelItem(*m_labelItems[i], m_labels.at(i)); + } +} + +void AxisRenderCache::updateSegmentStep() +{ + if (m_segmentCount > 0) + m_segmentStep = qFabs((m_max - m_min) / m_segmentCount); + else + m_segmentStep = 0.0f; // Irrelevant + updateSubSegmentStep(); +} + +void AxisRenderCache::updateSubSegmentStep() +{ + if (m_subSegmentCount > 1) + m_subSegmentStep = m_segmentStep / m_subSegmentCount; + else + m_subSegmentStep = m_segmentStep; +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/axisrendercache_p.h b/src/datavis3d/engine/axisrendercache_p.h new file mode 100644 index 00000000..4b38fa20 --- /dev/null +++ b/src/datavis3d/engine/axisrendercache_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 AXISRENDERCACHE_P_H +#define AXISRENDERCACHE_P_H + +#include "datavis3dglobal_p.h" +#include "labelitem_p.h" +#include "qabstractaxis_p.h" +#include "drawer_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class AxisRenderCache : public QObject +{ + Q_OBJECT +public: + AxisRenderCache(); + virtual ~AxisRenderCache(); + + void setDrawer(Drawer *drawer); + + void setType(QAbstractAxis::AxisType type); + inline QAbstractAxis::AxisType type() const { return m_type; } + void setTitle(const QString &title); + inline const QString &title() { return m_title; } + void setLabels(const QStringList &labels); + inline const QStringList &labels() { return m_labels; } + void setMin(qreal min); + inline qreal min() { return m_min; } + void setMax(qreal max); + inline qreal max() { return m_max; } + void setSegmentCount(int count); + inline int segmentCount() const { return m_segmentCount; } + void setSubSegmentCount(int count); + inline int subSegmentCount() const { return m_subSegmentCount; } + + inline LabelItem &titleItem() { return m_titleItem; } + inline QList<LabelItem *> &labelItems() { return m_labelItems; } + inline GLfloat segmentStep() const { return m_segmentStep; } + inline GLfloat subSegmentStep() const { return m_subSegmentStep; } + +public slots: + void updateTextures(); + +private: + void updateSegmentStep(); + void updateSubSegmentStep(); + + // Cached axis values + QAbstractAxis::AxisType m_type; + QString m_title; + QStringList m_labels; + qreal m_min; + qreal m_max; + int m_segmentCount; + int m_subSegmentCount; + + // Renderer items + Drawer *m_drawer; // Not owned + LabelItem m_titleItem; + QList<LabelItem *> m_labelItems; + GLfloat m_segmentStep; + GLfloat m_subSegmentStep; + + Q_DISABLE_COPY(AxisRenderCache) +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/bars3dcontroller.cpp b/src/datavis3d/engine/bars3dcontroller.cpp new file mode 100644 index 00000000..3f5a31b2 --- /dev/null +++ b/src/datavis3d/engine/bars3dcontroller.cpp @@ -0,0 +1,457 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "bars3dcontroller_p.h" +#include "bars3drenderer_p.h" +#include "camerahelper_p.h" +#include "qabstractaxis_p.h" +#include "qvalueaxis_p.h" +#include "qcategoryaxis.h" +#include "qbardataproxy_p.h" + +#include <QMatrix4x4> +#include <QMouseEvent> +#include <qmath.h> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +Bars3dController::Bars3dController(QRect boundRect) + : Abstract3DController(boundRect), + m_rowCount(0), + m_columnCount(0), + m_mouseState(MouseNone), + m_mousePos(QPoint(0, 0)), + m_isSlicingActivated(false), + m_isBarSpecRelative(true), + m_barThickness(QSizeF(0.75f, 0.75f)), + m_barSpacing(m_barThickness * 3.0f), + m_renderer(0), + m_data(0) +{ + // Default axes + setAxisX(new QCategoryAxis()); + setAxisY(new QValueAxis()); + setAxisZ(new QCategoryAxis()); + + setBarType(QDataVis::Bars, false); // default object type + + setDataProxy(new QBarDataProxy); +} + +Bars3dController::~Bars3dController() +{ + delete m_data; +} + +void Bars3dController::initializeOpenGL() +{ + // Initialization is called multiple times when Qt Quick components are used + if (isInitialized()) + return; + + m_renderer = new Bars3dRenderer(this); + setRenderer(m_renderer); +} + +void Bars3dController::synchDataToRenderer() +{ + Abstract3DController::synchDataToRenderer(); + + if (!isInitialized()) + return; + + // Notify changes to renderer + if (m_changeTracker.slicingActiveChanged) { + m_renderer->updateSlicingActive(m_isSlicingActivated); + m_changeTracker.slicingActiveChanged = false; + } + + if (m_changeTracker.sampleSpaceChanged) { + m_renderer->updateSampleSpace(m_rowCount, m_columnCount); + m_changeTracker.sampleSpaceChanged = false; + } + + if (m_changeTracker.barSpecsChanged) { + m_renderer->updateBarSpecs(m_barThickness, m_barSpacing, m_isBarSpecRelative); + m_changeTracker.barSpecsChanged = false; + } + + if (m_isDataDirty) { + m_renderer->updateDataModel(m_data); + m_isDataDirty = false; + } +} + +QMatrix4x4 Bars3dController::calculateViewMatrix(int zoom, int viewPortWidth, + int viewPortHeight, bool showUnder) +{ + return m_cameraHelper->calculateViewMatrix(m_mousePos, + zoom, + viewPortWidth, + viewPortHeight, + showUnder); +} + +bool Bars3dController::isSlicingActive() +{ + return m_isSlicingActivated; +} + +void Bars3dController::setSlicingActive(bool isSlicing) +{ + m_isSlicingActivated = isSlicing; + + m_changeTracker.slicingActiveChanged = true; + emit slicingActiveChanged(m_isSlicingActivated); +} + +Bars3dController::MouseState Bars3dController::mouseState() +{ + return m_mouseState; +} + + +#if defined(Q_OS_ANDROID) +void Bars3dController::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (!m_isSlicingActivated) { + m_mouseState = Bars3dController::MouseOnScene; + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = event->pos(); + } +} + +void Bars3dController::touchEvent(QTouchEvent *event) +{ + static int prevDistance = 0; + + QList<QTouchEvent::TouchPoint> points; + points = event->touchPoints(); + + if (!m_isSlicingActivated && points.count() == 2) { + m_mouseState = Bars3dController::MouseOnPinch; + + QPointF distance = points.at(0).pos() - points.at(1).pos(); + int newDistance = distance.manhattanLength(); + int zoomRate = 1; + int zoomLevel = m_zoomLevel; + if (zoomLevel > 100) + zoomRate = 5; + if (newDistance > prevDistance) + zoomLevel += zoomRate; + else + zoomLevel -= zoomRate; + if (zoomLevel > 500) + zoomLevel = 500; + else if (zoomLevel < 10) + zoomLevel = 10; + setZoomLevel(zoomLevel); + prevDistance = newDistance; + //qDebug() << "distance" << distance.manhattanLength(); + } +} +#endif + +void Bars3dController::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) +{ + QRect mainViewPort = m_renderer->mainViewPort(); + if (Qt::LeftButton == event->button()) { + if (m_isSlicingActivated) { + if (mousePos.x() <= mainViewPort.width() + && mousePos.y() <= mainViewPort.height()) { + m_mouseState = Bars3dController::MouseOnOverview; + //qDebug() << "Mouse pressed on overview"; + } else { + m_mouseState = Bars3dController::MouseOnZoom; + //qDebug() << "Mouse pressed on zoom"; + } + } else { +#if !defined(Q_OS_ANDROID) + m_mouseState = Bars3dController::MouseOnScene; +#else + m_mouseState = Bars3dController::MouseRotating; +#endif + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = mousePos; + //qDebug() << "Mouse pressed on scene"; + } + } else if (Qt::MiddleButton == event->button()) { + // reset rotations + m_mousePos = QPoint(0, 0); + } else if (!m_isSlicingActivated && Qt::RightButton == event->button()) { + // disable rotating when in slice view +#if !defined(Q_OS_ANDROID) + m_mouseState = Bars3dController::MouseRotating; +#else + m_mouseState = Bars3dController::MouseOnScene; +#endif + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = mousePos; + } + m_cameraHelper->updateMousePos(m_mousePos); +} + +void Bars3dController::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event); + if (Bars3dController::MouseRotating == m_mouseState) { + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = mousePos; + m_cameraHelper->updateMousePos(mousePos); + } + m_mouseState = Bars3dController::MouseNone; +} + +void Bars3dController::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event); + if (Bars3dController::MouseRotating == m_mouseState) + m_mousePos = mousePos; +} + +void Bars3dController::wheelEvent(QWheelEvent *event) +{ + // disable zooming if in slice view + if (m_isSlicingActivated) + return; + + int zoomLevel = m_zoomLevel; + if (zoomLevel > 100) + zoomLevel += event->angleDelta().y() / 12; + else if (zoomLevel > 50) + zoomLevel += event->angleDelta().y() / 60; + else + zoomLevel += event->angleDelta().y() / 120; + if (zoomLevel > 500) + zoomLevel = 500; + else if (zoomLevel < 10) + zoomLevel = 10; + + setZoomLevel(zoomLevel); +} + +void Bars3dController::setDataProxy(QBarDataProxy *proxy) +{ + delete m_data; + m_data = proxy; + + QObject::connect(m_data, &QBarDataProxy::arrayReset, this, + &Bars3dController::handleArrayReset); + QObject::connect(m_data, &QBarDataProxy::rowsAdded, this, + &Bars3dController::handleRowsAdded); + QObject::connect(m_data, &QBarDataProxy::rowsChanged, this, + &Bars3dController::handleRowsChanged); + QObject::connect(m_data, &QBarDataProxy::rowsRemoved, this, + &Bars3dController::handleRowsRemoved); + QObject::connect(m_data, &QBarDataProxy::rowsInserted, this, + &Bars3dController::handleRowsInserted); + QObject::connect(m_data, &QBarDataProxy::itemChanged, this, + &Bars3dController::handleItemChanged); + + adjustValueAxisRange(); + m_isDataDirty = true; +} + +QBarDataProxy *Bars3dController::dataProxy() +{ + return m_data; +} + +void Bars3dController::handleArrayReset() +{ + setSlicingActive(false); + adjustValueAxisRange(); + m_isDataDirty = true; +} + +void Bars3dController::handleRowsAdded(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO check if affects data window + // TODO should update slice instead of deactivating? + setSlicingActive(false); + adjustValueAxisRange(); + m_isDataDirty = true; +} + +void Bars3dController::handleRowsChanged(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO check if affects data window + // TODO should update slice instead of deactivating? + setSlicingActive(false); + adjustValueAxisRange(); + m_isDataDirty = true; +} + +void Bars3dController::handleRowsRemoved(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO check if affects data window + // TODO should update slice instead of deactivating? + setSlicingActive(false); + adjustValueAxisRange(); + m_isDataDirty = true; +} + +void Bars3dController::handleRowsInserted(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO check if affects data window + // TODO should update slice instead of deactivating? + setSlicingActive(false); + adjustValueAxisRange(); + m_isDataDirty = true; +} + +void Bars3dController::handleItemChanged(int rowIndex, int columnIndex) +{ + Q_UNUSED(rowIndex) + Q_UNUSED(columnIndex) + // TODO check if affects data window + // TODO should update slice instead of deactivating? + setSlicingActive(false); + adjustValueAxisRange(); + m_isDataDirty = true; +} + +void Bars3dController::handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust) +{ + Q_UNUSED(orientation) + Q_UNUSED(autoAdjust) + adjustValueAxisRange(); +} + +void Bars3dController::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative) +{ + m_barThickness = thickness; + m_barSpacing = spacing; + m_isBarSpecRelative = relative; + + m_changeTracker.barSpecsChanged = true; + emit barSpecsChanged(thickness, spacing, relative); +} + +QSizeF Bars3dController::barThickness() +{ + return m_barThickness; +} + +QSizeF Bars3dController::barSpacing() +{ + return m_barSpacing; +} + +bool Bars3dController::isBarSpecRelative() +{ + return m_isBarSpecRelative; +} + +void Bars3dController::setBarType(QDataVis::MeshStyle style, bool smooth) +{ + QString objFile; + if (style == QDataVis::Bars) { + if (smooth) + objFile = QStringLiteral(":/defaultMeshes/barSmooth"); + else + objFile = QStringLiteral(":/defaultMeshes/bar"); + } else if (style == QDataVis::Pyramids) { + if (smooth) + objFile = QStringLiteral(":/defaultMeshes/pyramidSmooth"); + else + objFile = QStringLiteral(":/defaultMeshes/pyramid"); + } else if (style == QDataVis::Cones) { + if (smooth) + objFile = QStringLiteral(":/defaultMeshes/coneSmooth"); + else + objFile = QStringLiteral(":/defaultMeshes/cone"); + } else if (style == QDataVis::Cylinders) { + if (smooth) + objFile = QStringLiteral(":/defaultMeshes/cylinderSmooth"); + else + objFile = QStringLiteral(":/defaultMeshes/cylinder"); + } else if (style == QDataVis::BevelBars) { + if (smooth) + objFile = QStringLiteral(":/defaultMeshes/bevelbarSmooth"); + else + objFile = QStringLiteral(":/defaultMeshes/bevelbar"); + } + Abstract3DController::setMeshFileName(objFile); +} + +// TODO: This sets data window. Needs more parameters, now assumes window always starts at 0,0. +void Bars3dController::setupSampleSpace(int rowCount, int columnCount) +{ + // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted) + setSlicingActive(false); + + m_rowCount = rowCount; + m_columnCount = columnCount; + + adjustValueAxisRange(); + + m_changeTracker.sampleSpaceChanged = true; + emit sampleSpaceChanged(rowCount, columnCount); +} + +void Bars3dController::setSelectionMode(QDataVis::SelectionMode mode) +{ + // Disable zoom if selection mode changes + setSlicingActive(false); + Abstract3DController::setSelectionMode(mode); +} + +QPoint Bars3dController::mousePosition() +{ + return m_mousePos; +} + +int Bars3dController::columnCount() +{ + return m_columnCount; +} + +int Bars3dController::rowCount() +{ + return m_rowCount; +} + +void Bars3dController::adjustValueAxisRange() +{ + QValueAxis *valueAxis = static_cast<QValueAxis *>(m_axisY); + if (valueAxis && valueAxis->isAutoAdjustRange() && m_data) { + QPair<GLfloat, GLfloat> limits = m_data->dptr()->limitValues(0, m_rowCount, + 0, m_columnCount); + if (limits.first < 0) { + // TODO: Currently we only support symmetric y-axis for bar chart if there are negative values + qreal maxAbs = qMax(qFabs(limits.first), qFabs(limits.second)); + // Call private implementation to avoid unsetting auto adjust flag + valueAxis->dptr()->setRange(-maxAbs, maxAbs); + } else if (limits.second == 0.0) { + valueAxis->dptr()->setRange(0.0, 1.0); // Only zero value values in data set, set range to something. + } else { + valueAxis->dptr()->setRange(0.0, limits.second); + } + } +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/bars3dcontroller_p.h b/src/datavis3d/engine/bars3dcontroller_p.h new file mode 100644 index 00000000..9811eb0d --- /dev/null +++ b/src/datavis3d/engine/bars3dcontroller_p.h @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 Q3DBARSCONTROLLER_p_H +#define Q3DBARSCONTROLLER_p_H + +#include "datavis3dglobal_p.h" +#include "abstract3dcontroller_p.h" + +//#define DISPLAY_RENDER_SPEED + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class Bars3dRenderer; +class QBarDataProxy; + +struct Bars3DChangeBitField { + bool slicingActiveChanged : 1; + bool sampleSpaceChanged : 1; + bool barSpecsChanged : 1; + + Bars3DChangeBitField() : + slicingActiveChanged(true), + sampleSpaceChanged(true), + barSpecsChanged(true) + { + } +}; + +class QT_DATAVIS3D_EXPORT Bars3dController : public Abstract3DController +{ + Q_OBJECT + +private: + + + Bars3DChangeBitField m_changeTracker; + + // Data + int m_rowCount; + int m_columnCount; + + // Interaction + MouseState m_mouseState; + QPoint m_mousePos; + bool m_isSlicingActivated; + + // Look'n'feel + bool m_isBarSpecRelative; + QSizeF m_barThickness; + QSizeF m_barSpacing; + + // Rendering + Bars3dRenderer *m_renderer; + QBarDataProxy *m_data; + +public: + explicit Bars3dController(QRect rect); + ~Bars3dController(); + + void initializeOpenGL(); + virtual void synchDataToRenderer(); + + int columnCount(); + int rowCount(); + + MouseState mouseState(); + QPoint mousePosition(); + + bool isSlicingActive(); + void setSlicingActive(bool isSlicing); + + QMatrix4x4 calculateViewMatrix(int zoom, int viewPortWidth, int viewPortHeight, bool showUnder = false); + + // bar thickness, spacing between bars, and is spacing relative to thickness or absolute + // y -component sets the thickness/spacing of z -direction + // With relative 0.0f means side-to-side, 1.0f = one thickness in between + void setBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f), + QSizeF spacing = QSizeF(1.0f, 1.0f), + bool relative = true); + QSizeF barThickness(); + QSizeF barSpacing(); + bool isBarSpecRelative(); + + // bar type; bars (=cubes), pyramids, cones, cylinders, etc. + void setBarType(QDataVis::MeshStyle style, bool smooth = false); + + // how many samples per row and column, and names for axes + void setupSampleSpace(int samplesRow, int samplesColumn); + + // Change selection mode; single bar, bar and row, bar and column, or all + void setSelectionMode(QDataVis::SelectionMode mode); + +#if defined(Q_OS_ANDROID) + void mouseDoubleClickEvent(QMouseEvent *event); + void touchEvent(QTouchEvent *event); +#endif + void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); + void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); + void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); + void wheelEvent(QWheelEvent *event); + + // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. + void setDataProxy(QBarDataProxy *proxy); + QBarDataProxy *dataProxy(); + virtual void handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust); + +public slots: + void handleArrayReset(); + void handleRowsAdded(int startIndex, int count); + void handleRowsChanged(int startIndex, int count); + void handleRowsRemoved(int startIndex, int count); + void handleRowsInserted(int startIndex, int count); + void handleItemChanged(int rowIndex, int columnIndex); + + +signals: + void slicingActiveChanged(bool isSlicing); + void sampleSpaceChanged(int samplesRow, int samplesColumn); + void barSpecsChanged(QSizeF thickness, QSizeF spacing, bool relative); + +private: + void adjustValueAxisRange(); + + Q_DISABLE_COPY(Bars3dController) + +}; + + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/bars3drenderer.cpp b/src/datavis3d/engine/bars3drenderer.cpp new file mode 100644 index 00000000..908b7888 --- /dev/null +++ b/src/datavis3d/engine/bars3drenderer.cpp @@ -0,0 +1,1839 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "bars3drenderer_p.h" +#include "bars3dcontroller_p.h" +#include "camerahelper_p.h" +#include "shaderhelper_p.h" +#include "objecthelper_p.h" +#include "texturehelper_p.h" +#include "theme_p.h" +#include "utils_p.h" +#include "drawer_p.h" +#include "qbardataitem.h" + +#include <QMatrix4x4> +#include <QMouseEvent> +#include <QThread> +#include <qmath.h> +#include <QDebug> + +// Commenting this draws the shadow map with perspective projection. Otherwise it's drawn in +// orthographic projection. +//#define USE_WIDER_SHADOWS + +// You can verify that depth buffer drawing works correctly by uncommenting this. +// You should see the scene from where the light is +//#define SHOW_DEPTH_TEXTURE_SCENE + +#ifdef DISPLAY_RENDER_SPEED +#include <QTime> +#endif + +QT_DATAVIS3D_BEGIN_NAMESPACE + +#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels + +const GLfloat gridLineWidth = 0.005f; +static QVector3D selectionSkipColor = QVector3D(255, 255, 255); // Selection texture's background color + +Bars3dRenderer::Bars3dRenderer(Bars3dController *controller) + : Abstract3DRenderer(controller), + m_controller(controller), + m_selectedBar(0), + m_previouslySelectedBar(0), + m_sliceSelection(0), + m_sliceCache(0), + m_sliceTitleItem(0), + m_xFlipped(false), + m_zFlipped(false), + m_yFlipped(false), + m_updateLabels(false), + m_barShader(0), + m_depthShader(0), + m_selectionShader(0), + m_backgroundShader(0), + m_labelShader(0), + m_barObj(0), + m_backgroundObj(0), + m_gridLineObj(0), + m_labelObj(0), + m_bgrTexture(0), + m_depthTexture(0), + m_selectionTexture(0), + m_depthFrameBuffer(0), + m_selectionFrameBuffer(0), + m_selectionDepthBuffer(0), + m_shadowQualityToShader(33.3f), + m_heightNormalizer(1.0f), + m_yAdjustment(0.0f), + m_rowWidth(0), + m_columnDepth(0), + m_maxDimension(0), + m_scaleX(0), + m_scaleZ(0), + m_scaleFactor(0), + m_maxSceneSize(40.0), + m_selection(selectionSkipColor), + m_hasHeightAdjustmentChanged(true) + #ifdef DISPLAY_RENDER_SPEED + ,m_isFirstFrame(true), + m_numFrames(0) + #endif +{ + m_dummyBarRenderItem.setRenderer(this); + initializeOpenGLFunctions(); + initializeOpenGL(); +} + +Bars3dRenderer::~Bars3dRenderer() +{ + m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); + m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); + m_textureHelper->deleteTexture(&m_selectionTexture); + m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); + m_textureHelper->deleteTexture(&m_bgrTexture); + if (m_sliceSelection) { + m_sliceSelection->clear(); // Slice doesn't own its items + delete m_sliceSelection; + } + delete m_barShader; + delete m_depthShader; + delete m_selectionShader; + delete m_backgroundShader; + delete m_barObj; + delete m_backgroundObj; + delete m_gridLineObj; + delete m_textureHelper; + delete m_drawer; +} + +void Bars3dRenderer::initializeOpenGL() +{ + m_textureHelper = new TextureHelper(); + m_drawer->initializeOpenGL(); + + // Initialize shaders + handleShadowQualityChange(); + initLabelShaders(QStringLiteral(":/shaders/vertexLabel"), + QStringLiteral(":/shaders/fragmentLabel")); + +#if !defined(QT_OPENGL_ES_2) + // Init depth shader (for shadows). Init in any case, easier to handle shadow activation if done via api. + initDepthShader(); +#endif + + // Init selection shader + initSelectionShader(); + + // Load grid line mesh + loadGridLineMesh(); + + // Load label mesh + loadLabelMesh(); + + // Set OpenGL features + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + +#if !defined(QT_OPENGL_ES_2) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); +#endif + + // Set view port + glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(), + m_sliceViewPort.width(), m_sliceViewPort.height()); + + // Load background mesh (we need to be initialized first) + loadBackgroundMesh(); + + Abstract3DRenderer::initializeOpenGL(); +} + +void Bars3dRenderer::updateDataModel(QBarDataProxy *dataProxy) +{ + // Update cached data window + int dataRowCount = dataProxy->rowCount(); + for (int i = 0; i < m_renderItemArray.size(); i++) { + int j = 0; + if (i < dataRowCount) { + const QBarDataRow *dataRow = dataProxy->rowAt(i); + int updateSize = qMin(dataRow->size(), m_renderItemArray[i].size()); + if (dataRow) { + for (; j < updateSize ; j++) { + qreal value = dataRow->at(j).value(); + m_renderItemArray[i][j].setValue(value); + m_renderItemArray[i][j].setHeight(value / m_heightNormalizer); + } + } + } + for (; j < m_renderItemArray[i].size(); j++) { + m_renderItemArray[i][j].setValue(0.0); + m_renderItemArray[i][j].setHeight(0.0f); + } + } + + Abstract3DRenderer::updateDataModel(dataProxy); +} + +void Bars3dRenderer::render(CameraHelper *camera, const GLuint defaultFboHandle) +{ +#ifdef DISPLAY_RENDER_SPEED + // For speed computation + if (m_isFirstFrame) { + m_lastFrameTime.start(); + m_isFirstFrame = false; + } + + // Measure speed (as milliseconds per frame) + m_numFrames++; + if (m_lastFrameTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago + qDebug() << qreal(m_lastFrameTime.elapsed()) / qreal(m_numFrames) << "ms/frame (=" << qreal(m_numFrames) << "fps)"; + m_numFrames = 0; + m_lastFrameTime.restart(); + } +#endif + + if (defaultFboHandle) { + glDepthMask(true); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + } + + QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme.m_windowColor); + glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (m_hasHeightAdjustmentChanged) { + // Set initial camera position. Also update if height adjustment has changed. + camera->setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp), + QVector3D(0.0f, -m_yAdjustment, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + m_hasHeightAdjustmentChanged = false; + } + + // If slice selection is on, draw the sliced scene + if (m_cachedIsSlicingActivated) + drawSlicedScene(camera, m_axisCacheX.titleItem(), m_axisCacheY.titleItem(), m_axisCacheZ.titleItem()); + + // Draw bars scene + drawScene(camera, defaultFboHandle); +} + +void Bars3dRenderer::drawSlicedScene(CameraHelper *camera, + const LabelItem &xLabel, + const LabelItem &yLabel, + const LabelItem &zLabel) +{ + GLfloat barPosX = 0; + GLint startBar = 0; + GLint stopBar = m_sliceSelection->size(); + GLint stepBar = 1; + QVector3D lightPos; + + // Specify viewport + glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(), + m_sliceViewPort.width(), m_sliceViewPort.height()); + + // Set up projection matrix + QMatrix4x4 projectionMatrix; + projectionMatrix.perspective(45.0f, (GLfloat)m_sliceViewPort.width() + / (GLfloat)m_sliceViewPort.height(), 0.1f, 100.0f); + +#ifdef ROTATE_ZOOM_SELECTION + // Calculate view matrix + QMatrix4x4 viewMatrix = m_controller->calculateViewMatrix(m_cachedZoomLevel * m_autoScaleAdjustment, + m_sliceViewPort.width(), + m_sliceViewPort.height()); + + // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) + lightPos = camera->calculateLightPosition(defaultLightPos); + + if (viewMatrix.row(0).z() <= 0) { + startBar = m_sliceSelection->size() - 1; + stopBar = -1; + stepBar = -1; + } +#else + // Set view matrix + QMatrix4x4 viewMatrix; + + // Adjust scaling (zoom rate based on aspect ratio) + GLfloat camPosZoomed = 5.0f / m_autoScaleAdjustment + zComp; + + viewMatrix.lookAt(QVector3D(0.0f, 0.0f, camPosZoomed), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + + // Set light position a bit below the camera to reduce glare (depends on do we have row or column zoom) + QVector3D sliceLightPos = defaultLightPos; + sliceLightPos.setY(-10.0f); + if (QDataVis::ModeZoomColumn == m_cachedSelectionMode) + lightPos = camera->calculateLightPosition(sliceLightPos, -85.0f); + else + lightPos = camera->calculateLightPosition(sliceLightPos, 5.0f); +#endif + + // Bind bar shader + m_barShader->bind(); + + // Draw bars + // Draw the selected row / column + for (int bar = startBar; bar != stopBar; bar += stepBar) { + BarRenderItem *item = m_sliceSelection->at(bar); + if (!item) + continue; + + if (item->height() < 0) + glCullFace(GL_FRONT); + else + glCullFace(GL_BACK); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 itModelMatrix; + + GLfloat barPosY = item->translation().y() - m_yAdjustment / 2.0f + 0.2f; // we need some room for labels underneath; add +0.2f + if (QDataVis::ModeZoomRow == m_cachedSelectionMode) + barPosX = item->translation().x(); + else + barPosX = -(item->translation().z() - zComp); // flip z; frontmost bar to the left + modelMatrix.translate(barPosX, barPosY, zComp); + modelMatrix.scale(QVector3D(m_scaleX, item->height(), m_scaleZ)); + itModelMatrix.scale(QVector3D(m_scaleX, item->height(), m_scaleZ)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + + QVector3D baseColor = Utils::vectorFromColor(m_cachedTheme.m_baseColor); + QVector3D heightColor = Utils::vectorFromColor(m_cachedTheme.m_heightColor) * item->height(); + + QVector3D barColor = baseColor + heightColor; + + GLfloat lightStrength = m_cachedTheme.m_lightStrength; + + if (item->height() != 0) { + // Set shader bindings + m_barShader->setUniformValue(m_barShader->lightP(), lightPos); + m_barShader->setUniformValue(m_barShader->view(), viewMatrix); + m_barShader->setUniformValue(m_barShader->model(), modelMatrix); + m_barShader->setUniformValue(m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + m_barShader->setUniformValue(m_barShader->color(), barColor); + m_barShader->setUniformValue(m_barShader->lightS(), lightStrength); + m_barShader->setUniformValue(m_barShader->ambientS(), m_cachedTheme.m_ambientStrength); + + // Draw the object + m_drawer->drawObject(m_barShader, m_barObj); + } + } + + // Release bar shader + m_barShader->release(); + + // Draw labels + m_labelShader->bind(); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glCullFace(GL_BACK); + if (m_cachedLabelTransparency > QDataVis::TransparencyNone) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + // Draw labels for axes + BarRenderItem *dummyItem(0); + const LabelItem &sliceSelectionLabel = *m_sliceTitleItem; + if (QDataVis::ModeZoomRow == m_cachedSelectionMode) { + if (m_sliceTitleItem) { + m_drawer->drawLabel(*dummyItem, sliceSelectionLabel, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), 0, + m_cachedSelectionMode, m_labelShader, + m_labelObj, camera, false, false, Drawer::LabelTop); + } + m_drawer->drawLabel(*dummyItem, zLabel, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), 0, + m_cachedSelectionMode, m_labelShader, + m_labelObj, camera, false, false, Drawer::LabelBottom); + } else { + m_drawer->drawLabel(*dummyItem, xLabel, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), 0, + m_cachedSelectionMode, m_labelShader, + m_labelObj, camera, false, false, Drawer::LabelBottom); + if (m_sliceTitleItem) { + m_drawer->drawLabel(*dummyItem, sliceSelectionLabel, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), 0, + m_cachedSelectionMode, m_labelShader, + m_labelObj, camera, false, false, Drawer::LabelTop); + } + } + m_drawer->drawLabel(*dummyItem, yLabel, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 90.0f), 0, + m_cachedSelectionMode, m_labelShader, + m_labelObj, camera, false, false, Drawer::LabelLeft); + + // Draw labels for bars + for (int col = 0; col < m_sliceSelection->size(); col++) { + BarRenderItem *item = m_sliceSelection->at(col); + // Draw values + m_drawer->drawLabel(*item, item->labelItem(), viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), item->height(), + m_cachedSelectionMode, m_labelShader, + m_labelObj, camera); + + // Draw labels + if (m_sliceCache->labelItems().size() > col) { + const LabelItem *labelItem(0); + // If draw order of bars is flipped, label draw order should be too + if (m_xFlipped) { + labelItem = m_sliceCache->labelItems().at( + m_sliceCache->labelItems().size() - col - 1); + } else { + labelItem = m_sliceCache->labelItems().at(col); + } + m_drawer->drawLabel(*item, *labelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, -45.0f), item->height(), + m_cachedSelectionMode, m_labelShader, + m_labelObj, camera, false, false, Drawer::LabelBelow); + } + } + + glDisable(GL_TEXTURE_2D); + if (m_cachedLabelTransparency > QDataVis::TransparencyNone) + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + + // Release label shader + m_labelShader->release(); +} + +void Bars3dRenderer::drawScene(CameraHelper *camera, + const GLuint defaultFboHandle) +{ + GLint startBar = 0; + GLint stopBar = 0; + GLint stepBar = 0; + + GLint startRow = 0; + GLint stopRow = 0; + GLint stepRow = 0; + + GLfloat backgroundRotation = 0; + + GLfloat barPos = 0; + GLfloat rowPos = 0; + + //m_selection = selectionSkipColor; + + // Specify viewport + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width(), m_mainViewPort.height()); + + // Set up projection matrix + QMatrix4x4 projectionMatrix; + projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width() + / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f); + + // Calculate view matrix + QMatrix4x4 viewMatrix = m_controller->calculateViewMatrix( + m_cachedZoomLevel * m_autoScaleAdjustment, + m_mainViewPort.width(), + m_mainViewPort.height(), + m_hasNegativeValues); + + // Calculate drawing order + // Draw order is reversed to optimize amount of drawing (ie. draw front objects first, depth test handles not needing to draw objects behind them) + if (viewMatrix.row(0).x() > 0) { + startRow = 0; + stopRow = m_cachedRowCount; + stepRow = 1; + m_zFlipped = false; + } else { + startRow = m_cachedRowCount - 1; + stopRow = -1; + stepRow = -1; + m_zFlipped = true; + } + if (viewMatrix.row(0).z() <= 0) { + startBar = 0; + stopBar = m_cachedColumnCount; + stepBar = 1; + m_xFlipped = false; + } else { + startBar = m_cachedColumnCount - 1; + stopBar = -1; + stepBar = -1; + m_xFlipped = true; + } + + // Check if we're viewing the scene from below + if (viewMatrix.row(2).y() < 0) + m_yFlipped = true; + else + m_yFlipped = false; + + // calculate background rotation based on view matrix rotation + if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() <= 0) + backgroundRotation = 270.0f; + else if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() > 0) + backgroundRotation = 180.0f; + else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() > 0) + backgroundRotation = 90.0f; + else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() <= 0) + backgroundRotation = 0.0f; + + // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) + QVector3D lightPos = camera->calculateLightPosition(defaultLightPos); + + // Skip depth rendering if we're in slice mode + // TODO: Fix this, causes problems if depth rendering is off in slice mode + // Introduce regardless of shadow quality to simplify logic + QMatrix4x4 depthViewMatrix; + QMatrix4x4 depthProjectionMatrix; + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone/*!m_cachedIsSlicingActivated*/) { + // Render scene into a depth texture for using with shadow mapping + // Enable drawing to depth framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); + glClear(GL_DEPTH_BUFFER_BIT); + + // Bind depth shader + m_depthShader->bind(); + + // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width() * m_cachedShadowQuality, + m_mainViewPort.height() * m_cachedShadowQuality); + + // Get the depth view matrix + // It may be possible to hack lightPos here if we want to make some tweaks to shadow + QVector3D depthLightPos = camera->calculateLightPosition( + QVector3D(0.0f, 0.0f, zComp), 0.0f, 1.5f / m_autoScaleAdjustment); + depthViewMatrix.lookAt(depthLightPos, QVector3D(0.0f, -m_yAdjustment, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed + //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); + // Set the depth projection matrix +#ifndef USE_WIDER_SHADOWS + // Use this for perspective shadows + depthProjectionMatrix.perspective(15.0f, (GLfloat)m_mainViewPort.width() + / (GLfloat)m_mainViewPort.height(), 3.0f, 100.0f); +#else + // Use these for orthographic shadows + //GLfloat testAspectRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height(); + //qDebug() << m_autoScaleAdjustment << m_yAdjustment; + depthProjectionMatrix.ortho(-2.0f * 2.0f, 2.0f * 2.0f, + -2.0f, 2.0f, + 0.0f, 100.0f); +#endif + // Draw bars to depth buffer + for (int row = startRow; row != stopRow; row += stepRow) { + for (int bar = startBar; bar != stopBar; bar += stepBar) { + const BarRenderItem &item = m_renderItemArray.at(row).at(bar); + if (!item.value()) + continue; + + // Set front face culling for positive valued bars and back face culling for + // negative valued bars to reduce self-shadowing issues + if (item.height() < 0) + glCullFace(GL_BACK); + else + glCullFace(GL_FRONT); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + barPos = (bar + 1) * (m_cachedBarSpacing.width()); + rowPos = (row + 1) * (m_cachedBarSpacing.height()); + + modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor, + item.height() - m_yAdjustment, + (m_columnDepth - rowPos) / m_scaleFactor + zComp); + modelMatrix.scale(QVector3D(m_scaleX, item.height(), m_scaleZ)); + + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf()); + glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, + (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT, + (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(m_depthShader->posAtt()); + } + } + + // Disable drawing to depth framebuffer (= enable drawing to screen) + glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); + + // Release depth shader + m_depthShader->release(); + +#if 0 // Use this if you want to see what is being drawn to the framebuffer + // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it) + m_labelShader->bind(); + glCullFace(GL_BACK); + glEnable(GL_TEXTURE_2D); + QMatrix4x4 modelMatrix; + QMatrix4x4 viewmatrix; + viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.5f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + modelMatrix.translate(0.0, 0.0, zComp); + QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; + m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); + m_drawer->drawObject(m_labelShader, m_labelObj, + m_depthTexture); + glDisable(GL_TEXTURE_2D); + m_labelShader->release(); +#endif + // Reset culling to normal + glCullFace(GL_BACK); + + // Revert to original viewport + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width(), m_mainViewPort.height()); + } +#endif + + // Skip selection mode drawing if we're slicing or have no selection mode + if (!m_cachedIsSlicingActivated && m_cachedSelectionMode > QDataVis::ModeNone) { + // Bind selection shader + m_selectionShader->bind(); + + // Draw bars to selection buffer + glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); + glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used + glClearColor(selectionSkipColor.x() / 255, selectionSkipColor.y() / 255, + selectionSkipColor.z() / 255, 1.0f); // Set clear color to white (= selectionSkipColor) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer + glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled + for (int row = startRow; row != stopRow; row += stepRow) { + for (int bar = startBar; bar != stopBar; bar += stepBar) { + const BarRenderItem &item = m_renderItemArray.at(row).at(bar); + if (!item.value()) + continue; + + if (item.height() < 0) + glCullFace(GL_FRONT); + else + glCullFace(GL_BACK); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + barPos = (bar + 1) * (m_cachedBarSpacing.width()); + rowPos = (row + 1) * (m_cachedBarSpacing.height()); + + modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor, + item.height() - m_yAdjustment, + (m_columnDepth - rowPos) / m_scaleFactor + zComp); + modelMatrix.scale(QVector3D(m_scaleX, item.height(), m_scaleZ)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + + // TODO: Save position to qdataitem, so that we don't need to calculate it each time? + + //#if !defined(QT_OPENGL_ES_2) + // QVector3D barColor = QVector3D((GLdouble)row / 32767.0, + // (GLdouble)bar / 32767.0, + // 0.0); + //#else + QVector3D barColor = QVector3D((GLdouble)row / 255.0, + (GLdouble)bar / 255.0, + 0.0); + //#endif + + m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); + m_selectionShader->setUniformValue(m_selectionShader->color(), barColor); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_selectionShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf()); + glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, + (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(m_selectionShader->posAtt()); + } + } + glEnable(GL_DITHER); + + // Read color under cursor + if (Bars3dController::MouseOnScene == m_controller->mouseState()) + m_selection = Utils::getSelection(m_controller->mousePosition(), m_cachedBoundingRect.height()); + + QMutexLocker locker(&m_mutex); + if (m_isSelectionPointRequestActive) { + m_isSelectionPointRequestActive = false; + m_selection = Utils::getSelection(m_selectionPointRequest, m_cachedBoundingRect.height()); + emit selectionUpdated(m_selection); + } + locker.unlock(); + + glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); + + // Release selection shader + m_selectionShader->release(); + +#if 0 // Use this if you want to see what is being drawn to the framebuffer + glCullFace(GL_BACK); + m_labelShader->bind(); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + QMatrix4x4 modelMatrix; + QMatrix4x4 viewmatrix; + viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + modelMatrix.translate(0.0, 0.0, zComp); + QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; + m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); + m_drawer->drawObject(m_labelShader, m_labelObj, m_selectionTexture); + glDisable(GL_TEXTURE_2D); + m_labelShader->release(); +#endif + } + + // Enable texturing + glEnable(GL_TEXTURE_2D); + + // Bind bar shader + m_barShader->bind(); + + // Draw bars + if (!m_cachedIsSlicingActivated && m_sliceSelection) { + m_sliceSelection->clear(); // Slice doesn't own its items + m_sliceCache = 0; + m_sliceTitleItem = 0; + } + bool barSelectionFound = false; + for (int row = startRow; row != stopRow; row += stepRow) { + for (int bar = startBar; bar != stopBar; bar += stepBar) { + BarRenderItem &item = m_renderItemArray[row][bar]; + + if (item.height() < 0) + glCullFace(GL_FRONT); + else + glCullFace(GL_BACK); + + QMatrix4x4 modelMatrix; + QMatrix4x4 itModelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + + barPos = (bar + 1) * (m_cachedBarSpacing.width()); + rowPos = (row + 1) * (m_cachedBarSpacing.height()); + modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor, + item.height() - m_yAdjustment, + (m_columnDepth - rowPos) / m_scaleFactor + zComp); + modelMatrix.scale(QVector3D(m_scaleX, item.height(), m_scaleZ)); + itModelMatrix.scale(QVector3D(m_scaleX, item.height(), m_scaleZ)); +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + QVector3D baseColor = Utils::vectorFromColor(m_cachedTheme.m_baseColor); + QVector3D heightColor = Utils::vectorFromColor(m_cachedTheme.m_heightColor) * item.height(); + QVector3D depthColor = Utils::vectorFromColor(m_cachedTheme.m_depthColor) + * (float(row) / GLfloat(m_cachedRowCount)); + + QVector3D barColor = baseColor + heightColor + depthColor; + + GLfloat lightStrength = m_cachedTheme.m_lightStrength; + + if (m_cachedSelectionMode > QDataVis::ModeNone) { + Bars3dController::SelectionType selectionType = isSelected(row, bar); + + switch (selectionType) { + case Bars3dController::SelectionItem: { + barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor); + lightStrength = m_cachedTheme.m_highlightLightStrength; + // Insert data to QDataItem. We have no ownership, don't delete the previous one + if (!m_cachedIsSlicingActivated) { + m_selectedBar = &item; + m_selectedBar->setPosition(QPoint(row, bar)); + item.setTranslation(modelMatrix.column(3).toVector3D()); + barSelectionFound = true; + if (m_cachedSelectionMode >= QDataVis::ModeZoomRow) { + item.setTranslation(modelMatrix.column(3).toVector3D()); + m_sliceSelection->append(&item); + } + } + break; + } + case Bars3dController::SelectionRow: { + // Current bar is on the same row as the selected bar + barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightRowColor); + lightStrength = m_cachedTheme.m_highlightLightStrength; + if (!m_cachedIsSlicingActivated && QDataVis::ModeZoomRow == m_cachedSelectionMode) { + item.setTranslation(modelMatrix.column(3).toVector3D()); + m_sliceSelection->append(&item); + if (!m_sliceCache) { + // m_sliceCache is the axis for labels, while title comes from different axis. + m_sliceCache = &m_axisCacheZ; + if (m_axisCacheX.labelItems().size() > row) + m_sliceTitleItem = m_axisCacheX.labelItems().at(row); + } + } + break; + } + case Bars3dController::SelectionColumn: { + // Current bar is on the same column as the selected bar + barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightColumnColor); + lightStrength = m_cachedTheme.m_highlightLightStrength; + if (!m_cachedIsSlicingActivated + && QDataVis::ModeZoomColumn == m_cachedSelectionMode) { + item.setTranslation(modelMatrix.column(3).toVector3D()); + m_sliceSelection->append(&item); + if (!m_sliceCache) { + // m_sliceCache is the axis for labels, while title comes from different axis. + m_sliceCache = &m_axisCacheX; + if (m_axisCacheZ.labelItems().size() > bar) + m_sliceTitleItem = m_axisCacheZ.labelItems().at(bar); + } + } + break; + } + case Bars3dController::SelectionNone: { + // Current bar is not selected, nor on a row or column + // do nothing + break; + } + } + } + + // Skip drawing of 0 -height bars + if (item.height() != 0) { + // Set shader bindings + m_barShader->setUniformValue(m_barShader->lightP(), lightPos); + m_barShader->setUniformValue(m_barShader->view(), viewMatrix); + m_barShader->setUniformValue(m_barShader->model(), modelMatrix); + m_barShader->setUniformValue(m_barShader->nModel(), + itModelMatrix.transposed().inverted()); + m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + m_barShader->setUniformValue(m_barShader->color(), barColor); + m_barShader->setUniformValue(m_barShader->ambientS(), m_cachedTheme.m_ambientStrength); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); + m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); + m_barShader->setUniformValue(m_barShader->lightS(), lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_barShader, m_barObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_barShader->setUniformValue(m_barShader->lightS(), lightStrength); + + // Draw the object + m_drawer->drawObject(m_barShader, m_barObj); + } + } + } + } + + // Release bar shader + m_barShader->release(); + + // Bind background shader + m_backgroundShader->bind(); + + if (m_hasNegativeValues) + glDisable(GL_CULL_FACE); + else + glCullFace(GL_BACK); + + // Draw background + if (m_cachedIsBackgroundEnabled && m_backgroundObj) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); + modelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, + 1.0f, + m_columnDepth / m_scaleFactor)); + modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); + itModelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, + 1.0f, + m_columnDepth / m_scaleFactor)); + +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme.m_backgroundColor); + + // Set shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos); + m_backgroundShader->setUniformValue(m_backgroundShader->view(), viewMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->model(), modelMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->nModel(), + itModelMatrix.inverted().transposed()); + m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->color(), backgroundColor); + m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(), + m_cachedTheme.m_ambientStrength * 2.0f); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), + m_shadowQualityToShader); + m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_backgroundShader, m_backgroundObj); + } + } + + // Release background shader + m_backgroundShader->release(); + + // Disable textures + glDisable(GL_TEXTURE_2D); + + // Reset culling + if (m_hasNegativeValues) { + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + } + + // Draw grid lines + if (m_cachedIsGridEnabled && m_heightNormalizer) { + // Bind bar shader + m_barShader->bind(); + + // Set unchanging shader bindings + QVector3D barColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine); + m_barShader->setUniformValue(m_barShader->lightP(), lightPos); + m_barShader->setUniformValue(m_barShader->view(), viewMatrix); + m_barShader->setUniformValue(m_barShader->color(), barColor); + m_barShader->setUniformValue(m_barShader->ambientS(), m_cachedTheme.m_ambientStrength); + + // Floor lines: rows + for (GLfloat row = 0.0f; row <= m_cachedRowCount; row++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); + modelMatrix.translate(0.0f, -m_yAdjustment, + (m_columnDepth - rowPos) / m_scaleFactor + zComp); + modelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, + gridLineWidth)); + itModelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, + gridLineWidth)); + // If we're viewing from below, grid line object must be flipped + if (m_yFlipped) + modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + m_barShader->setUniformValue(m_barShader->model(), modelMatrix); + m_barShader->setUniformValue(m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); + m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); + m_barShader->setUniformValue(m_barShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_barShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_barShader->setUniformValue(m_barShader->lightS(), m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_barShader, m_gridLineObj); + } + } + + // Floor lines: columns + for (GLfloat bar = 0.0f; bar <= m_cachedColumnCount; bar++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + barPos = (bar + 0.5f) * (m_cachedBarSpacing.width()); + modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor, + -m_yAdjustment, zComp); + modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + m_columnDepth / m_scaleFactor)); + itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + m_columnDepth / m_scaleFactor)); + + // If we're viewing from below, grid line object must be flipped + if (m_yFlipped) + modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + m_barShader->setUniformValue(m_barShader->model(), modelMatrix); + m_barShader->setUniformValue(m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); + m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); + m_barShader->setUniformValue(m_barShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_barShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_barShader->setUniformValue(m_barShader->lightS(), m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_barShader, m_gridLineObj); + } + } + + if (m_axisCacheY.segmentCount() > 0) { + // Wall lines: back wall + GLfloat heightStep = m_axisCacheY.subSegmentStep(); + GLfloat startLine = 0.0f; + + if (m_hasNegativeValues) + startLine = -m_heightNormalizer; + + for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer; + lineHeight += heightStep) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + if (m_zFlipped) { + modelMatrix.translate(0.0f, + 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment, + m_columnDepth / m_scaleFactor + zComp); + } else { + modelMatrix.translate(0.0f, + 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment, + -m_columnDepth / m_scaleFactor + zComp); + } + modelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, + gridLineWidth)); + itModelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, + gridLineWidth)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + m_barShader->setUniformValue(m_barShader->model(), modelMatrix); + m_barShader->setUniformValue(m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); + m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); + m_barShader->setUniformValue(m_barShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_barShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_barShader->setUniformValue(m_barShader->lightS(), m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_barShader, m_gridLineObj); + } + } + + // Wall lines: side wall + for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer; + lineHeight += heightStep) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + if (m_xFlipped) { + modelMatrix.translate(m_rowWidth / m_scaleFactor, + 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment, + zComp); + } else { + modelMatrix.translate(-m_rowWidth / m_scaleFactor, + 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment, + zComp); + } + modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + m_columnDepth / m_scaleFactor)); + itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + m_columnDepth / m_scaleFactor)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + m_barShader->setUniformValue(m_barShader->model(), modelMatrix); + m_barShader->setUniformValue(m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); + m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); + m_barShader->setUniformValue(m_barShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_barShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_barShader->setUniformValue(m_barShader->lightS(), m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_barShader, m_gridLineObj); + } + } + } + // Release bar shader + m_barShader->release(); + } + + // Generate label textures for slice selection if m_updateLabels is set + if (m_cachedIsSlicingActivated && m_updateLabels) { + // Create label textures + for (int col = 0; col < m_sliceSelection->size(); col++) { + BarRenderItem *item = m_sliceSelection->at(col); + m_drawer->generateLabelTexture(item); + } + } + + // Handle slice activation and label drawing + if (!barSelectionFound) { + // We have no ownership, don't delete. Just NULL the pointer. + m_selectedBar = NULL; + if (m_cachedIsSlicingActivated + && Bars3dController::MouseOnOverview == m_controller->mouseState()) + m_controller->setSlicingActive(false); + } else if (m_cachedSelectionMode >= QDataVis::ModeZoomRow + && Bars3dController::MouseOnScene == m_controller->mouseState()) { + // Activate slice mode + m_controller->setSlicingActive(true); + + // Create label textures + for (int col = 0; col < m_sliceSelection->size(); col++) { + BarRenderItem *item = m_sliceSelection->at(col); + m_drawer->generateLabelTexture(item); + } + } else { + // Print value of selected bar + m_labelShader->bind(); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + if (m_cachedLabelTransparency > QDataVis::TransparencyNone) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } +#ifndef DISPLAY_FULL_DATA_ON_SELECTION + // Draw just the value string of the selected bar + if (m_previouslySelectedBar != m_selectedBar || m_updateLabels) { + m_drawer->generateLabelTexture(m_selectedBar); + m_previouslySelectedBar = m_selectedBar; + } + + m_drawer->drawLabel(*m_selectedBar, m_selectedBar->labelItem(), + viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), + m_cachedSelectionMode, m_labelShader, + m_labelObj, true); +#else + // Draw the value string followed by row label and column label + LabelItem &labelItem = m_selectedBar->selectionLabel(); + if (m_previouslySelectedBar != m_selectedBar || m_updateLabels || !labelItem.textureId()) { + QString labelText = m_selectedBar->label(); + if ((m_axisCacheZ.labels().size() > m_selectedBar->position().y()) + && (m_axisCacheX.labels().size() > m_selectedBar->position().x())) { + labelText.append(QStringLiteral(" (")); + labelText.append(m_axisCacheX.labels().at(m_selectedBar->position().x())); + labelText.append(QStringLiteral(", ")); + labelText.append(m_axisCacheZ.labels().at(m_selectedBar->position().y())); + labelText.append(QStringLiteral(")")); + //qDebug() << labelText; + } + m_drawer->generateLabelItem(labelItem, labelText); + m_previouslySelectedBar = m_selectedBar; + } + + m_drawer->drawLabel(*m_selectedBar, labelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), + m_cachedSelectionMode, m_labelShader, + m_labelObj, camera, true, false); +#endif + glDisable(GL_TEXTURE_2D); + if (m_cachedLabelTransparency > QDataVis::TransparencyNone) + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + + // Release label shader + m_labelShader->release(); + + // Reset label update flag; they should have been updated when we get here + m_updateLabels = false; + } + + // TODO: Calculations done temporarily here. When optimizing, move to after data set addition? Keep drawing of the labels here. + // Bind label shader + m_labelShader->bind(); + + glEnable(GL_TEXTURE_2D); + if (m_cachedLabelTransparency > QDataVis::TransparencyNone) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + // Calculate the positions for row and column labels and store them + for (int row = 0; row != m_cachedRowCount; row++) { + if (m_axisCacheX.labelItems().size() > row) { + // Go through all rows and get position of max+1 or min-1 column, depending on x flip + // We need only positions for them, labels have already been generated at QDataSetPrivate. Just add LabelItems + rowPos = (row + 1) * (m_cachedBarSpacing.height()); + barPos = m_rowWidth; + GLfloat rotLabelX = -90.0f; + GLfloat rotLabelY = 0.0f; + GLfloat rotLabelZ = 0.0f; + Qt::AlignmentFlag alignment = Qt::AlignRight; + if (m_zFlipped) + rotLabelY = 180.0f; + if (m_xFlipped) { + barPos = -m_rowWidth; + alignment = Qt::AlignLeft; + } + if (m_yFlipped) { + if (m_zFlipped) + rotLabelY = 0.0f; + else + rotLabelY = 180.0f; + rotLabelZ = 180.0f; + } + QVector3D labelPos = QVector3D(barPos / m_scaleFactor, + -m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" + (m_columnDepth - rowPos) / m_scaleFactor + zComp); + + m_dummyBarRenderItem.setTranslation(labelPos); + const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(row); + //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << m_axisCacheX.labels().at(row); + + m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(rotLabelX, rotLabelY, rotLabelZ), + 0, m_cachedSelectionMode, + m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + alignment); + } + + } + for (int bar = 0; bar != m_cachedColumnCount; bar += 1) { + if (m_axisCacheZ.labelItems().size() > bar) { + // Go through all columns and get position of max+1 or min-1 row, depending on z flip + // We need only positions for them, labels have already been generated at QDataSetPrivate. Just add LabelItems + barPos = (bar + 1) * (m_cachedBarSpacing.width()); + rowPos = m_columnDepth; + GLfloat rotLabelX = -90.0f; + GLfloat rotLabelY = 90.0f; + GLfloat rotLabelZ = 0.0f; + Qt::AlignmentFlag alignment = Qt::AlignLeft; + if (m_xFlipped) + rotLabelY = -90.0f; + if (m_zFlipped) { + rowPos = -m_columnDepth; + alignment = Qt::AlignRight; + } + if (m_yFlipped) { + if (m_xFlipped) + rotLabelY = -90.0f; + else + rotLabelY = 90.0f; + rotLabelZ = 180.0f; + } + QVector3D labelPos = QVector3D((m_rowWidth - barPos) / m_scaleFactor, + -m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" + rowPos / m_scaleFactor + zComp); + + // TODO: Try it; draw the label here + + m_dummyBarRenderItem.setTranslation(labelPos); + const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(bar); + //qDebug() << "labelPos, col" << bar + 1 << ":" << labelPos << m_axisCacheZ.labels().at(bar); + + m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(rotLabelX, rotLabelY, rotLabelZ), + 0, m_cachedSelectionMode, + m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + alignment); + } + } + + // Y Labels + int labelNbr = 0; + GLfloat heightStep = m_axisCacheY.segmentStep(); + GLfloat startLine = 0.0f; + int labelCount = m_axisCacheY.labels().size(); + if (m_hasNegativeValues) + startLine = -m_heightNormalizer; + GLfloat labelPos = startLine; + + for (int i = 0; i < labelCount; i++) { + if (m_axisCacheY.labelItems().size() > labelNbr) { + GLfloat labelXTrans = m_rowWidth / m_scaleFactor; + GLfloat labelZTrans = m_columnDepth / m_scaleFactor; + GLfloat labelYTrans = 2.0f * labelPos / m_heightNormalizer - m_yAdjustment; + GLfloat rotLabelX = 0.0f; + GLfloat rotLabelY = -90.0f; + GLfloat rotLabelZ = 0.0f; + Qt::AlignmentFlag alignment = Qt::AlignLeft; + if (!m_xFlipped) { + labelXTrans = -labelXTrans; + rotLabelY = 90.0f; + } + if (m_zFlipped) { + labelZTrans = -labelZTrans; + alignment = Qt::AlignRight; + } + + const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr); + + // Back wall + QVector3D labelTrans = QVector3D(labelXTrans, labelYTrans, labelZTrans + zComp); + + //qDebug() << "labelPos, value:" << labelTrans; + + m_dummyBarRenderItem.setTranslation(labelTrans); + m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(rotLabelX, rotLabelY, rotLabelZ), + 0, m_cachedSelectionMode, + m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + alignment); + + // Side wall + if (m_xFlipped) + alignment = Qt::AlignLeft; + else + alignment = Qt::AlignRight; + if (m_zFlipped) + rotLabelY = 180.0f; + else + rotLabelY = 0.0f; + + labelTrans = QVector3D(-labelXTrans, labelYTrans, -labelZTrans + zComp); + + m_dummyBarRenderItem.setTranslation(labelTrans); + m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(rotLabelX, rotLabelY, rotLabelZ), + 0, m_cachedSelectionMode, + m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + alignment); + } + labelNbr++; + labelPos += heightStep; + } + + glDisable(GL_TEXTURE_2D); + if (m_cachedLabelTransparency > QDataVis::TransparencyNone) + glDisable(GL_BLEND); + + // Release label shader + m_labelShader->release(); +} + +void Bars3dRenderer::requestSelectionAtPoint(const QPoint &point) +{ + QMutexLocker locker(&m_mutex); + m_selectionPointRequest.setX(point.x()); + m_selectionPointRequest.setY(point.y()); + m_isSelectionPointRequestActive = true; +} + +void Bars3dRenderer::handleResize() +{ + if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) + return; + + // Set view port + if (m_cachedIsSlicingActivated) { + m_mainViewPort = QRect(0, + m_cachedBoundingRect.height() - m_cachedBoundingRect.height() / 5, + m_cachedBoundingRect.width() / 5, + m_cachedBoundingRect.height() / 5); + } else { + m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); + } + m_sliceViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); + + Abstract3DRenderer::handleResize(); +} + +void Bars3dRenderer::updateBarSpecs(QSizeF thickness, QSizeF spacing, bool relative) +{ + m_cachedBarThickness = thickness; + if (relative) { + m_cachedBarSpacing.setWidth((thickness.width() * 2) * (spacing.width() + 1.0f)); + m_cachedBarSpacing.setHeight((thickness.height() * 2) * (spacing.height() + 1.0f)); + } else { + m_cachedBarSpacing = thickness * 2 + spacing * 2; + } + + // Calculate here and at setting sample space + calculateSceneScalingFactors(); +} + +void Bars3dRenderer::updateMeshFileName(const QString &objFileName) +{ + Abstract3DRenderer::updateMeshFileName(objFileName); + loadBarMesh(); +} + +void Bars3dRenderer::updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max) +{ + Abstract3DRenderer::updateAxisRange(orientation, min, max); + calculateHeightAdjustment(); + + // Check if we have negative values + if (min < 0 && !m_hasNegativeValues) { + m_hasNegativeValues = true; + // Reload background + loadBackgroundMesh(); + } else if (min >= 0 && m_hasNegativeValues) { + m_hasNegativeValues = false; + // Reload background + loadBackgroundMesh(); + } + + // TODO Currently barchart only supports zero centered or zero minimum ranges + if (min > 0.0 || (min != 0.0 && (qFabs(min) != qFabs(max)))) + qWarning() << __FUNCTION__ << "Bar chart currently properly supports only zero-centered and zero minimum ranges for Y-axis."; +} + +void Bars3dRenderer::updateSampleSpace(int rowCount, int columnCount) +{ + // Destroy old render items and reallocate new array + // TODO is there a way to allocate the whole array with one allocation? + m_renderItemArray.clear(); + m_renderItemArray.resize(rowCount); + for (int i = 0; i < rowCount; i++) { + m_renderItemArray[i].resize(columnCount); + for (int j = 0; j < columnCount; j++) + m_renderItemArray[i][j].setRenderer(this); + } + + // Force update for selection related items + m_sliceCache = 0; + m_sliceTitleItem = 0; + if (m_sliceSelection) + m_sliceSelection->clear(); + + m_cachedColumnCount = columnCount; + m_cachedRowCount = rowCount; + // TODO: Invent "idiotproof" max scene size formula.. + // This seems to work ok if spacing is not negative (and row/column or column/row ratio is not too high) + m_maxSceneSize = 2 * qSqrt(columnCount * rowCount); + //qDebug() << "maxSceneSize" << m_maxSceneSize; + // Calculate here and at setting bar specs + calculateSceneScalingFactors(); +} + +void Bars3dRenderer::updateSelectionMode(QDataVis::SelectionMode mode) +{ + Abstract3DRenderer::updateSelectionMode(mode); + + // Create zoom selection if there isn't one + if (mode >= QDataVis::ModeZoomRow && !m_sliceSelection) { + m_sliceSelection = new QList<BarRenderItem *>; + if (mode == QDataVis::ModeZoomRow) + m_sliceSelection->reserve(m_cachedRowCount); + else + m_sliceSelection->reserve(m_cachedColumnCount); + } +} + +void Bars3dRenderer::updateBackgroundEnabled(bool enable) +{ + if (enable != m_cachedIsBackgroundEnabled) { + Abstract3DRenderer::updateBackgroundEnabled(enable); + loadBarMesh(); // Load changed bar type + } +} + +void Bars3dRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) +{ + qDebug() << "Bars3dRenderer::setShadowQuality" << quality; + m_cachedShadowQuality = quality; + switch (quality) { + case QDataVis::ShadowLow: + m_shadowQualityToShader = 33.3f; + break; + case QDataVis::ShadowMedium: + m_shadowQualityToShader = 100.0f; + break; + case QDataVis::ShadowHigh: + m_shadowQualityToShader = 200.0f; + break; + default: + m_shadowQualityToShader = 0.0f; + break; + } +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Re-init shaders + if (!m_cachedTheme.m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } else { + // Re-init shaders + if (!m_cachedTheme.m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + // Re-init depth buffer + updateDepthBuffer(); +#else + if (!m_cachedTheme.m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentColorOnYES2")); + } else { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); +#endif +} + +void Bars3dRenderer::loadBarMesh() +{ + QString objectFileName = m_cachedObjFile; + if (m_barObj) + delete m_barObj; + // If background is disabled, load full version of bar mesh + if (!m_cachedIsBackgroundEnabled) + objectFileName.append(QStringLiteral("Full")); + m_barObj = new ObjectHelper(objectFileName); + m_barObj->load(); +} + +void Bars3dRenderer::loadBackgroundMesh() +{ + if (m_backgroundObj) + delete m_backgroundObj; + if (m_hasNegativeValues) + m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/negativeBackground")); + else + m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background")); + m_backgroundObj->load(); +} + +void Bars3dRenderer::loadGridLineMesh() +{ + if (m_gridLineObj) + delete m_gridLineObj; + m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar")); + m_gridLineObj->load(); +} + +void Bars3dRenderer::loadLabelMesh() +{ + if (m_labelObj) + delete m_labelObj; + m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); + m_labelObj->load(); +} + +void Bars3dRenderer::updateTextures() +{ + // Drawer has changed; this flag needs to be checked when checking if we need to update labels + m_updateLabels = true; +} + +void Bars3dRenderer::calculateSceneScalingFactors() +{ + // Calculate scene scaling and translation factors + m_rowWidth = ((m_cachedColumnCount + 1) * m_cachedBarSpacing.width()) / 2.0f; + m_columnDepth = ((m_cachedRowCount + 1) * m_cachedBarSpacing.height()) / 2.0f; + m_maxDimension = qMax(m_rowWidth, m_columnDepth); + m_scaleFactor = qMin((m_cachedColumnCount * (m_maxDimension / m_maxSceneSize)), + (m_cachedRowCount * (m_maxDimension / m_maxSceneSize))); + m_scaleX = m_cachedBarThickness.width() / m_scaleFactor; + m_scaleZ = m_cachedBarThickness.height() / m_scaleFactor; + //qDebug() << "m_scaleX" << m_scaleX << "m_scaleFactor" << m_scaleFactor; + //qDebug() << "m_scaleZ" << m_scaleZ << "m_scaleFactor" << m_scaleFactor; + //qDebug() << "m_rowWidth:" << m_rowWidth << "m_columnDepth:" << m_columnDepth << "m_maxDimension:" << m_maxDimension; +} + +void Bars3dRenderer::calculateHeightAdjustment() +{ + m_heightNormalizer = (GLfloat)qMax(qFabs(m_axisCacheY.min()), qFabs(m_axisCacheY.max())); + + // 2.0f = max difference between minimum and maximum value after scaling with m_heightNormalizer + GLfloat newAdjustment = 2.0f - ((m_heightNormalizer - m_axisCacheY.min()) / m_heightNormalizer); + if (newAdjustment != m_yAdjustment) { + m_hasHeightAdjustmentChanged = true; + m_yAdjustment = newAdjustment; + } + //qDebug() << m_yAdjustment; +} + +Bars3dController::SelectionType Bars3dRenderer::isSelected(GLint row, GLint bar) +{ + //static QVector3D prevSel = m_selection; // TODO: For debugging + Bars3dController::SelectionType isSelectedType = Bars3dController::SelectionNone; + if (m_selection == selectionSkipColor) + return isSelectedType; // skip window + + //#if !defined(QT_OPENGL_ES_2) + // QVector3D current = QVector3D((GLuint)row, (GLuint)bar, 0); + //#else + QVector3D current = QVector3D((GLubyte)row, (GLubyte)bar, 0); + //#endif + + // TODO: For debugging + //if (selection != prevSel) { + // qDebug() << "current" << current.x() << current .y() << current.z(); + // qDebug() << "selection" << selection.x() << selection .y() << selection.z(); + // prevSel = selection; + //} + if (current == m_selection) { + isSelectedType = Bars3dController::SelectionItem; + } + else if (current.y() == m_selection.y() && (m_cachedSelectionMode == QDataVis::ModeItemAndColumn + || m_cachedSelectionMode == QDataVis::ModeItemRowAndColumn + || m_cachedSelectionMode == QDataVis::ModeZoomColumn)) { + isSelectedType = Bars3dController::SelectionColumn; + } + else if (current.x() == m_selection.x() && (m_cachedSelectionMode == QDataVis::ModeItemAndRow + || m_cachedSelectionMode == QDataVis::ModeItemRowAndColumn + || m_cachedSelectionMode == QDataVis::ModeZoomRow)) { + isSelectedType = Bars3dController::SelectionRow; + } + return isSelectedType; +} + +void Bars3dRenderer::updateSlicingActive(bool isSlicing) +{ + m_cachedIsSlicingActivated = isSlicing; + if (isSlicing) { + m_mainViewPort = QRect(0, m_cachedBoundingRect.height() - m_cachedBoundingRect.height() / 5, + m_cachedBoundingRect.width() / 5, m_cachedBoundingRect.height() / 5); + } else { + m_mainViewPort = QRect(0, 0, this->m_cachedBoundingRect.width(), + this->m_cachedBoundingRect.height()); + } +} + +QRect Bars3dRenderer::mainViewPort() +{ + return m_mainViewPort; +} + +void Bars3dRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader) +{ + if (m_barShader) + delete m_barShader; + m_barShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_barShader->initialize(); +} + +void Bars3dRenderer::initSelectionShader() +{ + if (m_selectionShader) + delete m_selectionShader; + m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSelection"), + QStringLiteral(":/shaders/fragmentSelection")); + m_selectionShader->initialize(); +} + +void Bars3dRenderer::initSelectionBuffer() +{ + if (m_selectionTexture) + m_textureHelper->deleteTexture(&m_selectionTexture); + + m_selectionTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(), + m_selectionFrameBuffer, + m_selectionDepthBuffer); +} + +#if !defined(QT_OPENGL_ES_2) +void Bars3dRenderer::initDepthShader() +{ + if (m_depthShader) + delete m_depthShader; + m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"), + QStringLiteral(":/shaders/fragmentDepth")); + m_depthShader->initialize(); +} + +void Bars3dRenderer::updateDepthBuffer() +{ + if (m_depthTexture) { + m_textureHelper->deleteTexture(&m_depthTexture); + m_depthTexture = 0; + } + + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(), + m_depthFrameBuffer, + m_cachedShadowQuality); + if (!m_depthTexture) { + switch (m_cachedShadowQuality) { + case QDataVis::ShadowHigh: + qWarning("Creating high quality shadows failed. Changing to medium quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowMedium); + break; + case QDataVis::ShadowMedium: + qWarning("Creating medium quality shadows failed. Changing to low quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowLow); + break; + case QDataVis::ShadowLow: + qWarning("Creating low quality shadows failed. Switching shadows off."); + (void)m_controller->setShadowQuality(QDataVis::ShadowNone); + break; + default: + // You'll never get here + break; + } + } + } +} +#endif + +void Bars3dRenderer::initBackgroundShaders(const QString &vertexShader, + const QString &fragmentShader) +{ + if (m_backgroundShader) + delete m_backgroundShader; + m_backgroundShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_backgroundShader->initialize(); +} + +void Bars3dRenderer::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) +{ + if (m_labelShader) + delete m_labelShader; + m_labelShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_labelShader->initialize(); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/bars3drenderer_p.h b/src/datavis3d/engine/bars3drenderer_p.h new file mode 100644 index 00000000..93d47cf1 --- /dev/null +++ b/src/datavis3d/engine/bars3drenderer_p.h @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 Q3DBARSRENDERER_p_H +#define Q3DBARSRENDERER_p_H + +#include <QtCore/QSize> +#include <QtCore/QObject> +#include <QtGui/QOpenGLFunctions> +#include <QtGui/QFont> +#include <QTime> +#include <QWindow> +#include <QMutex> + +#include "datavis3dglobal_p.h" +#include "bars3dcontroller_p.h" +#include "abstract3drenderer_p.h" +#include "qbardataproxy.h" +#include "barrenderitem_p.h" + +//#define DISPLAY_RENDER_SPEED + +class QPoint; +class QSizeF; +class QOpenGLShaderProgram; + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class ShaderHelper; +class ObjectHelper; +class TextureHelper; +class Theme; +class Drawer; +class LabelItem; +class CameraHelper; + +class QT_DATAVIS3D_EXPORT Bars3dRenderer : public Abstract3DRenderer +{ + Q_OBJECT + +private: + // TODO: Filter to the set of attributes to be moved to the model object. + Bars3dController *m_controller; + + // Mutex for sharing resources between render and main threads. + // TODO this mutex needs to go, too... + QMutex m_mutex; + + // Cached state based on emitted signals from the controller + QSizeF m_cachedBarThickness; + QSizeF m_cachedBarSpacing; + bool m_cachedIsSlicingActivated; + int m_cachedRowCount; + int m_cachedColumnCount; + + // Internal state + BarRenderItem *m_selectedBar; // points to renderitem array + BarRenderItem *m_previouslySelectedBar; // points to renderitem array + QList<BarRenderItem *> *m_sliceSelection; + AxisRenderCache *m_sliceCache; // not owned + const LabelItem *m_sliceTitleItem; // not owned + bool m_xFlipped; + bool m_zFlipped; + bool m_yFlipped; + QRect m_mainViewPort; + QRect m_sliceViewPort; + bool m_updateLabels; + ShaderHelper *m_barShader; + ShaderHelper *m_depthShader; + ShaderHelper *m_selectionShader; + ShaderHelper *m_backgroundShader; + ShaderHelper *m_labelShader; + ObjectHelper *m_barObj; + ObjectHelper *m_backgroundObj; + ObjectHelper *m_gridLineObj; + ObjectHelper *m_labelObj; + TextureHelper *m_textureHelper; + GLuint m_bgrTexture; + GLuint m_depthTexture; + GLuint m_selectionTexture; + GLuint m_depthFrameBuffer; + GLuint m_selectionFrameBuffer; + GLuint m_selectionDepthBuffer; + GLfloat m_shadowQualityToShader; + GLfloat m_heightNormalizer; + GLfloat m_yAdjustment; + GLfloat m_rowWidth; + GLfloat m_columnDepth; + GLfloat m_maxDimension; + GLfloat m_scaleX; + GLfloat m_scaleZ; + GLfloat m_scaleFactor; + GLfloat m_maxSceneSize; + QVector3D m_selection; + + QPoint m_selectionPointRequest; + bool m_isSelectionPointRequestActive; + + bool m_hasHeightAdjustmentChanged; + BarRenderItem m_dummyBarRenderItem; + + BarRenderItemArray m_renderItemArray; + +#ifdef DISPLAY_RENDER_SPEED + bool m_isFirstFrame; + QTime m_lastFrameTime; + GLint m_numFrames; +#endif + +public: + explicit Bars3dRenderer(Bars3dController *controller); + ~Bars3dRenderer(); + + void updateDataModel(QBarDataProxy *dataProxy); + void render(CameraHelper *camera, const GLuint defaultFboHandle = 0); + + QRect mainViewPort(); + +public slots: + void updateBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f), + QSizeF spacing = QSizeF(1.0f, 1.0f), + bool relative = true); + void updateSelectionMode(QDataVis::SelectionMode newMode); + void updateSlicingActive(bool isSlicing); + void updateSampleSpace(int rowCount, int columnCount); + void updateBackgroundEnabled(bool enable); + void updateMeshFileName(const QString &objFileName); + + // Overloaded from abstract renderer + virtual void updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); + + // Requests that upon next render pass the column and row under the given point is inspected for selection. + // Only one request can be queued per render pass at this point. New request will override any pending requests. + // After inspection the selectionUpdated signal is emitted. + virtual void requestSelectionAtPoint(const QPoint &point); + +signals: + void selectionUpdated(QVector3D selection); + +private: + virtual void initializeOpenGL(); + virtual void initShaders(const QString &vertexShader, const QString &fragmentShader); + virtual void updateShadowQuality(QDataVis::ShadowQuality quality); + virtual void updateTextures(); + + void drawSlicedScene(CameraHelper *camera, + const LabelItem &xLabel, const LabelItem &yLabel, const LabelItem &zLabel); + void drawScene(CameraHelper *camera, const GLuint defaultFboHandle); + void handleResize(); + + void loadBarMesh(); + void loadBackgroundMesh(); + void loadGridLineMesh(); + void loadLabelMesh(); + void initSelectionShader(); + void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); + void initLabelShaders(const QString &vertexShader, const QString &fragmentShader); + void initSelectionBuffer(); +#if !defined(QT_OPENGL_ES_2) + void initDepthShader(); + void updateDepthBuffer(); +#endif + void calculateSceneScalingFactors(); + void calculateHeightAdjustment(); + Abstract3DController::SelectionType isSelected(GLint row, GLint bar); + + Q_DISABLE_COPY(Bars3dRenderer) + + friend class BarRenderItem; +}; + + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/bars3dshared.cpp b/src/datavis3d/engine/bars3dshared.cpp deleted file mode 100644 index 55efb7cc..00000000 --- a/src/datavis3d/engine/bars3dshared.cpp +++ /dev/null @@ -1,2421 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "bars3dshared_p.h" -#include "camerahelper_p.h" -#include "qdataitem_p.h" -#include "qdatarow_p.h" -#include "qdataset_p.h" -#include "shaderhelper_p.h" -#include "objecthelper_p.h" -#include "texturehelper_p.h" -#include "theme_p.h" -#include "utils_p.h" -#include "drawer_p.h" - -#include <QMatrix4x4> -#include <QOpenGLPaintDevice> -#include <QPainter> -#include <QScreen> -#include <QMouseEvent> - -#include <qmath.h> - -#include <QDebug> - -// Uncommenting this draws the shadow map with wider FOV than scene itself, making the light -// seem to be closer to scene than it actually is. This way shadows look slightly better (to me anyway) -#define USE_WIDER_SHADOWS - -// You can verify that depth buffer drawing works correctly by uncommenting this. -// You should see the scene from where the light is -//#define SHOW_DEPTH_TEXTURE_SCENE - -//#define DISPLAY_RENDER_SPEED - -#ifdef DISPLAY_RENDER_SPEED -#include <QTime> -#endif - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -//#define USE_HAX0R_SELECTION // keep this defined until the "real" method works -#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels - -const GLfloat gridLineWidth = 0.005f; -static QVector3D skipColor = QVector3D(255, 255, 255); // Selection texture's background color - -Bars3dShared::Bars3dShared(QRect rect, GLuint fbohandle) - : m_boundingRect(rect.x(), rect.y(), rect.width(), rect.height()), - m_paintDevice(0), - m_barShader(0), - m_depthShader(0), - m_selectionShader(0), - m_backgroundShader(0), - m_labelShader(0), - m_barObj(0), - m_backgroundObj(0), - m_gridLineObj(0), - m_labelObj(0), - m_sampleCount(0, 0), - m_objFile(QStringLiteral(":/defaultMeshes/bar")), - m_mousePressed(MouseNone), - m_mousePos(QPoint(0, 0)), - m_zoomLevel(100), - m_zoomAdjustment(1.0f), - m_horizontalRotation(-45.0f), - m_verticalRotation(15.0f), - m_barThickness(QSizeF(0.75f, 0.75f)), - m_barSpacing(m_barThickness * 3.0f), - m_heightNormalizer(0.0f), - m_yAdjustment(0.0f), - m_rowWidth(0), - m_columnDepth(0), - m_maxDimension(0), - m_scaleX(0), - m_scaleZ(0), - m_scaleFactor(0), - m_maxSceneSize(40.0), - m_theme(new Theme()), - m_isInitialized(false), - m_selectionMode(ModeBar), - m_selectedBar(0), - m_zoomSelection(0), - m_dataSet(new QDataSet()), - m_axisLabelX(QStringLiteral("X")), - m_axisLabelZ(QStringLiteral("Z")), - m_axisLabelY(QStringLiteral("Y")), - m_sceneViewPort(rect.x(), rect.y(), rect.width(), rect.height()), - m_zoomViewPort(rect.x(), rect.y(), rect.width(), rect.height()), - m_zoomActivated(false), - m_labelTransparency(TransparencyFromTheme), - m_font(QFont(QStringLiteral("Arial"))), - m_drawer(new Drawer(*m_theme, m_font, m_labelTransparency)), - m_xFlipped(false), - m_zFlipped(false), - m_yFlipped(false), - m_bgrTexture(0), - m_depthTexture(0), - m_selectionTexture(0), - m_depthFrameBuffer(0), - m_selectionFrameBuffer(0), - m_selectionDepthBuffer(0), - m_updateLabels(false), - m_gridEnabled(true), - m_bgrEnabled(true), - m_shadowQuality(ShadowLow), - m_shadowQualityToShader(33.3f), - m_tickCount(0), - m_tickStep(0), - m_negativeValues(false), - m_fbohandle(fbohandle) -{ - m_theme = new Theme(); - m_dataSet->d_ptr->setDrawer(m_drawer); - QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Bars3dShared::updateTextures); -} - -Bars3dShared::~Bars3dShared() -{ -#ifndef USE_HAX0R_SELECTION - glDeleteFramebuffers(1, &m_selectionFrameBuffer); - glDeleteRenderbuffers(1, &m_selectionDepthBuffer); - m_textureHelper->deleteTexture(&m_selectionTexture); -#endif - glDeleteFramebuffers(1, &m_depthFrameBuffer); - m_textureHelper->deleteTexture(&m_bgrTexture); - delete m_dataSet; - if (m_zoomSelection) { - m_zoomSelection->d_ptr->clear(); - delete m_zoomSelection; - } - delete m_barShader; - delete m_depthShader; - delete m_selectionShader; - delete m_backgroundShader; - delete m_barObj; - delete m_backgroundObj; - delete m_gridLineObj; - delete m_textureHelper; - delete m_drawer; -} - - -void Bars3dShared::render() -{ - if (!m_isInitialized) - return; - -#ifdef DISPLAY_RENDER_SPEED - // For speed computation - static bool firstRender = true; - static QTime lastTime; - static GLint nbFrames = 0; - if (firstRender) { - lastTime.start(); - firstRender = false; - } - - // Measure speed (as milliseconds per frame) - nbFrames++; - if (lastTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago - qDebug() << qreal(lastTime.elapsed()) / qreal(nbFrames) << "ms/frame (=" << qreal(nbFrames) << "fps)"; - nbFrames = 0; - lastTime.restart(); - } -#endif - - // If zoom selection is on, draw zoom scene - drawZoomScene(); - // Draw bars scene - drawScene(); -} - -void Bars3dShared::initializeOpenGL() -{ - // Initialization is called multiple times when Qt Quick components are used - if (m_isInitialized) - return; - - initializeOpenGLFunctions(); - - m_textureHelper = new TextureHelper(); - m_drawer->initializeOpenGL(); - - // Resize in case we've missed resize events - resizeNotify(); - - // Initialize shaders -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > ShadowNone) { - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - // Init the depth buffer (for shadows) - initDepthBuffer(); - } else { - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } -#else - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); -#endif - - initLabelShaders(QStringLiteral(":/shaders/vertexLabel"), - QStringLiteral(":/shaders/fragmentLabel")); - -#if !defined(QT_OPENGL_ES_2) - // Init depth shader (for shadows). Init in any case, easier to handle shadow activation if done via api. - initDepthShader(); -#endif - - // Init selection shader - initSelectionShader(); - -#ifndef USE_HAX0R_SELECTION - // Init the selection buffer - initSelectionBuffer(); -#endif - - // Load default mesh - loadBarMesh(); - - // Load background mesh - loadBackgroundMesh(); - - // Load grid line mesh - loadGridLineMesh(); - - // Load label mesh - loadLabelMesh(); - - // Set OpenGL features - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - -#if !defined(QT_OPENGL_ES_2) - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); -#endif - - // Set initial camera position - // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later - CameraHelper::setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - - // Set view port - glViewport(0, 0, width(), height()); - - // Set initialized -flag - m_isInitialized = true; - - // Load background mesh - loadBackgroundMesh(); -} - -void Bars3dShared::drawZoomScene() -{ - // Set clear color - QVector3D clearColor = Utils::vectorFromColor(m_theme->m_windowColor); - glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // If no zoom, return - if (!m_zoomActivated) - return; - - GLfloat barPosX = 0; - GLint startBar = 0; - GLint stopBar = m_zoomSelection->d_ptr->row().size(); - GLint stepBar = 1; - QVector3D lightPos; - - // Specify viewport - glViewport(m_zoomViewPort.x(), m_zoomViewPort.y(), - m_zoomViewPort.width(), m_zoomViewPort.height()); - - // Set up projection matrix - QMatrix4x4 projectionMatrix; - projectionMatrix.perspective(45.0f, (GLfloat)m_zoomViewPort.width() - / (GLfloat)m_zoomViewPort.height(), 0.1f, 100.0f); - -#ifdef ROTATE_ZOOM_SELECTION - // Calculate view matrix - QMatrix4x4 viewMatrix = CameraHelper::calculateViewMatrix(m_mousePos, - m_zoomLevel - * m_zoomAdjustment, - m_zoomViewPort.width(), - m_zoomViewPort.height()); - - // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) - lightPos = CameraHelper::calculateLightPosition(defaultLightPos); - - if (viewMatrix.row(0).z() <= 0) { - startBar = m_zoomSelection->d_ptr->row().size() - 1; - stopBar = -1; - stepBar = -1; - } -#else - // Set view matrix - QMatrix4x4 viewMatrix; - - // Adjust scaling (zoom rate based on aspect ratio) - GLfloat camPosZoomed = 5.0f / m_zoomAdjustment + zComp; - - viewMatrix.lookAt(QVector3D(0.0f, 0.0f, camPosZoomed), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - - // Set light position a bit below the camera to reduce glare (depends on do we have row or column zoom) - QVector3D zoomLightPos = defaultLightPos; - zoomLightPos.setY(-10.0f); - if (ModeZoomColumn == m_selectionMode) - lightPos = CameraHelper::calculateLightPosition(zoomLightPos, -85.0f); - else - lightPos = CameraHelper::calculateLightPosition(zoomLightPos, 5.0f); -#endif - - // Bind bar shader - m_barShader->bind(); - - // Draw bars - // Draw the selected row / column - for (int bar = startBar; bar != stopBar; bar += stepBar) { - QDataItem *item = m_zoomSelection->d_ptr->getItem(bar); - if (!item) - continue; - - GLfloat barHeight = item->d_ptr->value() / m_heightNormalizer; - - if (barHeight < 0) - glCullFace(GL_FRONT); - else - glCullFace(GL_BACK); - - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 itModelMatrix; - - GLfloat barPosY = item->d_ptr->translation().y() - m_yAdjustment / 2.0f + 0.2f; // we need some room for labels underneath; add +0.2f - if (ModeZoomRow == m_selectionMode) - barPosX = item->d_ptr->translation().x(); - else - barPosX = -(item->d_ptr->translation().z() - zComp); // flip z; frontmost bar to the left - modelMatrix.translate(barPosX, barPosY, zComp); - modelMatrix.scale(QVector3D(m_scaleX, barHeight, m_scaleZ)); - itModelMatrix.scale(QVector3D(m_scaleX, barHeight, m_scaleZ)); - - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - - QVector3D baseColor = Utils::vectorFromColor(m_theme->m_baseColor); - QVector3D heightColor = Utils::vectorFromColor(m_theme->m_heightColor) * barHeight; - - QVector3D barColor = baseColor + heightColor; - - GLfloat lightStrength = m_theme->m_lightStrength; - - if (barHeight != 0) { - // Set shader bindings - m_barShader->setUniformValue(m_barShader->lightP(), lightPos); - m_barShader->setUniformValue(m_barShader->view(), viewMatrix); - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); - m_barShader->setUniformValue(m_barShader->color(), barColor); - m_barShader->setUniformValue(m_barShader->lightS(), lightStrength); - m_barShader->setUniformValue(m_barShader->ambientS(), - m_theme->m_ambientStrength); - - // Draw the object - m_drawer->drawObject(m_barShader, m_barObj); - } - } - - // Release bar shader - m_barShader->release(); - - // Draw labels - m_labelShader->bind(); - glDisable(GL_DEPTH_TEST); - glEnable(GL_TEXTURE_2D); - glCullFace(GL_BACK); - if (m_labelTransparency > TransparencyNone) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - // Draw labels for axes - QDataItem *dummyItem = NULL; - LabelItem x; - LabelItem z; - LabelItem y; - m_dataSet->d_ptr->axisLabelItems(&x, &z, &y); - LabelItem zoomSelectionLabel = m_zoomSelection->d_ptr->labelItem(); - if (ModeZoomRow == m_selectionMode) { - m_drawer->drawLabel(*dummyItem, zoomSelectionLabel, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer, - m_selectionMode, m_labelShader, - m_labelObj, false, false, LabelTop); - m_drawer->drawLabel(*dummyItem, z, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer, - m_selectionMode, m_labelShader, - m_labelObj, false, false, LabelBottom); - } else { - m_drawer->drawLabel(*dummyItem, x, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer, - m_selectionMode, m_labelShader, - m_labelObj, false, false, LabelBottom); - m_drawer->drawLabel(*dummyItem, zoomSelectionLabel, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer, - m_selectionMode, m_labelShader, - m_labelObj, false, false, LabelTop); - } - m_drawer->drawLabel(*dummyItem, y, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 90.0f), m_heightNormalizer, - m_selectionMode, m_labelShader, - m_labelObj, false, false, LabelLeft); - - // Draw labels for bars - for (int col = 0; col < m_zoomSelection->d_ptr->row().size(); col++) { - QDataItem *item = m_zoomSelection->d_ptr->getItem(col); - // Draw values - m_drawer->drawLabel(*item, item->d_ptr->label(), viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer, - m_selectionMode, m_labelShader, - m_labelObj); - // Draw labels - LabelItem labelItem; - if (ModeZoomRow == m_selectionMode) { - if (m_dataSet->d_ptr->columnLabelItems().size() > col) { - // If draw order of bars is flipped, label draw order should be too - if (m_xFlipped) { - labelItem = m_dataSet->d_ptr->columnLabelItems().at( - m_dataSet->d_ptr->columnLabelItems().size() - col - 1); - } else { - labelItem = m_dataSet->d_ptr->columnLabelItems().at(col); - } - } - } else { - if (m_dataSet->d_ptr->rowLabelItems().size() > col) { - // If draw order of bars is flipped, label draw order should be too - if (m_zFlipped) { - labelItem = m_dataSet->d_ptr->rowLabelItems().at( - m_dataSet->d_ptr->rowLabelItems().size() - col - 1); - } else { - labelItem = m_dataSet->d_ptr->rowLabelItems().at(col); - } - } - } - m_drawer->drawLabel(*item, labelItem, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, -45.0f), m_heightNormalizer, - m_selectionMode, m_labelShader, - m_labelObj, false, false, LabelBelow); - } - - glDisable(GL_TEXTURE_2D); - if (m_labelTransparency > TransparencyNone) - glDisable(GL_BLEND); - glEnable(GL_DEPTH_TEST); - - // Release label shader - m_labelShader->release(); -} - -void Bars3dShared::drawScene() -{ - GLint startBar = 0; - GLint stopBar = 0; - GLint stepBar = 0; - - GLint startRow = 0; - GLint stopRow = 0; - GLint stepRow = 0; - - GLfloat backgroundRotation = 0; - - GLfloat barPos = 0; - GLfloat rowPos = 0; - - static QVector3D selection = skipColor; - - // Specify viewport - glViewport(m_sceneViewPort.x(), m_sceneViewPort.y(), - m_sceneViewPort.width(), m_sceneViewPort.height()); - - // Set up projection matrix - QMatrix4x4 projectionMatrix; - projectionMatrix.perspective(45.0f, (GLfloat)m_sceneViewPort.width() - / (GLfloat)m_sceneViewPort.height(), 0.1f, 100.0f); - - // Calculate view matrix - QMatrix4x4 viewMatrix = CameraHelper::calculateViewMatrix(m_mousePos, - m_zoomLevel - * m_zoomAdjustment, - m_sceneViewPort.width(), - m_sceneViewPort.height(), - m_negativeValues); - - // Calculate drawing order - // Draw order is reversed to optimize amount of drawing (ie. draw front objects first, depth test handles not needing to draw objects behind them) - if (viewMatrix.row(0).x() > 0) { - startRow = 0; - stopRow = m_sampleCount.second; - stepRow = 1; - m_zFlipped = false; - } else { - startRow = m_sampleCount.second - 1; - stopRow = -1; - stepRow = -1; - m_zFlipped = true; - } - if (viewMatrix.row(0).z() <= 0) { - startBar = 0; - stopBar = m_sampleCount.first; - stepBar = 1; - m_xFlipped = false; - } else { - startBar = m_sampleCount.first - 1; - stopBar = -1; - stepBar = -1; - m_xFlipped = true; - } - - // Check if we're viewing the scene from below - if (viewMatrix.row(2).y() < 0) - m_yFlipped = true; - else - m_yFlipped = false; - - // calculate background rotation based on view matrix rotation - if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() <= 0) - backgroundRotation = 270.0f; - else if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() > 0) - backgroundRotation = 180.0f; - else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() > 0) - backgroundRotation = 90.0f; - else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() <= 0) - backgroundRotation = 0.0f; - - // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) - QVector3D lightPos = CameraHelper::calculateLightPosition(defaultLightPos); - //lightPos = QVector3D(0.0f, 4.0f, zComp); // center of bars, 4.0f above - for testing - - // Skip depth rendering if we're in zoom mode - // TODO: Fix this, causes problems if depth rendering is off in zoom mode - // Introduce regardless of shadow quality to simplify logic - QMatrix4x4 depthViewMatrix; - QMatrix4x4 depthProjectionMatrix; - -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > ShadowNone/*!m_zoomActivated*/) { - // Render scene into a depth texture for using with shadow mapping - // Bind depth shader - m_depthShader->bind(); - - // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. - glViewport(m_sceneViewPort.x(), m_sceneViewPort.y(), - m_sceneViewPort.width() * m_shadowQuality, - m_sceneViewPort.height() * m_shadowQuality); - - // Enable drawing to framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); - glClear(GL_DEPTH_BUFFER_BIT); - - // Get the depth view matrix - // It may be possible to hack lightPos here if we want to make some tweaks to shadow - depthViewMatrix.lookAt(lightPos, QVector3D(0.0f, -m_yAdjustment, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed - //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); - // Set the depth projection matrix -#ifdef USE_WIDER_SHADOWS - // Use this for a bit exaggerated shadows - depthProjectionMatrix.perspective(20.0f, (GLfloat)m_sceneViewPort.width() - / (GLfloat)m_sceneViewPort.height(), 3.0f, 100.0f); -#else - // Use these for normal shadows, with the light further away - depthProjectionMatrix = projectionMatrix; -#endif - // Draw bars to depth buffer - for (int row = startRow; row != stopRow; row += stepRow) { - for (int bar = startBar; bar != stopBar; bar += stepBar) { - if (!m_dataSet->d_ptr->getRow(row)) - continue; - QDataItem *item = m_dataSet->d_ptr->getRow(row)->d_ptr->getItem(bar); - if (!item) - continue; - - GLfloat barHeight = item->d_ptr->value() / m_heightNormalizer; - - // skip shadows for 0 -height bars - if (barHeight == 0) - continue; - - // Set front face culling for positive valued bars and back face culling for - // negative valued bars to reduce self-shadowing issues - if (barHeight < 0) - glCullFace(GL_BACK); - else - glCullFace(GL_FRONT); - - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - - barPos = (bar + 1) * (m_barSpacing.width()); - rowPos = (row + 1) * (m_barSpacing.height()); - - modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor, - barHeight - m_yAdjustment, - (m_columnDepth - rowPos) / m_scaleFactor - + zComp); - modelMatrix.scale(QVector3D(m_scaleX, barHeight, m_scaleZ)); - - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); - - // 1st attribute buffer : vertices - glEnableVertexAttribArray(m_depthShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf()); - glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, - (void *)0); - - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf()); - - // Draw the triangles - glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT, - (void *)0); - - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glDisableVertexAttribArray(m_depthShader->posAtt()); - } - } - - // Disable drawing to framebuffer (= enable drawing to screen) - glBindFramebuffer(GL_FRAMEBUFFER, m_fbohandle); - - // Release depth shader - m_depthShader->release(); - -#if 0 // Use this if you want to see what is being drawn to the framebuffer - // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it) - m_labelShader->bind(); - glCullFace(GL_BACK); - glEnable(GL_TEXTURE_2D); - QMatrix4x4 modelMatrix; - QMatrix4x4 viewmatrix; - viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.5f + zComp), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - modelMatrix.translate(0.0, 0.0, zComp); - QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; - m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); - m_drawer->drawObject(m_labelShader, m_labelObj, - m_depthTexture); - glDisable(GL_TEXTURE_2D); - m_labelShader->release(); -#endif - // Reset culling to normal - glCullFace(GL_BACK); - - // Revert to original viewport - glViewport(m_sceneViewPort.x(), m_sceneViewPort.y(), - m_sceneViewPort.width(), m_sceneViewPort.height()); - } -#endif - - // Skip selection mode drawing if we're zoomed or have no selection mode - if (!m_zoomActivated && m_selectionMode > ModeNone) { - // Bind selection shader - m_selectionShader->bind(); - - // Draw bars to selection buffer -#ifndef USE_HAX0R_SELECTION - glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); - glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used - glClearColor(skipColor.x() / 255, skipColor.y() / 255, skipColor.z() / 255, 1.0f); // Set clear color to white (= skipColor) - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer -#endif - glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled - for (int row = startRow; row != stopRow; row += stepRow) { - for (int bar = startBar; bar != stopBar; bar += stepBar) { - if (!m_dataSet->d_ptr->getRow(row)) - continue; - QDataItem *item = m_dataSet->d_ptr->getRow(row)->d_ptr->getItem(bar); - if (!item) - continue; - - GLfloat barHeight = item->d_ptr->value() / m_heightNormalizer; - - if (barHeight < 0) - glCullFace(GL_FRONT); - else - glCullFace(GL_BACK); - - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - - barPos = (bar + 1) * (m_barSpacing.width()); - rowPos = (row + 1) * (m_barSpacing.height()); - - modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor, - barHeight - m_yAdjustment, - (m_columnDepth - rowPos) / m_scaleFactor - + zComp); - modelMatrix.scale(QVector3D(m_scaleX, barHeight, m_scaleZ)); - - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - - // TODO: Save position to qdataitem, so that we don't need to calculate it each time? - - //#if !defined(QT_OPENGL_ES_2) - // QVector3D barColor = QVector3D((GLdouble)row / 32767.0, - // (GLdouble)bar / 32767.0, - // 0.0); - //#else - QVector3D barColor = QVector3D((GLdouble)row / 255.0, - (GLdouble)bar / 255.0, - 0.0); - //#endif - - m_selectionShader->setUniformValue(m_selectionShader->MVP(), - MVPMatrix); - m_selectionShader->setUniformValue(m_selectionShader->color(), - barColor); - -#ifdef USE_HAX0R_SELECTION - // 1st attribute buffer : vertices - glEnableVertexAttribArray(m_selectionShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf()); - glVertexAttribPointer(m_selectionShader->posAtt(), - 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf()); - - // Draw the triangles - glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), - GL_UNSIGNED_SHORT, (void *)0); - - // Free buffers - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - glDisableVertexAttribArray(m_selectionShader->posAtt()); -#else - // 1st attribute buffer : vertices - glEnableVertexAttribArray(m_selectionShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf()); - glVertexAttribPointer(m_selectionShader->posAtt(), - 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf()); - - // Draw the triangles - glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT, - (void *)0); - - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glDisableVertexAttribArray(m_selectionShader->posAtt()); -#endif - } - } - glEnable(GL_DITHER); - - // Read color under cursor - if (Bars3dShared::MouseOnScene == m_mousePressed) - selection = Utils::getSelection(m_mousePos, height()); - -#ifndef USE_HAX0R_SELECTION - glBindFramebuffer(GL_FRAMEBUFFER, m_fbohandle); -#endif - - // Release selection shader - m_selectionShader->release(); - -#if 0 // Use this if you want to see what is being drawn to the framebuffer - glCullFace(GL_BACK); - m_labelShader->bind(); - glDisable(GL_DEPTH_TEST); - glEnable(GL_TEXTURE_2D); - QMatrix4x4 modelMatrix; - QMatrix4x4 viewmatrix; - viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f + zComp), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - modelMatrix.translate(0.0, 0.0, zComp); - QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; - m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); - m_drawer->drawObject(m_labelShader, m_labelObj, - m_selectionTexture); - glDisable(GL_TEXTURE_2D); - m_labelShader->release(); -#endif - -#ifdef USE_HAX0R_SELECTION - // Set clear color - QVector3D clearColor = Utils::vectorFromColor(m_theme->m_windowColor); - glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); - // Clear after selection - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -#endif - } - - // Bind bar shader - m_barShader->bind(); - - // Enable texturing - glEnable(GL_TEXTURE_2D); - - // Draw bars - if (!m_zoomActivated && m_zoomSelection) - m_zoomSelection->d_ptr->clear(); - bool barSelectionFound = false; - for (int row = startRow; row != stopRow; row += stepRow) { - for (int bar = startBar; bar != stopBar; bar += stepBar) { - if (!m_dataSet->d_ptr->getRow(row)) - continue; - QDataItem *item = m_dataSet->d_ptr->getRow(row)->d_ptr->getItem(bar); - if (!item) - continue; - - GLfloat barHeight = item->d_ptr->value() / m_heightNormalizer; - - if (barHeight < 0) - glCullFace(GL_FRONT); - else - glCullFace(GL_BACK); - - QMatrix4x4 modelMatrix; - QMatrix4x4 itModelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - - barPos = (bar + 1) * (m_barSpacing.width()); - rowPos = (row + 1) * (m_barSpacing.height()); - modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor, - barHeight - m_yAdjustment, - (m_columnDepth - rowPos) / m_scaleFactor + zComp); - modelMatrix.scale(QVector3D(m_scaleX, barHeight, m_scaleZ)); - itModelMatrix.scale(QVector3D(m_scaleX, barHeight, m_scaleZ)); -#ifdef SHOW_DEPTH_TEXTURE_SCENE - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; -#else - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; -#endif - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - QVector3D baseColor = Utils::vectorFromColor(m_theme->m_baseColor); - QVector3D heightColor = Utils::vectorFromColor(m_theme->m_heightColor) - * barHeight; - QVector3D depthColor = Utils::vectorFromColor(m_theme->m_depthColor) - * (float(row) / GLfloat(m_sampleCount.second)); - - QVector3D barColor = baseColor + heightColor + depthColor; - - GLfloat lightStrength = m_theme->m_lightStrength; - if (m_selectionMode > ModeNone) { - Bars3dShared::SelectionType selectionType = isSelected(row, bar, - selection); - switch (selectionType) { - case Bars3dShared::SelectionBar: { - barColor = Utils::vectorFromColor(m_theme->m_highlightBarColor); - lightStrength = m_theme->m_highlightLightStrength; - // Insert data to QDataItem. We have no ownership, don't delete the previous one - if (!m_zoomActivated) { - m_selectedBar = item; - if (m_dataSet->d_ptr->rowLabelItems().size() > row - && m_dataSet->d_ptr->columnLabelItems().size() > bar) { - m_selectedBar->setPosition( - QPoint(m_dataSet->d_ptr->rowLabelItems().size() - - row - 1, - m_dataSet->d_ptr->columnLabelItems().size() - - bar - 1)); - } - item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D()); - barSelectionFound = true; - if (m_selectionMode >= ModeZoomRow) { - item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D()); - m_zoomSelection->addItem(item); - } - } - break; - } - case Bars3dShared::SelectionRow: { - // Current bar is on the same row as the selected bar - barColor = Utils::vectorFromColor(m_theme->m_highlightRowColor); - lightStrength = m_theme->m_highlightLightStrength; - if (!m_zoomActivated && ModeZoomRow == m_selectionMode) { - item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D()); - m_zoomSelection->addItem(item); - if (m_dataSet->d_ptr->rowLabelItems().size() > row) { - m_zoomSelection->d_ptr->setLabelItem( - m_dataSet->d_ptr->rowLabelItems().at( - m_dataSet->d_ptr->rowLabelItems().size() - - row - 1)); - } - } - break; - } - case Bars3dShared::SelectionColumn: { - // Current bar is on the same column as the selected bar - barColor = Utils::vectorFromColor(m_theme->m_highlightColumnColor); - lightStrength = m_theme->m_highlightLightStrength; - if (!m_zoomActivated && ModeZoomColumn == m_selectionMode) { - item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D()); - m_zoomSelection->addItem(item); - if (m_dataSet->d_ptr->columnLabelItems().size() > bar) { - m_zoomSelection->d_ptr->setLabelItem( - m_dataSet->d_ptr->columnLabelItems().at( - m_dataSet->d_ptr->columnLabelItems().size() - - bar - 1)); - } - } - break; - } - case Bars3dShared::SelectionNone: { - // Current bar is not selected, nor on a row or column - // do nothing - break; - } - } - } - - if (barHeight != 0) { - // Set shader bindings - m_barShader->setUniformValue(m_barShader->lightP(), lightPos); - m_barShader->setUniformValue(m_barShader->view(), viewMatrix); - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.transposed().inverted()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); - m_barShader->setUniformValue(m_barShader->color(), barColor); - m_barShader->setUniformValue(m_barShader->ambientS(), - m_theme->m_ambientStrength); - -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > ShadowNone) { - // Set shadow shader bindings - m_barShader->setUniformValue(m_barShader->shadowQ(), - m_shadowQualityToShader); - m_barShader->setUniformValue(m_barShader->depth(), - depthMVPMatrix); - m_barShader->setUniformValue(m_barShader->lightS(), - lightStrength / 10.0f); - - // Draw the object - m_drawer->drawObject(m_barShader, m_barObj, - 0, m_depthTexture); - } else -#endif - { - // Set shadowless shader bindings - m_barShader->setUniformValue(m_barShader->lightS(), - lightStrength); - - // Draw the object - m_drawer->drawObject(m_barShader, m_barObj); - } - } - } - } - - // Release bar shader - m_barShader->release(); - - // Bind background shader - m_backgroundShader->bind(); - - if (m_negativeValues) - glDisable(GL_CULL_FACE); - else - glCullFace(GL_BACK); - - // Draw background - if (m_bgrEnabled && m_backgroundObj) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; - - modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); - modelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, - 1.0f, - m_columnDepth / m_scaleFactor)); - modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); - itModelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, - 1.0f, - m_columnDepth / m_scaleFactor)); - -#ifdef SHOW_DEPTH_TEXTURE_SCENE - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; -#else - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; -#endif - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - QVector3D backgroundColor = Utils::vectorFromColor(m_theme->m_backgroundColor); - - // Set shader bindings - m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), - lightPos); - m_backgroundShader->setUniformValue(m_backgroundShader->view(), - viewMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->model(), - modelMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->nModel(), - itModelMatrix.inverted().transposed()); - m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), - MVPMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->color(), - backgroundColor); - m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(), - m_theme->m_ambientStrength * 2.0f); - -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > ShadowNone) { - // Set shadow shader bindings - m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), - m_shadowQualityToShader); - m_backgroundShader->setUniformValue(m_backgroundShader->depth(), - depthMVPMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), - m_theme->m_lightStrength / 10.0f); - - // Draw the object - m_drawer->drawObject(m_backgroundShader, m_backgroundObj, - 0, m_depthTexture); - } else -#endif - { - // Set shadowless shader bindings - m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), - m_theme->m_lightStrength); - - // Draw the object - m_drawer->drawObject(m_backgroundShader, m_backgroundObj); - } - } - - // Disable textures - glDisable(GL_TEXTURE_2D); - - // Release background shader - m_backgroundShader->release(); - - // Reset culling - if (m_negativeValues) { - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - } - - // Draw grid lines - if (m_gridEnabled && m_heightNormalizer) { - // Bind bar shader - m_barShader->bind(); - - // Set unchanging shader bindings - QVector3D barColor = Utils::vectorFromColor(m_theme->m_gridLine); - m_barShader->setUniformValue(m_barShader->lightP(), lightPos); - m_barShader->setUniformValue(m_barShader->view(), viewMatrix); - m_barShader->setUniformValue(m_barShader->color(), barColor); - m_barShader->setUniformValue(m_barShader->ambientS(), - m_theme->m_ambientStrength); - - // Floor lines: rows - for (GLfloat row = 0.0f; row <= m_sampleCount.second; row++) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; - - rowPos = (row + 0.5f) * (m_barSpacing.height()); - modelMatrix.translate(0.0f, -m_yAdjustment, - (m_columnDepth - rowPos) / m_scaleFactor + zComp); - modelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, - gridLineWidth)); - itModelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, - gridLineWidth)); - // If we're viewing from below, grid line object must be flipped - if (m_yFlipped) - modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0); - - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - // Set the rest of the shader bindings - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); - -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > ShadowNone) { - // Set shadow shader bindings - m_barShader->setUniformValue(m_barShader->shadowQ(), - m_shadowQualityToShader); - m_barShader->setUniformValue(m_barShader->depth(), - depthMVPMatrix); - m_barShader->setUniformValue(m_barShader->lightS(), - m_theme->m_lightStrength / 10.0f); - - // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj, - 0, m_depthTexture); - } else -#endif - { - // Set shadowless shader bindings - m_barShader->setUniformValue(m_barShader->lightS(), - m_theme->m_lightStrength); - - // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj); - } - } - - // Floor lines: columns - for (GLfloat bar = 0.0f; bar <= m_sampleCount.first; bar++) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; - - barPos = (bar + 0.5f) * (m_barSpacing.width()); - modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor, - -m_yAdjustment, zComp); - modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, - m_columnDepth / m_scaleFactor)); - itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, - m_columnDepth / m_scaleFactor)); - - // If we're viewing from below, grid line object must be flipped - if (m_yFlipped) - modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0); - - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - // Set the rest of the shader bindings - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); - -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > ShadowNone) { - // Set shadow shader bindings - m_barShader->setUniformValue(m_barShader->shadowQ(), - m_shadowQualityToShader); - m_barShader->setUniformValue(m_barShader->depth(), - depthMVPMatrix); - m_barShader->setUniformValue(m_barShader->lightS(), - m_theme->m_lightStrength / 10.0f); - - // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj, - 0, m_depthTexture); - } else -#endif - { - // Set shadowless shader bindings - m_barShader->setUniformValue(m_barShader->lightS(), - m_theme->m_lightStrength); - - // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj); - } - } - - // Wall lines: back wall - GLfloat heightStep = m_heightNormalizer / 5.0f; // default to 5 lines - GLfloat startLine; - - if (m_tickCount > 0) - heightStep = m_tickStep; - - if (m_negativeValues) - startLine = -m_heightNormalizer; - else - startLine = heightStep; - - for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer; - lineHeight += heightStep) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; - - if (m_zFlipped) { - modelMatrix.translate(0.0f, - 2.0f * lineHeight / m_heightNormalizer - - m_yAdjustment, - m_columnDepth / m_scaleFactor + zComp); - } else { - modelMatrix.translate(0.0f, - 2.0f * lineHeight / m_heightNormalizer - - m_yAdjustment, - -m_columnDepth / m_scaleFactor + zComp); - } - modelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, - gridLineWidth)); - itModelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, - gridLineWidth)); - - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - // Set the rest of the shader bindings - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); - -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > ShadowNone) { - // Set shadow shader bindings - m_barShader->setUniformValue(m_barShader->shadowQ(), - m_shadowQualityToShader); - m_barShader->setUniformValue(m_barShader->depth(), - depthMVPMatrix); - m_barShader->setUniformValue(m_barShader->lightS(), - m_theme->m_lightStrength / 10.0f); - - // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj, - 0, m_depthTexture); - } else -#endif - { - // Set shadowless shader bindings - m_barShader->setUniformValue(m_barShader->lightS(), - m_theme->m_lightStrength); - - // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj); - } - } - - // Wall lines: side wall - for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer; - lineHeight += heightStep) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; - - if (m_xFlipped) { - modelMatrix.translate(m_rowWidth / m_scaleFactor, - 2.0f * lineHeight / m_heightNormalizer - - m_yAdjustment, - zComp); - } else { - modelMatrix.translate(-m_rowWidth / m_scaleFactor, - 2.0f * lineHeight / m_heightNormalizer - - m_yAdjustment, - zComp); - } - modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, - m_columnDepth / m_scaleFactor)); - itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, - m_columnDepth / m_scaleFactor)); - - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - // Set the rest of the shader bindings - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); - -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > ShadowNone) { - // Set shadow shader bindings - m_barShader->setUniformValue(m_barShader->shadowQ(), - m_shadowQualityToShader); - m_barShader->setUniformValue(m_barShader->depth(), - depthMVPMatrix); - m_barShader->setUniformValue(m_barShader->lightS(), - m_theme->m_lightStrength / 10.0f); - - // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj, - 0, m_depthTexture); - } else -#endif - { - // Set shadowless shader bindings - m_barShader->setUniformValue(m_barShader->lightS(), - m_theme->m_lightStrength); - - // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj); - } - } - - // Release bar shader - m_barShader->release(); - } - - // TODO: Draw y labels - - // Generate label textures for zoom selection if m_updateLabels is set - if (m_zoomActivated && m_updateLabels) { - // Create label textures - for (int col = 0; col < m_zoomSelection->d_ptr->row().size(); col++) { - QDataItem *item = m_zoomSelection->d_ptr->getItem(col); - m_drawer->generateLabelTexture(item); - } - } - - // Handle zoom activation and label drawing - if (!barSelectionFound) { - // We have no ownership, don't delete. Just NULL the pointer. - m_selectedBar = NULL; - if (m_zoomActivated && Bars3dShared::MouseOnOverview == m_mousePressed) { - m_sceneViewPort = QRect(0, 0, width(), height()); - m_zoomActivated = false; - } - } else if (m_selectionMode >= ModeZoomRow - && Bars3dShared::MouseOnScene == m_mousePressed) { - // Activate zoom mode - m_zoomActivated = true; - m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5); - - // Create label textures - for (int col = 0; col < m_zoomSelection->d_ptr->row().size(); col++) { - QDataItem *item = m_zoomSelection->d_ptr->getItem(col); - m_drawer->generateLabelTexture(item); - } - } else { - // Print value of selected bar - static QDataItem *prevItem = m_selectedBar; - m_labelShader->bind(); - glDisable(GL_DEPTH_TEST); - glEnable(GL_TEXTURE_2D); - if (m_labelTransparency > TransparencyNone) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } -#ifndef DISPLAY_FULL_DATA_ON_SELECTION - // Draw just the value string of the selected bar - if (prevItem != m_selectedBar || m_updateLabels) { - m_drawer->generateLabelTexture(m_selectedBar); - prevItem = m_selectedBar; - } - - m_drawer->drawLabel(*m_selectedBar, m_selectedBar->label(), - viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer, - m_selectionMode, m_labelShader, - m_labelObj, true); -#else - static bool firstSelection = true; - // Draw the value string followed by row label and column label - LabelItem labelItem = m_selectedBar->d_ptr->selectionLabel(); - if (firstSelection || prevItem != m_selectedBar || m_updateLabels) { - QString labelText = m_selectedBar->d_ptr->valueStr(); - if ((m_dataSet->d_ptr->columnLabels().size() - > m_selectedBar->position().y()) - && (m_dataSet->d_ptr->rowLabels().size() - > m_selectedBar->position().x())) { - labelText.append(QStringLiteral(" (")); - labelText.append(m_dataSet->d_ptr->rowLabels().at( - m_selectedBar->position().x())); - labelText.append(QStringLiteral(", ")); - labelText.append(m_dataSet->d_ptr->columnLabels().at( - m_selectedBar->position().y())); - labelText.append(QStringLiteral(")")); - //qDebug() << labelText; - } - m_drawer->generateLabelItem(&labelItem, labelText); - m_selectedBar->d_ptr->setSelectionLabel(labelItem); - prevItem = m_selectedBar; - firstSelection = false; - } - - m_drawer->drawLabel(*m_selectedBar, labelItem, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_heightNormalizer, - m_selectionMode, m_labelShader, - m_labelObj, true, false); -#endif - glDisable(GL_TEXTURE_2D); - if (m_labelTransparency > TransparencyNone) - glDisable(GL_BLEND); - glEnable(GL_DEPTH_TEST); - - // Release label shader - m_labelShader->release(); - - // Reset label update flag; they should have been updated when we get here - m_updateLabels = false; - } - - // TODO: Calculations done temporarily here. When optimizing, move to after data set addition? Keep drawing of the labels here. - // Bind label shader - m_labelShader->bind(); - - glEnable(GL_TEXTURE_2D); - if (m_labelTransparency > TransparencyNone) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - // Calculate the positions for row and column labels and store them into QDataItems (and QDataRows?) - for (int row = 0; row != m_sampleCount.second; row += 1) { - // Go through all rows and get position of max+1 or min-1 column, depending on x flip - // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems - rowPos = (row + 1) * (m_barSpacing.height()); - barPos = 0; - GLfloat rotLabelX = -90.0f; - GLfloat rotLabelY = 0.0f; - GLfloat rotLabelZ = 0.0f; - Qt::AlignmentFlag alignment = Qt::AlignRight; - if (m_zFlipped) - rotLabelY = 180.0f; - if (m_xFlipped) { - barPos = (m_sampleCount.first + 1) * (m_barSpacing.width()); - alignment = Qt::AlignLeft; - } - if (m_yFlipped) { - if (m_zFlipped) - rotLabelY = 0.0f; - else - rotLabelY = 180.0f; - rotLabelZ = 180.0f; - } - QVector3D labelPos = QVector3D((m_rowWidth - barPos) / m_scaleFactor, - -m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" - (m_columnDepth - rowPos) / m_scaleFactor - + zComp); - - // TODO: Try it; draw the label here - - // Create a data item - QDataItem *label = new QDataItem(); - label->d_ptr->setTranslation(labelPos); - if (m_dataSet->d_ptr->rowLabelItems().size() > row) { - label->d_ptr->setLabel(m_dataSet->d_ptr->rowLabelItems().at( - m_dataSet->d_ptr->rowLabelItems().size() - row - 1)); - } - - //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << m_dataSet->d_ptr->rowLabels().at(row); - - m_drawer->drawLabel(*label, label->d_ptr->label(), viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(rotLabelX, rotLabelY, rotLabelZ), - m_heightNormalizer, m_selectionMode, - m_labelShader, m_labelObj, true, true, LabelMid, - alignment); - - delete label; - } - for (int bar = 0; bar != m_sampleCount.first; bar += 1) { - // Go through all columns and get position of max+1 or min-1 row, depending on z flip - // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems - barPos = (bar + 1) * (m_barSpacing.width()); - rowPos = 0; - GLfloat rotLabelX = -90.0f; - GLfloat rotLabelY = 90.0f; - GLfloat rotLabelZ = 0.0f; - Qt::AlignmentFlag alignment = Qt::AlignLeft; - if (m_xFlipped) - rotLabelY = -90.0f; - if (m_zFlipped) { - rowPos = (m_sampleCount.second + 1) * (m_barSpacing.height()); - alignment = Qt::AlignRight; - } - if (m_yFlipped) { - if (m_xFlipped) - rotLabelY = -90.0f; - else - rotLabelY = 90.0f; - rotLabelZ = 180.0f; - } - QVector3D labelPos = QVector3D((m_rowWidth - barPos) / m_scaleFactor, - -m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" - (m_columnDepth - rowPos) / m_scaleFactor - + zComp); - - // TODO: Try it; draw the label here - - // Create a data item - QDataItem *label = new QDataItem(); - label->d_ptr->setTranslation(labelPos); - if (m_dataSet->d_ptr->columnLabelItems().size() > bar) { - label->d_ptr->setLabel(m_dataSet->d_ptr->columnLabelItems().at( - m_dataSet->d_ptr->columnLabelItems().size() - - bar - 1)); - } - - //qDebug() << "labelPos, col" << bar + 1 << ":" << labelPos << m_dataSet->d_ptr->columnLabels().at(bar); - - m_drawer->drawLabel(*label, label->d_ptr->label(), viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(rotLabelX, rotLabelY, rotLabelZ), - m_heightNormalizer, m_selectionMode, - m_labelShader, m_labelObj, true, true, LabelMid, - alignment); - - delete label; - } - glDisable(GL_TEXTURE_2D); - if (m_labelTransparency > TransparencyNone) - glDisable(GL_BLEND); - - // Release label shader - m_labelShader->release(); -} - -#if defined(Q_OS_ANDROID) -void Bars3dShared::mouseDoubleClickEvent(QMouseEvent *event) -{ - if (!m_zoomActivated) { - m_mousePressed = Bars3dShared::MouseOnScene; - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = event->pos(); - } -} - -void Bars3dShared::touchEvent(QTouchEvent *event) -{ - static int prevDistance = 0; - - QList<QTouchEvent::TouchPoint> points; - points = event->touchPoints(); - - if (points.count() == 2) { - m_mousePressed = Bars3dShared::MouseOnPinch; - - QPointF distance = points.at(0).pos() - points.at(1).pos(); - int newDistance = distance.manhattanLength(); - int zoomRate = 1; - if (m_zoomLevel > 100) - zoomRate = 5; - if (newDistance > prevDistance) - m_zoomLevel += zoomRate; - else - m_zoomLevel -= zoomRate; - if (m_zoomLevel > 500) - m_zoomLevel = 500; - else if (m_zoomLevel < 10) - m_zoomLevel = 10; - prevDistance = newDistance; - //qDebug() << "distance" << distance.manhattanLength(); - } -} -#endif - -void Bars3dShared::mousePressEvent(QMouseEvent *event) -{ - if (Qt::LeftButton == event->button()) { - if (m_zoomActivated) { - if (event->pos().x() <= m_sceneViewPort.width() - && event->pos().y() <= m_sceneViewPort.height()) { - m_mousePressed = Bars3dShared::MouseOnOverview; - //qDebug() << "Mouse pressed on overview"; - } else { - m_mousePressed = Bars3dShared::MouseOnZoom; - //qDebug() << "Mouse pressed on zoom"; - } - } else { -#if !defined(Q_OS_ANDROID) - m_mousePressed = Bars3dShared::MouseOnScene; -#else - m_mousePressed = Bars3dShared::MouseRotating; -#endif - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = event->pos(); - //qDebug() << "Mouse pressed on scene"; - } - } else if (Qt::MiddleButton == event->button()) { - // reset rotations - m_mousePos = QPoint(0, 0); - } else if (Qt::RightButton == event->button()) { -#if !defined(Q_OS_ANDROID) - m_mousePressed = Bars3dShared::MouseRotating; -#else - m_mousePressed = Bars3dShared::MouseOnScene; -#endif - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = event->pos(); - } - CameraHelper::updateMousePos(m_mousePos); -} - -void Bars3dShared::mouseReleaseEvent(QMouseEvent *event) -{ - if (Bars3dShared::MouseRotating == m_mousePressed) { - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = event->pos(); - CameraHelper::updateMousePos(event->pos()); - } - m_mousePressed = Bars3dShared::MouseNone; -} - -void Bars3dShared::mouseMoveEvent(QMouseEvent *event) -{ - if (Bars3dShared::MouseRotating == m_mousePressed) - m_mousePos = event->pos(); -} - -void Bars3dShared::wheelEvent(QWheelEvent *event) -{ - if (m_zoomLevel > 100) - m_zoomLevel += event->angleDelta().y() / 12; - else if (m_zoomLevel > 50) - m_zoomLevel += event->angleDelta().y() / 60; - else - m_zoomLevel += event->angleDelta().y() / 120; - if (m_zoomLevel > 500) - m_zoomLevel = 500; - else if (m_zoomLevel < 10) - m_zoomLevel = 10; -} - -void Bars3dShared::resizeNotify() -{ - qDebug() << "Bars3dShared::resizeEvent " << width() << "x" <<height(); - - // Set view port - if (m_zoomActivated) - m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5); - else - m_sceneViewPort = QRect(0, 0, width(), height()); - m_zoomViewPort = QRect(0, 0, width(), height()); - - // Calculate zoom level based on aspect ratio - GLfloat div; - GLfloat zoomAdjustment; - div = qMin(width(), height()); - zoomAdjustment = defaultRatio * ((width() / div) / (height() / div)); - //qDebug() << "zoom adjustment" << zoomAdjustment; - m_zoomAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f - - // Re-init selection buffer - initSelectionBuffer(); - -#if !defined(QT_OPENGL_ES_2) - // Re-init depth buffer - if (m_isInitialized && m_shadowQuality > ShadowNone) - initDepthBuffer(); -#endif -} - -void Bars3dShared::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative) -{ - m_barThickness = thickness; - if (relative) { - m_barSpacing.setWidth((thickness.width() * 2) * (spacing.width() + 1.0f)); - m_barSpacing.setHeight((thickness.height() * 2) * (spacing.height() + 1.0f)); - } else { - m_barSpacing = thickness * 2 + spacing * 2; - } - // Calculate here and at setting sample space - calculateSceneScalingFactors(); -} - -void Bars3dShared::setBarType(BarStyle style, bool smooth) -{ - if (style == Bars) { - if (smooth) - m_objFile = QStringLiteral(":/defaultMeshes/barSmooth"); - else - m_objFile = QStringLiteral(":/defaultMeshes/bar"); - } else if (style == Pyramids) { - if (smooth) - m_objFile = QStringLiteral(":/defaultMeshes/pyramidSmooth"); - else - m_objFile = QStringLiteral(":/defaultMeshes/pyramid"); - } else if (style == Cones) { - if (smooth) - m_objFile = QStringLiteral(":/defaultMeshes/coneSmooth"); - else - m_objFile = QStringLiteral(":/defaultMeshes/cone"); - } else if (style == Cylinders) { - if (smooth) - m_objFile = QStringLiteral(":/defaultMeshes/cylinderSmooth"); - else - m_objFile = QStringLiteral(":/defaultMeshes/cylinder"); - } else if (style == BevelBars) { - if (smooth) - m_objFile = QStringLiteral(":/defaultMeshes/bevelbarSmooth"); - else - m_objFile = QStringLiteral(":/defaultMeshes/bevelbar"); - } - // Reload mesh data - if (m_isInitialized) - loadBarMesh(); -} - -void Bars3dShared::setMeshFileName(const QString &objFileName) -{ - m_objFile = objFileName; -} - -void Bars3dShared::setupSampleSpace(int samplesRow, int samplesColumn, const QString &labelRow, - const QString &labelColumn, const QString &labelHeight) -{ - // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted) - closeZoomMode(); - // Delete previous data set - delete m_dataSet; - m_dataSet = new QDataSet(); - m_sampleCount = qMakePair(samplesRow, samplesColumn); - m_dataSet->setLabels(labelRow, labelColumn, labelHeight); - // TODO: Invent "idiotproof" max scene size formula.. - // This seems to work ok if spacing is not negative (and row/column or column/row ratio is not too high) - m_maxSceneSize = 2 * qSqrt(samplesRow * samplesColumn); - //qDebug() << "maxSceneSize" << m_maxSceneSize; - // Calculate here and at setting bar specs - calculateSceneScalingFactors(); - m_axisLabelX = labelRow; - m_axisLabelZ = labelColumn; - m_axisLabelY = labelHeight; -} - -void Bars3dShared::setCameraPreset(CameraPreset preset) -{ - CameraHelper::setCameraPreset(preset); -} - -void Bars3dShared::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) -{ - m_horizontalRotation = qBound(-180.0f, horizontal, 180.0f); - m_verticalRotation = qBound(0.0f, vertical, 90.0f); - m_zoomLevel = qBound(10, distance, 500); - CameraHelper::setCameraRotation(QPointF(m_horizontalRotation, - m_verticalRotation)); - //qDebug() << "camera rotation set to" << m_horizontalRotation << m_verticalRotation; -} - -void Bars3dShared::setTheme(ColorTheme theme) -{ - m_theme->useTheme(theme); - m_drawer->setTheme(*m_theme); - // Re-initialize shaders -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > ShadowNone) { - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - } else { - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - } -#else - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } -#endif -} - -void Bars3dShared::setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, - bool uniform) -{ - m_theme->m_baseColor = baseColor; - m_theme->m_heightColor = heightColor; - m_theme->m_depthColor = depthColor; - //qDebug() << "colors:" << m_baseColor << m_heightColor << m_depthColor; - if (m_theme->m_uniformColor != uniform) { -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > ShadowNone) { - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - } else { - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - } -#else - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } -#endif - } - m_theme->m_uniformColor = uniform; -} - -void Bars3dShared::setSelectionMode(SelectionMode mode) -{ - m_selectionMode = mode; - // Disable zoom if selection mode changes - closeZoomMode(); - // Create zoom selection if there isn't one - if (mode >= ModeZoomRow && !m_zoomSelection) - m_zoomSelection = new QDataRow(); -} - -SelectionMode Bars3dShared::selectionMode() -{ - return m_selectionMode; -} - -void Bars3dShared::setFontSize(float fontsize) -{ - m_font.setPointSizeF(fontsize); - m_drawer->setFont(m_font); -} - -float Bars3dShared::fontSize() -{ - return m_font.pointSizeF(); -} - -void Bars3dShared::setFont(const QFont &font) -{ - m_font = font; - m_drawer->setFont(font); -} - -QFont Bars3dShared::font() -{ - return m_font; -} - -void Bars3dShared::setLabelTransparency(LabelTransparency transparency) -{ - m_labelTransparency = transparency; - m_drawer->setTransparency(transparency); -} - -LabelTransparency Bars3dShared::labelTransparency() -{ - return m_labelTransparency; -} - -void Bars3dShared::setGridEnabled(bool enable) -{ - m_gridEnabled = enable; -} - -bool Bars3dShared::gridEnabled() -{ - return m_gridEnabled; -} - -void Bars3dShared::setBackgroundEnabled(bool enable) -{ - if (m_bgrEnabled != enable) { - m_bgrEnabled = enable; - // Load changed bar type - loadBarMesh(); - } -} - -bool Bars3dShared::backgroundEnabled() -{ - return m_bgrEnabled; -} - -void Bars3dShared::setShadowQuality(ShadowQuality quality) -{ - m_shadowQuality = quality; - switch (quality) { - case ShadowLow: - m_shadowQualityToShader = 33.3f; - break; - case ShadowMedium: - m_shadowQualityToShader = 100.0f; - break; - case ShadowHigh: - m_shadowQualityToShader = 200.0f; - break; - default: - m_shadowQualityToShader = 0.0f; - break; - } - if (m_isInitialized) { -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > ShadowNone) { - // Re-init depth buffer - initDepthBuffer(); - // Re-init shaders - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } else { - // Re-init shaders - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } -#else - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); -#endif - } -} - -ShadowQuality Bars3dShared::shadowQuality() -{ - return m_shadowQuality; -} - -void Bars3dShared::setTickCount(GLint tickCount, GLfloat step, GLfloat minimum) -{ - m_tickCount = tickCount; - m_tickStep = step; - if (tickCount > 0 && step > 0) { - m_heightNormalizer = tickCount * step; - calculateHeightAdjustment(QPair<float, float>(minimum, m_heightNormalizer)); - } -} - -void Bars3dShared::addDataRow(const QVector<float> &dataRow, const QString &labelRow, - const QVector<QString> &labelsColumn) -{ - // Convert to QDataRow and add to QDataSet - QDataRow *row = new QDataRow(labelRow); - for (int i = 0; i < dataRow.size(); i++) - row->addItem(new QDataItem(dataRow.at(i))); - row->d_ptr->verifySize(m_sampleCount.first); - m_dataSet->addRow(row); - handleLimitChange(); - m_dataSet->setLabels(m_axisLabelX, m_axisLabelZ, m_axisLabelY, - QVector<QString>(), labelsColumn); - m_dataSet->d_ptr->verifySize(m_sampleCount.second); -} - -void Bars3dShared::addDataRow(const QVector<QDataItem*> &dataRow, const QString &labelRow, - const QVector<QString> &labelsColumn) -{ - // Convert to QDataRow and add to QDataSet - QDataRow *row = new QDataRow(labelRow); - for (int i = 0; i < dataRow.size(); i++) - row->addItem(dataRow.at(i)); - row->d_ptr->verifySize(m_sampleCount.first); - m_dataSet->addRow(row); - handleLimitChange(); - m_dataSet->setLabels(m_axisLabelX, m_axisLabelZ, m_axisLabelY, - QVector<QString>(), labelsColumn); - m_dataSet->d_ptr->verifySize(m_sampleCount.second); -} - -void Bars3dShared::addDataRow(QDataRow *dataRow) -{ - QDataRow *row = dataRow; - // Check that the input data fits into sample space, and resize if it doesn't - row->d_ptr->verifySize(m_sampleCount.first); - // With each new row, the previous data row must be moved back - // ie. we need as many vectors as we have rows in the sample space - m_dataSet->addRow(row); - // if the added data pushed us over sample space, remove the oldest data set - m_dataSet->d_ptr->verifySize(m_sampleCount.second); - handleLimitChange(); -} - -void Bars3dShared::addDataSet(const QVector< QVector<float> > &data, - const QVector<QString> &labelsRow, - const QVector<QString> &labelsColumn) -{ - // Copy axis labels - QString xAxis; - QString zAxis; - QString yAxis; - m_dataSet->d_ptr->axisLabels(&xAxis, &zAxis, &yAxis); - // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted) - closeZoomMode(); - // Delete old data set - delete m_dataSet; - m_dataSet = new QDataSet(); - // Give drawer to data set - m_dataSet->d_ptr->setDrawer(m_drawer); - // Convert to QDataRow and add to QDataSet - QDataRow *row; - for (int rowNr = 0; rowNr < data.size(); rowNr++) { - if (labelsRow.size() >= (rowNr + 1)) - row = new QDataRow(labelsRow.at(rowNr)); - else - row = new QDataRow(); - for (int colNr = 0; colNr < data.at(rowNr).size(); colNr++) - row->addItem(new QDataItem(data.at(rowNr).at(colNr))); - row->d_ptr->verifySize(m_sampleCount.first); - m_dataSet->addRow(row); - row++; - } - handleLimitChange(); - m_dataSet->setLabels(xAxis, zAxis, yAxis, labelsRow, labelsColumn); - m_dataSet->d_ptr->verifySize(m_sampleCount.second); -} - -void Bars3dShared::addDataSet(const QVector< QVector<QDataItem*> > &data, - const QVector<QString> &labelsRow, - const QVector<QString> &labelsColumn) -{ - // Copy axis labels - QString xAxis; - QString zAxis; - QString yAxis; - m_dataSet->d_ptr->axisLabels(&xAxis, &zAxis, &yAxis); - // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted) - closeZoomMode(); - // Delete old data set - delete m_dataSet; - m_dataSet = new QDataSet(); - // Give drawer to data set - m_dataSet->d_ptr->setDrawer(m_drawer); - // Convert to QDataRow and add to QDataSet - QDataRow *row; - for (int rowNr = 0; rowNr < data.size(); rowNr++) { - if (labelsRow.size() >= (rowNr + 1)) - row = new QDataRow(labelsRow.at(rowNr)); - else - row = new QDataRow(); - for (int colNr = 0; colNr < data.at(rowNr).size(); colNr++) - row->addItem(data.at(rowNr).at(colNr)); - row->d_ptr->verifySize(m_sampleCount.first); - m_dataSet->addRow(row); - row++; - } - handleLimitChange(); - m_dataSet->setLabels(xAxis, zAxis, yAxis, labelsRow, labelsColumn); - m_dataSet->d_ptr->verifySize(m_sampleCount.second); -} - -void Bars3dShared::addDataSet(QDataSet* dataSet) -{ - // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted) - closeZoomMode(); - // Delete old data set - delete m_dataSet; - // Check sizes - dataSet->d_ptr->verifySize(m_sampleCount.second, m_sampleCount.first); - // Take ownership of given set - m_dataSet = dataSet; - handleLimitChange(); - // Give drawer to data set - m_dataSet->d_ptr->setDrawer(m_drawer); -} - -const QSize Bars3dShared::size() -{ - return m_boundingRect.size();; -} - -const QRect Bars3dShared::boundingRect() -{ - return m_boundingRect; -} - -void Bars3dShared::setBoundingRect(const QRect boundingRect) -{ - m_boundingRect = boundingRect; -} - -void Bars3dShared::setWidth(const int width) -{ - m_boundingRect.setWidth(width); -} - -int Bars3dShared::width() -{ - return m_boundingRect.width(); -} - -void Bars3dShared::setHeight(const int height) -{ - m_boundingRect.setHeight(height); -} - -int Bars3dShared::height() -{ - return m_boundingRect.height(); -} - -void Bars3dShared::setX(const int x) -{ - m_boundingRect.setX(x); -} - -int Bars3dShared::x() -{ - return m_boundingRect.x(); -} - -void Bars3dShared::setY(const int y) -{ - m_boundingRect.setY(y); -} - -int Bars3dShared::y() -{ - return m_boundingRect.y(); -} - -void Bars3dShared::loadBarMesh() -{ - QString objectFileName = m_objFile; - if (m_barObj) - delete m_barObj; - // If background is disabled, load full version of bar mesh - if (!m_bgrEnabled) - objectFileName.append(QStringLiteral("Full")); - m_barObj = new ObjectHelper(objectFileName); - m_barObj->load(); -} - -void Bars3dShared::loadBackgroundMesh() -{ - if (!m_isInitialized) - return; - - if (m_backgroundObj) - delete m_backgroundObj; - if (m_negativeValues) - m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/negativeBackground")); - else - m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background")); - m_backgroundObj->load(); -} - -void Bars3dShared::loadGridLineMesh() -{ - if (m_gridLineObj) - delete m_gridLineObj; - m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar")); - m_gridLineObj->load(); -} - -void Bars3dShared::loadLabelMesh() -{ - if (m_labelObj) - delete m_labelObj; - m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); - m_labelObj->load(); -} - -void Bars3dShared::initShaders(const QString &vertexShader, const QString &fragmentShader) -{ - if (m_barShader) - delete m_barShader; - m_barShader = new ShaderHelper(this, vertexShader, fragmentShader); - m_barShader->initialize(); -} - -void Bars3dShared::initSelectionShader() -{ - if (m_selectionShader) - delete m_selectionShader; - m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSelection"), - QStringLiteral(":/shaders/fragmentSelection")); - m_selectionShader->initialize(); -} - -void Bars3dShared::initSelectionBuffer() -{ -#ifndef USE_HAX0R_SELECTION - if (m_selectionTexture) { - glDeleteFramebuffers(1, &m_selectionFrameBuffer); - glDeleteRenderbuffers(1, &m_selectionDepthBuffer); - m_textureHelper->deleteTexture(&m_selectionTexture); - } - m_selectionTexture = m_textureHelper->createSelectionTexture(this->size(), - m_selectionFrameBuffer, - m_selectionDepthBuffer); -#endif -} - -#if !defined(QT_OPENGL_ES_2) -void Bars3dShared::initDepthShader() -{ - if (m_depthShader) - delete m_depthShader; - m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"), - QStringLiteral(":/shaders/fragmentDepth")); - m_depthShader->initialize(); -} - -void Bars3dShared::initDepthBuffer() -{ - if (m_depthTexture) { - glDeleteFramebuffers(1, &m_depthFrameBuffer); - m_textureHelper->deleteTexture(&m_depthTexture); - } - m_depthTexture = m_textureHelper->createDepthTexture(this->size(), m_depthFrameBuffer, - m_shadowQuality); -} -#endif - -void Bars3dShared::initBackgroundShaders(const QString &vertexShader, - const QString &fragmentShader) -{ - if (m_backgroundShader) - delete m_backgroundShader; - m_backgroundShader = new ShaderHelper(this, vertexShader, fragmentShader); - m_backgroundShader->initialize(); -} - -void Bars3dShared::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) -{ - if (m_labelShader) - delete m_labelShader; - m_labelShader = new ShaderHelper(this, vertexShader, fragmentShader); - m_labelShader->initialize(); -} - -void Bars3dShared::updateTextures() -{ - // Drawer has changed; this flag needs to be checked when checking if we need to update labels - m_updateLabels = true; -} - -void Bars3dShared::calculateSceneScalingFactors() -{ - // Calculate scene scaling and translation factors - m_rowWidth = ((m_sampleCount.first + 1) * m_barSpacing.width()) / 2.0f; - m_columnDepth = ((m_sampleCount.second + 1) * m_barSpacing.height()) / 2.0f; - m_maxDimension = qMax(m_rowWidth, m_columnDepth); - m_scaleFactor = qMin((m_sampleCount.first * (m_maxDimension / m_maxSceneSize)), - (m_sampleCount.second * (m_maxDimension / m_maxSceneSize))); - m_scaleX = m_barThickness.width() / m_scaleFactor; - m_scaleZ = m_barThickness.height() / m_scaleFactor; - //qDebug() << "m_scaleX" << m_scaleX << "m_scaleFactor" << m_scaleFactor; - //qDebug() << "m_scaleZ" << m_scaleZ << "m_scaleFactor" << m_scaleFactor; - //qDebug() << "m_rowWidth:" << m_rowWidth << "m_columnDepth:" << m_columnDepth << "m_maxDimension:" << m_maxDimension; -} - -void Bars3dShared::calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits) -{ - // 2.0f = max difference between minimum and maximum value after scaling with m_heightNormalizer - m_yAdjustment = 2.0f - ((limits.second - limits.first) / m_heightNormalizer); - //qDebug() << m_yAdjustment; -} - -Bars3dShared::SelectionType Bars3dShared::isSelected(GLint row, GLint bar, - const QVector3D &selection) -{ - //static QVector3D prevSel = selection; // TODO: For debugging - SelectionType isSelectedType = SelectionNone; -#ifdef USE_HAX0R_SELECTION - if (selection == Utils::vectorFromColor(m_theme->m_windowColor)) -#else - if (selection == skipColor) -#endif - return isSelectedType; // skip window - - //#if !defined(QT_OPENGL_ES_2) - // QVector3D current = QVector3D((GLuint)row, (GLuint)bar, 0); - //#else - QVector3D current = QVector3D((GLubyte)row, (GLubyte)bar, 0); - //#endif - - // TODO: For debugging - //if (selection != prevSel) { - // qDebug() << "current" << current.x() << current .y() << current.z(); - // qDebug() << "selection" << selection.x() << selection .y() << selection.z(); - // prevSel = selection; - //} - if (current == selection) - isSelectedType = SelectionBar; - else if (current.y() == selection.y() && (m_selectionMode == ModeBarAndColumn - || m_selectionMode == ModeBarRowAndColumn - || m_selectionMode == ModeZoomColumn)) - isSelectedType = SelectionColumn; - else if (current.x() == selection.x() && (m_selectionMode == ModeBarAndRow - || m_selectionMode == ModeBarRowAndColumn - || m_selectionMode == ModeZoomRow)) - isSelectedType = SelectionRow; - return isSelectedType; -} - -void Bars3dShared::handleLimitChange() -{ - // Get the limits - QPair<GLfloat, GLfloat> limits = m_dataSet->d_ptr->limitValues(); - - // TODO: What if we have only negative values? - - // Check if we have negative values - if (limits.first < 0 && !m_negativeValues) { - m_negativeValues = true; - // Reload background - loadBackgroundMesh(); - } else if (limits.first >= 0 && m_negativeValues) { - m_negativeValues = false; - // Reload background - loadBackgroundMesh(); - } - - // Don't auto-adjust height if tick count is set - if (m_tickCount == 0) { - m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); - calculateHeightAdjustment(limits); - } -} - -void Bars3dShared::closeZoomMode() -{ - m_zoomActivated = false; - m_sceneViewPort = QRect(0, 0, this->width(), this->height()); -} - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/bars3dshared_p.h b/src/datavis3d/engine/bars3dshared_p.h deleted file mode 100644 index 2250b7c4..00000000 --- a/src/datavis3d/engine/bars3dshared_p.h +++ /dev/null @@ -1,326 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt 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 Q3DBARSSHARED_p_H -#define Q3DBARSSHARED_p_H - -#include "QtDataVis3D/qdatavis3dglobal.h" -#include "QtDataVis3D/qdatavis3namespace.h" - -#include <QtCore/QSize> -#include <QtCore/QObject> -#include <QtGui/QOpenGLFunctions> -#include <QtGui/QFont> - -#include <QWindow> - -class QOpenGLPaintDevice; -class QPoint; -class QSizeF; -class QOpenGLShaderProgram; - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -class QDataItem; -class QDataRow; -class QDataSet; -class ShaderHelper; -class ObjectHelper; -class TextureHelper; -class Theme; -class Drawer; -class LabelItem; -class Bars3dSharedPrivate; - -class QTENTERPRISE_DATAVIS3D_EXPORT Bars3dShared : public QObject, public QOpenGLFunctions -{ - Q_OBJECT - -public: - enum SelectionType { - SelectionNone = 0, - SelectionBar, - SelectionRow, - SelectionColumn - }; - - enum MousePressType { - MouseNone = 0, - MouseOnScene, - MouseOnOverview, - MouseOnZoom, - MouseRotating, - MouseOnPinch - }; - - QRect m_boundingRect; - QOpenGLPaintDevice *m_paintDevice; - ShaderHelper *m_barShader; - ShaderHelper *m_depthShader; - ShaderHelper *m_selectionShader; - ShaderHelper *m_backgroundShader; - ShaderHelper *m_labelShader; - ObjectHelper *m_barObj; - ObjectHelper *m_backgroundObj; - ObjectHelper *m_gridLineObj; - ObjectHelper *m_labelObj; - QPair<int, int> m_sampleCount; - QString m_objFile; - MousePressType m_mousePressed; - QPoint m_mousePos; - GLint m_zoomLevel; - GLfloat m_zoomAdjustment; - GLfloat m_horizontalRotation; - GLfloat m_verticalRotation; - QSizeF m_barThickness; - QSizeF m_barSpacing; - GLfloat m_heightNormalizer; - GLfloat m_yAdjustment; - GLfloat m_rowWidth; - GLfloat m_columnDepth; - GLfloat m_maxDimension; - GLfloat m_scaleX; - GLfloat m_scaleZ; - GLfloat m_scaleFactor; - GLfloat m_maxSceneSize; - Theme *m_theme; - bool m_isInitialized; - SelectionMode m_selectionMode; - QDataItem *m_selectedBar; - QDataRow *m_zoomSelection; - QDataSet *m_dataSet; - QString m_axisLabelX; - QString m_axisLabelZ; - QString m_axisLabelY; - QRect m_sceneViewPort; - QRect m_zoomViewPort; - bool m_zoomActivated; - TextureHelper *m_textureHelper; - LabelTransparency m_labelTransparency; - QFont m_font; - Drawer *m_drawer; - bool m_xFlipped; - bool m_zFlipped; - bool m_yFlipped; - GLuint m_bgrTexture; - GLuint m_depthTexture; - GLuint m_selectionTexture; - GLuint m_depthFrameBuffer; - GLuint m_selectionFrameBuffer; - GLuint m_selectionDepthBuffer; - bool m_updateLabels; - bool m_gridEnabled; - bool m_bgrEnabled; - ShadowQuality m_shadowQuality; - GLfloat m_shadowQualityToShader; - GLint m_tickCount; - GLfloat m_tickStep; - bool m_negativeValues; - GLuint m_fbohandle; - QSize m_size; - -public: - explicit Bars3dShared(QRect rect, GLuint fbohandle=0); - ~Bars3dShared(); - - void initializeOpenGL(); - void render(); - - // Add a row of data. Each new row is added to the front of the sample space, moving previous - // rows back (if sample space is more than one row deep) - void addDataRow(const QVector<GLfloat> &dataRow, - const QString &labelRow = QString(), - const QVector<QString> &labelsColumn = QVector<QString>()); - // ownership of dataItems is transferred - void addDataRow(const QVector<QDataItem*> &dataRow, - const QString &labelRow = QString(), - const QVector<QString> &labelsColumn = QVector<QString>()); - // ownership of dataRow is transferred - void addDataRow(QDataRow *dataRow); - - // Add complete data set at a time, as a vector of data rows - void addDataSet(const QVector< QVector<GLfloat> > &data, - const QVector<QString> &labelsRow = QVector<QString>(), - const QVector<QString> &labelsColumn = QVector<QString>()); - - // ownership of dataItems is transferred - void addDataSet(const QVector< QVector<QDataItem*> > &data, - const QVector<QString> &labelsRow = QVector<QString>(), - const QVector<QString> &labelsColumn = QVector<QString>()); - // ownership of dataSet is transferred - void addDataSet(QDataSet* dataSet); - - // bar thickness, spacing between bars, and is spacing relative to thickness or absolute - // y -component sets the thickness/spacing of z -direction - // With relative 0.0f means side-to-side, 1.0f = one thickness in between - void setBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f), - QSizeF spacing = QSizeF(1.0f, 1.0f), - bool relative = true); - - // bar type; bars (=cubes), pyramids, cones, cylinders, etc. - void setBarType(BarStyle style, bool smooth = false); - - // override bar type with own mesh - void setMeshFileName(const QString &objFileName); - - // how many samples per row and column, and names for axes - void setupSampleSpace(int samplesRow, int samplesColumn, - const QString &labelRow = QString(), - const QString &labelColumn = QString(), - const QString &labelHeight = QString()); - - // Select preset camera placement - void setCameraPreset(CameraPreset preset); - - // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and - // vertical (0...90) (or (-90...90) if there are negative values) angles and distance in - // percentage (10...500)) - void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); - - // Set theme (bar colors, shaders, window color, background colors, light intensity and text - // colors are affected) - void setTheme(ColorTheme theme); - - // Set color if you don't want to use themes. Set uniform to false if you want the (height) - // color to change from bottom to top - void setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, - bool uniform = true); - - // Set tick count and step. Note; tickCount * step should be the maximum possible value of data - // set. Minimum is the absolute minimum possible value a bar can have. This is especially - // important to set if values can be negative. - void setTickCount(GLint tickCount, GLfloat step, GLfloat minimum = 0.0f); - - // TODO: light placement API - - // Size - const QSize size(); - const QRect boundingRect(); - void setBoundingRect(const QRect boundingRect); - void setWidth(const int width); - int width(); - void setHeight(const int height); - int height(); - void setX(const int x); - int x(); - void setY(const int y); - int y(); - - // Change selection mode; single bar, bar and row, bar and column, or all - void setSelectionMode(SelectionMode mode); - SelectionMode selectionMode(); - - // Font size adjustment - void setFontSize(float fontsize); - float fontSize(); - - // Set font - void setFont(const QFont &font); - QFont font(); - - // Label transparency adjustment - void setLabelTransparency(LabelTransparency transparency); - LabelTransparency labelTransparency(); - - // Enable or disable background grid - void setGridEnabled(bool enable); - bool gridEnabled(); - - // Enable or disable background mesh - void setBackgroundEnabled(bool enable); - bool backgroundEnabled(); - - // Adjust shadow quality - void setShadowQuality(ShadowQuality quality); - ShadowQuality shadowQuality(); - -#if defined(Q_OS_ANDROID) - void mouseDoubleClickEvent(QMouseEvent *event); - void touchEvent(QTouchEvent *event); -#endif - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void wheelEvent(QWheelEvent *event); - void resizeNotify(); - - void loadBarMesh(); - void loadBackgroundMesh(); - void loadGridLineMesh(); - void loadLabelMesh(); - void initShaders(const QString &vertexShader, const QString &fragmentShader); - void initSelectionShader(); - void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); - void initLabelShaders(const QString &vertexShader, const QString &fragmentShader); - void initSelectionBuffer(); -#if !defined(QT_OPENGL_ES_2) - void initDepthShader(); - void initDepthBuffer(); -#endif - void updateTextures(); - void calculateSceneScalingFactors(); - void calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits); - SelectionType isSelected(GLint row, GLint bar, const QVector3D &selection); - void handleLimitChange(); - void closeZoomMode(); - -private: - void drawZoomScene(); - void drawScene(); - Q_DISABLE_COPY(Bars3dShared) - - friend class DeclarativeBars; - friend class DeclarativeBarsRenderer; -}; - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/drawer.cpp b/src/datavis3d/engine/drawer.cpp index 3c4d30cf..5d524963 100644 --- a/src/datavis3d/engine/drawer.cpp +++ b/src/datavis3d/engine/drawer.cpp @@ -1,51 +1,28 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ -#include "qdatavis3namespace.h" +#include "qdatavis3denums.h" #include "drawer_p.h" #include "shaderhelper_p.h" #include "objecthelper_p.h" +#include "abstractobjecthelper_p.h" +#include "surfaceobject_p.h" #include "camerahelper_p.h" -#include "qdataitem.h" -#include "qdataitem_p.h" #include "utils_p.h" #include "texturehelper_p.h" #include <QMatrix4x4> @@ -62,9 +39,9 @@ public: }; StaticLibInitializer staticLibInitializer; -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE -Drawer::Drawer(const Theme &theme, const QFont &font, LabelTransparency transparency) +Drawer::Drawer(const Theme &theme, const QFont &font, QDataVis::LabelTransparency transparency) : m_theme(theme), m_font(font), m_transparency(transparency), @@ -96,15 +73,21 @@ void Drawer::setFont(const QFont &font) emit drawerChanged(); } -void Drawer::setTransparency(LabelTransparency transparency) +void Drawer::setTransparency(QDataVis::LabelTransparency transparency) { m_transparency = transparency; emit drawerChanged(); } -void Drawer::drawObject(ShaderHelper *shader, ObjectHelper *object, GLuint textureId, +void Drawer::drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLuint textureId, GLuint depthTextureId) { + // Store the GL state before changing + GLint oldActiveTex[1]; + glGetIntegerv(GL_ACTIVE_TEXTURE, oldActiveTex); + GLint oldTexId[1]; + glGetIntegerv(GL_TEXTURE_BINDING_2D, oldTexId); + if (textureId) { // Activate texture glActiveTexture(GL_TEXTURE0); @@ -140,29 +123,63 @@ void Drawer::drawObject(ShaderHelper *shader, ObjectHelper *object, GLuint textu glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object->elementBuf()); // Draw the triangles - glDrawElements(GL_TRIANGLES, object->indexCount(), GL_UNSIGNED_SHORT, (void*)0); + glDrawElements(GL_TRIANGLES, object->indexCount(), object->indicesType(), (void*)0); // Free buffers glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - if (textureId || depthTextureId) { - glBindTexture(GL_TEXTURE_2D, 0); + if (textureId || depthTextureId) glDisableVertexAttribArray(shader->uvAtt()); - } + glDisableVertexAttribArray(shader->normalAtt()); glDisableVertexAttribArray(shader->posAtt()); + + // Restore the GL state + glActiveTexture(*oldActiveTex); + glBindTexture(GL_TEXTURE_2D, *oldTexId); } -void Drawer::drawLabel(const QDataItem &item, const LabelItem &label, +void Drawer::drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object) +{ + // Store the GL state before changing + GLint oldActiveTex[1]; + glGetIntegerv(GL_ACTIVE_TEXTURE, oldActiveTex); + GLint oldTexId[1]; + glGetIntegerv(GL_TEXTURE_BINDING_2D, oldTexId); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(shader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, object->vertexBuf()); + glVertexAttribPointer(shader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object->gridElementBuf()); + + // Draw the lines + glDrawElements(GL_LINES, object->gridIndexCount(), object->indicesType(), (void*)0); + + // Free buffers + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(shader->posAtt()); + + // Restore the GL state + glActiveTexture(*oldActiveTex); + glBindTexture(GL_TEXTURE_2D, *oldTexId); +} + +void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelItem, const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix, const QVector3D &positionComp, const QVector3D &rotation, - GLfloat maxHeight, SelectionMode mode, - ShaderHelper *shader, ObjectHelper *object, bool useDepth, bool rotateAlong, + GLfloat itemHeight, QDataVis::SelectionMode mode, + ShaderHelper *shader, ObjectHelper *object, + CameraHelper *camera, + bool useDepth, bool rotateAlong, LabelPosition position, Qt::AlignmentFlag alignment) { // Draw label - LabelItem labelItem = label; if (!labelItem.textureId()) return; // No texture, skip @@ -184,20 +201,20 @@ void Drawer::drawLabel(const QDataItem &item, const LabelItem &label, } case LabelMid: { // Use this for positioning with absolute item y position value - yPosition = item.d_ptr->translation().y(); + yPosition = item.translation().y(); break; } case LabelHigh: { // TODO: Fix this. Can't seem to get it right (if ok with positive-only bars, doesn't look good on +- and vice versa) - yPosition = item.d_ptr->translation().y() + (item.d_ptr->value() / maxHeight) / 2.0f; + yPosition = item.translation().y() + itemHeight / 2.0f; break; } case LabelOver: { float mod = 0.1f; - if (item.d_ptr->value() < 0) + if (itemHeight < 0) mod = -0.1f; - yPosition = item.d_ptr->translation().y() - (positionComp.y() / 2.0f - 0.2f) - + (item.d_ptr->value() / maxHeight) + mod; + yPosition = item.translation().y() - (positionComp.y() / 2.0f - 0.2f) + + itemHeight + mod; break; } case LabelBottom: { @@ -232,16 +249,16 @@ void Drawer::drawLabel(const QDataItem &item, const LabelItem &label, switch (alignment) { case Qt::AlignLeft: { xAlignment = (-(GLfloat)textureSize.width() * scaleFactor) - * qFabs(cos(rotation.y() * m_pi / 180.0f)); + * qFabs(qCos(qDegreesToRadians(rotation.y()))); zAlignment = ((GLfloat)textureSize.width() * scaleFactor) - * qFabs(sin(rotation.y() * m_pi / 180.0f)); + * qFabs(qSin(qDegreesToRadians(rotation.y()))); break; } case Qt::AlignRight: { xAlignment = ((GLfloat)textureSize.width() * scaleFactor) - * qFabs(cos(rotation.y() * m_pi / 180.0f)); + * qFabs(qCos(qDegreesToRadians(rotation.y()))); zAlignment = (-(GLfloat)textureSize.width() * scaleFactor) - * qFabs(sin(rotation.y() * m_pi / 180.0f)); + * qFabs(qSin(qDegreesToRadians(rotation.y()))); break; } default: { @@ -250,24 +267,30 @@ void Drawer::drawLabel(const QDataItem &item, const LabelItem &label, } if (position < LabelBottom) { - xPosition = item.d_ptr->translation().x(); + xPosition = item.translation().x(); if (useDepth) - zPosition = item.d_ptr->translation().z(); - else if (ModeZoomColumn == mode) - xPosition = -(item.d_ptr->translation().z()) + positionComp.z(); // flip first to left + zPosition = item.translation().z(); + else if (QDataVis::ModeZoomColumn == mode) + xPosition = -(item.translation().z()) + positionComp.z(); // flip first to left } // Position label modelMatrix.translate(xPosition + xAlignment, yPosition, zPosition + zAlignment); // Rotate - modelMatrix.rotate(rotation.z(), 0.0f, 0.0f, 1.0f); + // TODO: We should convert rotations to use quaternions to avoid rotation order problems + //QQuaternion rotQuatX = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, rotation.x()); + //QQuaternion rotQuatY = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, rotation.y()); + //QQuaternion rotQuatZ = QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, rotation.z()); + //QQuaternion rotQuaternion = rotQuatX + rotQuatY + rotQuatZ; + //modelMatrix.rotate(rotQuaternion); modelMatrix.rotate(rotation.y(), 0.0f, 1.0f, 0.0f); + modelMatrix.rotate(rotation.z(), 0.0f, 0.0f, 1.0f); modelMatrix.rotate(rotation.x(), 1.0f, 0.0f, 0.0f); if (useDepth && !rotateAlong) { // Apply negative camera rotations to keep labels facing camera - QPointF camRotations = CameraHelper::getCameraRotations(); + QPointF camRotations = camera->getCameraRotations(); modelMatrix.rotate(-camRotations.x(), 0.0f, 1.0f, 0.0f); modelMatrix.rotate(-camRotations.y(), 1.0f, 0.0f, 0.0f); } @@ -286,21 +309,17 @@ void Drawer::drawLabel(const QDataItem &item, const LabelItem &label, drawObject(shader, object, labelItem.textureId()); } -void Drawer::generateLabelTexture(QDataItem *item) +void Drawer::generateLabelTexture(AbstractRenderItem *item) { - LabelItem labelItem = item->d_ptr->label(); - generateLabelItem(&labelItem, item->d_ptr->valueStr()); - item->d_ptr->setLabel(labelItem); + LabelItem &labelItem = item->labelItem(); + generateLabelItem(labelItem, item->label()); } -void Drawer::generateLabelItem(LabelItem *item, const QString &text) +void Drawer::generateLabelItem(LabelItem &item, const QString &text) { initializeOpenGL(); - // Delete previous texture, if there is one - GLuint labelTexture = item->textureId(); - if (labelTexture) - glDeleteTextures(1, &labelTexture); + item.clear(); // Create labels // Print label into a QImage using QPainter @@ -311,9 +330,9 @@ void Drawer::generateLabelItem(LabelItem *item, const QString &text) m_transparency); // Set label size - item->setSize(label.size()); - // Insert text texture into label - item->setTextureId(m_textureHelper->create2DTexture(label, true, true)); + item.setSize(label.size()); + // Insert text texture into label (also deletes the old texture) + item.setTextureId(m_textureHelper->create2DTexture(label, true, true)); } -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/drawer_p.h b/src/datavis3d/engine/drawer_p.h index e31ab0cb..3139fbe0 100644 --- a/src/datavis3d/engine/drawer_p.h +++ b/src/datavis3d/engine/drawer_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,46 +29,63 @@ #ifndef DRAWER_P_H #define DRAWER_P_H -#include "QtDataVis3D/qdatavis3dglobal.h" -#include "QtDataVis3D/qdatavis3namespace.h" +#include "datavis3dglobal_p.h" #include "q3dbars.h" #include "theme_p.h" #include "labelitem_p.h" +#include "abstractrenderitem_p.h" #include <QFont> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE -class QDataItem; class ShaderHelper; class ObjectHelper; +class AbstractObjectHelper; +class SurfaceObject; class TextureHelper; +class CameraHelper; class Drawer : public QObject, public QOpenGLFunctions { Q_OBJECT public: - explicit Drawer(const Theme &theme, const QFont &font, LabelTransparency transparency); + enum LabelPosition { + LabelBelow = 0, + LabelLow, + LabelMid, + LabelHigh, + LabelOver, + LabelBottom, // Absolute positions from here onward, used for axes (QDataItem is ignored) + LabelTop, + LabelLeft, + LabelRight + }; + +public: + explicit Drawer(const Theme &theme, const QFont &font, QDataVis::LabelTransparency transparency); ~Drawer(); void initializeOpenGL(); void setTheme(const Theme &theme); void setFont(const QFont &font); - void setTransparency(LabelTransparency transparency); + void setTransparency(QDataVis::LabelTransparency transparency); - void drawObject(ShaderHelper *shader, ObjectHelper *object, GLuint textureId = 0, + void drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLuint textureId = 0, GLuint depthTextureId = 0); - void drawLabel(const QDataItem &item, const LabelItem &label, + void drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object); + void drawLabel(const AbstractRenderItem &item, const LabelItem &labelItem, const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix, - const QVector3D &positionComp, const QVector3D &rotation, GLfloat maxHeight, - SelectionMode mode, ShaderHelper *shader, ObjectHelper *object, + const QVector3D &positionComp, const QVector3D &rotation, GLfloat itemHeight, + QDataVis::SelectionMode mode, ShaderHelper *shader, ObjectHelper *object, + CameraHelper *camera, bool useDepth = false, bool rotateAlong = false, LabelPosition position = LabelOver, Qt::AlignmentFlag alignment = Qt::AlignCenter); - void generateLabelTexture(QDataItem *item); - void generateLabelItem(LabelItem *item, const QString &text); + void generateLabelTexture(AbstractRenderItem *item); + void generateLabelItem(LabelItem &item, const QString &text); Q_SIGNALS: void drawerChanged(); @@ -99,10 +93,10 @@ Q_SIGNALS: private: Theme m_theme; QFont m_font; - LabelTransparency m_transparency; + QDataVis::LabelTransparency m_transparency; TextureHelper *m_textureHelper; }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/engine/engine.pri b/src/datavis3d/engine/engine.pri index b220120f..5dc415e1 100644 --- a/src/datavis3d/engine/engine.pri +++ b/src/datavis3d/engine/engine.pri @@ -1,29 +1,44 @@ -SOURCES += $$PWD/q3dwindow.cpp \ - $$PWD/q3dbars.cpp \ - $$PWD/q3dmaps.cpp \ - $$PWD/qdataitem.cpp \ - $$PWD/qdatarow.cpp \ - $$PWD/qdataset.cpp \ - $$PWD/theme.cpp \ - $$PWD/drawer.cpp \ - $$PWD/labelitem.cpp \ - $$PWD/bars3dshared.cpp - HEADERS += $$PWD/q3dwindow_p.h \ $$PWD/q3dwindow.h \ $$PWD/q3dbars.h \ $$PWD/q3dbars_p.h \ $$PWD/q3dmaps.h \ $$PWD/q3dmaps_p.h \ - $$PWD/qdataitem.h \ - $$PWD/qdataitem_p.h \ - $$PWD/qdatarow.h \ - $$PWD/qdatarow_p.h \ - $$PWD/qdataset.h \ - $$PWD/qdataset_p.h \ $$PWD/theme_p.h \ $$PWD/drawer_p.h \ - $$PWD/labelitem_p.h \ - $$PWD/bars3dshared_p.h + $$PWD/bars3dcontroller_p.h \ + $$PWD/bars3drenderer_p.h \ + $$PWD/maps3dcontroller_p.h \ + $$PWD/maps3drenderer_p.h \ + $$PWD/q3dsurface.h \ + $$PWD/q3dsurface_p.h \ + $$PWD/surface3dcontroller_p.h \ + $$PWD/surface3drenderer_p.h \ + $$PWD/abstract3dcontroller_p.h \ + $$PWD/q3dscatter.h \ + $$PWD/q3dscatter_p.h \ + $$PWD/scatter3dcontroller_p.h \ + $$PWD/scatter3drenderer_p.h \ + $$PWD/axisrendercache_p.h \ + $$PWD/abstract3drenderer_p.h + +SOURCES += $$PWD/q3dwindow.cpp \ + $$PWD/q3dbars.cpp \ + $$PWD/q3dmaps.cpp \ + $$PWD/theme.cpp \ + $$PWD/drawer.cpp \ + $$PWD/bars3dcontroller.cpp \ + $$PWD/bars3drenderer.cpp \ + $$PWD/maps3dcontroller.cpp \ + $$PWD/maps3drenderer.cpp \ + $$PWD/q3dsurface.cpp \ + $$PWD/surface3drenderer.cpp \ + $$PWD/surface3dcontroller.cpp \ + $$PWD/abstract3dcontroller.cpp \ + $$PWD/q3dscatter.cpp \ + $$PWD/scatter3dcontroller.cpp \ + $$PWD/scatter3drenderer.cpp \ + $$PWD/axisrendercache.cpp \ + $$PWD/abstract3drenderer.cpp RESOURCES += engine/engine.qrc diff --git a/src/datavis3d/engine/engine.qrc b/src/datavis3d/engine/engine.qrc index 2588197a..af6e899d 100644 --- a/src/datavis3d/engine/engine.qrc +++ b/src/datavis3d/engine/engine.qrc @@ -26,6 +26,8 @@ <file alias="bevelbarSmoothFull">meshes/barFilledSmooth.obj</file> <file alias="barFull">meshes/cubeFilledFlat.obj</file> <file alias="barSmoothFull">meshes/cubeFilledSmooth.obj</file> + <file alias="dotSmooth">meshes/scatterdot.obj</file> + <file alias="dot">meshes/scatterdotFlat.obj</file> </qresource> <qresource prefix="/shaders"> <file alias="fragment">shaders/default.frag</file> @@ -48,6 +50,12 @@ <file alias="fragmentES2">shaders/default_ES2.frag</file> <file alias="vertexES2">shaders/default_ES2.vert</file> <file alias="fragmentTextureES2">shaders/texture_ES2.frag</file> + <file alias="fragmentSurface">shaders/surface.frag</file> + <file alias="vertexSurface">shaders/surface.vert</file> + <file alias="fragmentSurfaceGrid">shaders/surfaceGrid.frag</file> + <file alias="vertexSurfaceGrid">shaders/surfaceGrid.vert</file> + <file alias="vertexSurfaceFlat">shaders/surfaceFlat.vert</file> + <file alias="fragmentSurfaceFlat">shaders/surfaceFlat.frag</file> </qresource> <qresource prefix="/textures"/> </RCC> diff --git a/src/datavis3d/engine/labelitem.cpp b/src/datavis3d/engine/labelitem.cpp deleted file mode 100644 index 19051dd7..00000000 --- a/src/datavis3d/engine/labelitem.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "labelitem_p.h" - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -LabelItem::LabelItem() - : m_size(QSize(0, 0)), - m_textureId(0) -{ -} - -LabelItem::~LabelItem() -{ -} - -void LabelItem::setSize(const QSize &size) -{ - m_size = size; -} - -QSize LabelItem::size() -{ - return m_size; -} - -void LabelItem::setTextureId(GLuint textureId) -{ - m_textureId = textureId; -} - -GLuint LabelItem::textureId() -{ - return m_textureId; -} - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/labelitem_p.h b/src/datavis3d/engine/labelitem_p.h deleted file mode 100644 index 47e480b2..00000000 --- a/src/datavis3d/engine/labelitem_p.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt 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 LABELITEM_P_H -#define LABELITEM_P_H - -#include "qdatavis3dglobal.h" -#include <QOpenGLFunctions> -#include <QSize> - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -class LabelItem -{ -public: - explicit LabelItem(); - ~LabelItem(); - - void setSize(const QSize &size); - QSize size(); - void setTextureId(GLuint textureId); - GLuint textureId(); - -private: - QSize m_size; - GLuint m_textureId; -}; - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/maps3dcontroller.cpp b/src/datavis3d/engine/maps3dcontroller.cpp new file mode 100644 index 00000000..e86bdfa2 --- /dev/null +++ b/src/datavis3d/engine/maps3dcontroller.cpp @@ -0,0 +1,1763 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "maps3dcontroller_p.h" +#include "maps3drenderer_p.h" +#include "camerahelper_p.h" +#include "shaderhelper_p.h" +#include "objecthelper_p.h" +#include "texturehelper_p.h" +#include "theme_p.h" +#include "utils_p.h" +#include "drawer_p.h" +#include "maprenderitem_p.h" +#include "qmapdataproxy_p.h" + +#include <QOpenGLFunctions> +#include <QMatrix4x4> +#include <QMouseEvent> +#include <qmath.h> + +#include <QDebug> + +//#define DISPLAY_RENDER_SPEED + +// Commenting this draws the shadow map with perspective projection. Otherwise it's drawn in +// orthographic projection. +//#define USE_WIDER_SHADOWS + +// You can verify that depth buffer drawing works correctly by uncommenting this. +// You should see the scene from where the light is +//#define SHOW_DEPTH_TEXTURE_SCENE + +#ifdef DISPLAY_RENDER_SPEED +#include <QTime> +#endif + +QT_DATAVIS3D_BEGIN_NAMESPACE + +//#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels + +const GLfloat gridLineWidth = 0.005f; +GLfloat distanceMod = 0.0f; +static QVector3D skipColor = QVector3D(255, 255, 255); // Selection texture's background color + +Maps3DController::Maps3DController(const QRect &rect) + : m_camera(new CameraHelper()), + m_barShader(0), + m_depthShader(0), + m_selectionShader(0), + m_backgroundShader(0), + m_labelShader(0), + m_barObj(0), + m_backgroundObj(0), + m_gridLineObj(0), + m_labelObj(0), + m_objFile(QStringLiteral(":/defaultMeshes/bar")), + m_mousePressed(MouseNone), + m_mousePos(QPoint(0, 0)), + m_zoomLevel(100), + m_autoScaleAdjustment(1.0f), + m_horizontalRotation(0.0f), + m_verticalRotation(45.0f), + m_barThickness(QVector3D(1.0f, 1.0f, 1.0f)), + m_heightNormalizer(0.0f), + m_yAdjustment(0.0f), + m_scaleFactor(1.0f), + m_theme(new Theme()), + m_isInitialized(false), + m_selectionMode(QDataVis::ModeItem), + m_selectedBar(0), + m_previouslySelectedBar(0), + m_axisLabelX(QStringLiteral("X")), + m_axisLabelZ(QStringLiteral("Z")), + m_axisLabelY(QStringLiteral("Y")), + m_sceneViewPort(rect.x(), rect.y(), rect.width(), rect.height()), + m_zoomViewPort(rect.x(), rect.y(), rect.width(), rect.height()), + m_zoomActivated(false), + m_textureHelper(new TextureHelper()), + m_labelTransparency(QDataVis::TransparencyFromTheme), + m_font(QFont(QStringLiteral("Arial"))), + m_drawer(new Drawer(*m_theme, m_font, m_labelTransparency)), + m_areaSize(QSizeF(1.0f, 1.0f)), + m_bgrTexture(0), + m_depthTexture(0), + m_selectionTexture(0), + m_depthFrameBuffer(0), + m_selectionFrameBuffer(0), + m_selectionDepthBuffer(0), + m_updateLabels(true), + m_adjustDirection(Q3DMaps::AdjustHeight), + m_shadowQuality(QDataVis::ShadowLow), + m_shadowQualityToShader(33.3f), + m_bgrHasAlpha(false), + m_boundingRect(rect.x(), rect.y(), rect.width(), rect.height()), + m_data(0), + m_valuesDirty(false) +{ + //m_data->setDrawer(m_drawer); + //QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Maps3DController::updateTextures); +} + +Maps3DController::~Maps3DController() +{ + m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); + m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); + m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); + m_textureHelper->deleteTexture(&m_selectionTexture); + m_textureHelper->deleteTexture(&m_bgrTexture); + delete m_barShader; + delete m_selectionShader; + delete m_backgroundShader; + delete m_barObj; + delete m_backgroundObj; + delete m_gridLineObj; + delete m_textureHelper; + delete m_drawer; + delete m_camera; +} + +void Maps3DController::initializeOpenGL() +{ + // Initialization is called multiple times when Qt Quick components are used + if (m_isInitialized) + return; + + m_renderer = new Maps3DRenderer(this); + initializeOpenGLFunctions(); + + m_textureHelper = new TextureHelper(); + m_drawer->initializeOpenGL(); + + // Initialize shaders +#if !defined(QT_OPENGL_ES_2) + if (m_shadowQuality > QDataVis::ShadowNone) { + if (!m_theme->m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadow")); + } else { + if (!m_theme->m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), + QStringLiteral(":/shaders/fragmentTexture")); + } +#else + if (!m_theme->m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentColorOnYES2")); + } else { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), // Same vertex shader ok for ES2 + QStringLiteral(":/shaders/fragmentTextureES2")); +#endif + initLabelShaders(QStringLiteral(":/shaders/vertexLabel"), + QStringLiteral(":/shaders/fragmentLabel")); + +#if !defined(QT_OPENGL_ES_2) + // Init depth shader (for shadows). Init in any case, easier to handle shadow activation if done via api. + initDepthShader(); +#endif + + // Init selection shader + initSelectionShader(); + + // Load default mesh + loadBarMesh(); + + // Load grid line mesh + loadGridLineMesh(); + + // Load label mesh + loadLabelMesh(); + + // Set OpenGL features + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + +#if !defined(QT_OPENGL_ES_2) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); +#endif + + // Set initial camera position + // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later + m_camera->setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 1.0f + 2.9f * zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + + // Adjust to default rotation + setCameraPosition(m_horizontalRotation, m_verticalRotation, m_zoomLevel); + + // Set view port + glViewport(0, 0, width(), height()); + + // Set initialized -flag + m_isInitialized = true; + + // Resize in case we've missed resize events + // Resize calls initSelectionBuffer and initDepthBuffer, so they don't need to be called here + resizeNotify(); + + // Load background mesh (we need to be initialized first) + loadBackgroundMesh(); + + // Update default light position +#ifndef USE_WIDER_SHADOWS + distanceMod = 5.0f; +#endif +} + +void Maps3DController::synchDataToRenderer() +{ + // TODO: Implement! +} + + +/*! + * \internal + */ +void Maps3DController::render(const GLuint defaultFboHandle) +{ + if (!m_isInitialized) + return; + +#ifdef DISPLAY_RENDER_SPEED + // For speed computation + static bool firstRender = true; + static QTime lastTime; + static GLint nbFrames = 0; + if (firstRender) { + lastTime.start(); + firstRender = false; + } + + // Measure speed (as milliseconds per frame) + nbFrames++; + if (lastTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago + qDebug() << qreal(lastTime.elapsed()) / qreal(nbFrames) << "ms/frame (=" << qreal(nbFrames) << "fps)"; + nbFrames = 0; + lastTime.restart(); + } +#endif + + // Update cached values + if (m_valuesDirty) { + const QMapDataArray &dataArray = *m_data->array(); + int dataSize = dataArray.size(); + m_renderItemArray.resize(dataSize); + for (int i = 0; i < dataSize ; i++) { + qreal value = dataArray.at(i).value(); + m_renderItemArray[i].setValue(value); + m_renderItemArray[i].setMapPosition(dataArray.at(i).mapPosition()); + m_renderItemArray[i].setHeight(value / m_heightNormalizer); + m_renderItemArray[i].setItemLabel(dataArray.at(i).label()); + calculateTranslation(m_renderItemArray[i]); + m_renderItemArray[i].setRenderer(this); + } + m_valuesDirty = false; + } + + if (defaultFboHandle) { + glDepthMask(true); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + } + + // Draw scene + drawScene(defaultFboHandle); +} + +/*! + * \internal + */ +void Maps3DController::drawScene(const GLuint defaultFboHandle) +{ + // Set clear color + QVector3D clearColor = Utils::vectorFromColor(m_theme->m_windowColor); + glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + static QVector3D selection = skipColor; + + // Specify viewport + glViewport(m_sceneViewPort.x(), m_sceneViewPort.y(), + m_sceneViewPort.width(), m_sceneViewPort.height()); + + // Set up projection matrix + QMatrix4x4 projectionMatrix; + projectionMatrix.perspective(45.0f, (GLfloat)m_sceneViewPort.width() + / (GLfloat)m_sceneViewPort.height(), 0.1f, 100.0f); + + // Calculate view matrix + QMatrix4x4 viewMatrix = m_camera->calculateViewMatrix(m_mousePos, + m_zoomLevel * m_autoScaleAdjustment, + m_sceneViewPort.width(), + m_sceneViewPort.height()); + + // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) + QVector3D lightPos = m_camera->calculateLightPosition(defaultLightPos, 0.0f, distanceMod); + + // Map adjustment direction to model matrix scaling + GLfloat heightMultiplier = 0.0f; + GLfloat widthMultiplier = 0.0f; + GLfloat depthMultiplier = 0.0f; + GLfloat heightScaler = 0.0f; + GLfloat widthScaler = 0.0f; + GLfloat depthScaler = 0.0f; + switch (m_adjustDirection) { + case Q3DMaps::AdjustHeight: + widthMultiplier = 0.0f; + heightMultiplier = 1.0f; + depthMultiplier = 0.0f; + widthScaler = m_barThickness.x() / m_scaleFactor; + heightScaler = 0.0f; + depthScaler = m_barThickness.z() / m_scaleFactor; + break; + case Q3DMaps::AdjustWidth: + widthMultiplier = 1.0f; + heightMultiplier = 0.0f; + depthMultiplier = 0.0f; + widthScaler = 0.0f; + heightScaler = m_barThickness.y() / m_scaleFactor; + depthScaler = m_barThickness.z() / m_scaleFactor; + break; + case Q3DMaps::AdjustDepth: + widthMultiplier = 0.0f; + heightMultiplier = 0.0f; + depthMultiplier = 1.0f; + widthScaler = m_barThickness.x() / m_scaleFactor; + heightScaler = m_barThickness.y() / m_scaleFactor; + depthScaler = 0.0f; + break; + case Q3DMaps::AdjustRadius: + widthMultiplier = 1.0f; + heightMultiplier = 0.0f; + depthMultiplier = 1.0f; + widthScaler = 0.0f; + heightScaler = m_barThickness.y() / m_scaleFactor; + depthScaler = 0.0f; + break; + case Q3DMaps::AdjustAll: + widthMultiplier = 1.0f; + heightMultiplier = 1.0f; + depthMultiplier = 1.0f; + widthScaler = 0.0f; + heightScaler = 0.0f; + depthScaler = 0.0f; + break; + } + + // Introduce regardless of shadow quality to simplify logic + QMatrix4x4 depthViewMatrix; + QMatrix4x4 depthProjectionMatrix; + +#if !defined(QT_OPENGL_ES_2) + if (m_shadowQuality > QDataVis::ShadowNone) { + // Render scene into a depth texture for using with shadow mapping + // Bind depth shader + m_depthShader->bind(); + + // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. + glViewport(m_sceneViewPort.x(), m_sceneViewPort.y(), + m_sceneViewPort.width() * m_shadowQuality, + m_sceneViewPort.height() * m_shadowQuality); + + // Enable drawing to framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); + glClear(GL_DEPTH_BUFFER_BIT); + + // Set front face culling to reduce self-shadowing issues + glCullFace(GL_FRONT); + + // Get the depth view matrix + // It may be possible to hack lightPos here if we want to make some tweaks to shadow + QVector3D depthLightPos = m_camera->calculateLightPosition( + defaultLightPos, 0.0f, (distanceMod + 1.5f) / m_autoScaleAdjustment); + depthViewMatrix.lookAt(depthLightPos, QVector3D(0.0f, -m_yAdjustment, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed + //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); + // Set the depth projection matrix +#ifndef USE_WIDER_SHADOWS + // Use this for perspective shadows + depthProjectionMatrix.perspective(15.0f, (GLfloat)m_sceneViewPort.width() + / (GLfloat)m_sceneViewPort.height(), 3.0f, 200.0f); +#else + // Use these for orthographic shadows + //qDebug() << m_areaSize.width() / m_scaleFactor << m_yAdjustment; + GLfloat testAspectRatio = (GLfloat)m_sceneViewPort.width() / (GLfloat)m_sceneViewPort.height(); + depthProjectionMatrix.ortho(-(2.0f * m_areaSize.width()) / m_scaleFactor, + (2.0f * m_areaSize.width()) / m_scaleFactor, + -m_yAdjustment * 4.0f * testAspectRatio, + m_yAdjustment * 4.0f * testAspectRatio, + 0.0f, 100.0f); +#endif +#if 0 + // Draw background to depth buffer (You don't want to do this, except maybe for debugging purposes) + if (m_backgroundObj) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(0.0f, -m_yAdjustment, zComp); + modelMatrix.scale(QVector3D(m_areaSize.width() / m_scaleFactor, + 1.0f, + m_areaSize.height() / m_scaleFactor)); + modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f); + + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_backgroundObj->vertexBuf()); + glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_backgroundObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, m_backgroundObj->indexCount(), GL_UNSIGNED_SHORT, + (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(m_depthShader->posAtt()); + } +#endif + // Draw bars to depth buffer + for (int bar = 0; bar < m_renderItemArray.size(); bar++) { + const MapRenderItem &item = m_renderItemArray.at(bar); + if (!item.value()) + continue; + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(item.translation().x(), + heightMultiplier * item.height() + heightScaler - m_yAdjustment, + item.translation().z()); + modelMatrix.scale(QVector3D(widthMultiplier * item.height() + widthScaler, + heightMultiplier * item.height() + heightScaler, + depthMultiplier * item.height() + depthScaler)); + + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf()); + glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(m_depthShader->posAtt()); + } + + // Disable drawing to framebuffer (= enable drawing to screen) + glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); + + // Reset culling to normal + glCullFace(GL_BACK); + + // Release depth shader + m_depthShader->release(); + + // Revert to original viewport + glViewport(m_sceneViewPort.x(), m_sceneViewPort.y(), + m_sceneViewPort.width(), m_sceneViewPort.height()); + +#if 0 // Use this if you want to see what is being drawn to the framebuffer + // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it) + m_labelShader->bind(); + glEnable(GL_TEXTURE_2D); + QMatrix4x4 modelMatrix; + QMatrix4x4 viewmatrix; + viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.5f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + modelMatrix.translate(0.0, 0.0, zComp); + QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; + m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); + m_drawer->drawObject(m_labelShader, m_labelObj, + m_depthTexture); + glDisable(GL_TEXTURE_2D); + m_labelShader->release(); +#endif + } +#endif + +#if 1 + // Skip selection mode drawing if we're zoomed or have no selection mode + if (!m_zoomActivated && m_selectionMode > QDataVis::ModeNone) { + // Bind selection shader + m_selectionShader->bind(); + + // Draw bars to selection buffer + glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); + glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used + glClearColor(skipColor.x() / 255, skipColor.y() / 255, skipColor.z() / 255, 1.0f); // Set clear color to white (= skipColor) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer + glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled + GLint barIdxRed = 0; + GLint barIdxGreen = 0; + GLint barIdxBlue = 0; + for (int bar = 0; bar < m_renderItemArray.size(); bar++, barIdxRed++) { + const MapRenderItem &item = m_renderItemArray.at(bar); + if (!item.value()) + continue; + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(item.translation().x(), + heightMultiplier * item.height() + heightScaler - m_yAdjustment, + item.translation().z()); + modelMatrix.scale(QVector3D(widthMultiplier * item.height() + widthScaler, + heightMultiplier * item.height() + heightScaler, + depthMultiplier * item.height() + depthScaler)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + + if (barIdxRed > 0 && barIdxRed % 256 == 0) { + barIdxRed = 0; + barIdxGreen++; + } + if (barIdxGreen > 0 && barIdxGreen % 256 == 0) { + barIdxGreen = 0; + barIdxBlue++; + } + if (barIdxBlue > 255) + qFatal("Too many objects"); + + QVector3D barColor = QVector3D((GLfloat)barIdxRed / 255.0f, + (GLfloat)barIdxGreen / 255.0f, + (GLfloat)barIdxBlue / 255.0f); + + m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); + m_selectionShader->setUniformValue(m_selectionShader->color(), barColor); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_selectionShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf()); + glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(m_selectionShader->posAtt()); + } + glEnable(GL_DITHER); + + // Read color under cursor + if (Maps3DController::MouseOnScene == m_mousePressed) + selection = Utils::getSelection(m_mousePos, height()); + + glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); + + // Release selection shader + m_selectionShader->release(); + +#if 0 // Use this if you want to see what is being drawn to the framebuffer + m_labelShader->bind(); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + QMatrix4x4 modelMatrix; + QMatrix4x4 viewmatrix; + viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + modelMatrix.translate(0.0, 0.0, zComp); + QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; + m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); + m_drawer->drawObject(m_labelShader, m_labelObj, + m_selectionTexture); + glDisable(GL_TEXTURE_2D); + m_labelShader->release(); +#endif + } +#if 1 + // Bind bar shader + m_barShader->bind(); + + // Enable texture + glEnable(GL_TEXTURE_2D); + + // Draw bars + // TODO: Handle zoom by camera transformations + //if (!m_zoomActivated) + + bool barSelectionFound = false; + for (int bar = 0; bar < m_renderItemArray.size(); bar++) { + MapRenderItem &item = m_renderItemArray[bar]; + if (!item.value()) + continue; + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(item.translation().x(), + heightMultiplier * item.height() + heightScaler - m_yAdjustment, + item.translation().z()); + modelMatrix.scale(QVector3D(widthMultiplier * item.height() + widthScaler, + heightMultiplier * item.height() + heightScaler, + depthMultiplier * item.height() + depthScaler)); + itModelMatrix.scale(QVector3D(widthMultiplier * item.height() + widthScaler, + heightMultiplier * item.height() + heightScaler, + depthMultiplier * item.height() + depthScaler)); + +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + QVector3D baseColor = Utils::vectorFromColor(m_theme->m_baseColor); + QVector3D heightColor = Utils::vectorFromColor(m_theme->m_heightColor) * item.height(); + + QVector3D barColor = baseColor + heightColor; + + GLfloat lightStrength = m_theme->m_lightStrength; + if (m_selectionMode > QDataVis::ModeNone) { + Maps3DController::SelectionType selectionType = isSelected(bar, selection); + switch (selectionType) { + case Maps3DController::SelectionBar: { + barColor = Utils::vectorFromColor(m_theme->m_highlightBarColor); + lightStrength = m_theme->m_highlightLightStrength; + // Insert data to QDataItem. We have no ownership, don't delete the previous one + if (!m_zoomActivated) { + m_selectedBar = &item; + barSelectionFound = true; + } + break; + } + case Maps3DController::SelectionNone: { + // Current bar is not selected, nor on a row or column + // do nothing + break; + } + default: { + // Unsupported selection mode + // do nothing + break; + } + } + } + + if (item.height() != 0) { + // Set shader bindings + m_barShader->setUniformValue(m_barShader->lightP(), lightPos); + m_barShader->setUniformValue(m_barShader->view(), viewMatrix); + m_barShader->setUniformValue(m_barShader->model(), modelMatrix); + m_barShader->setUniformValue(m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + m_barShader->setUniformValue(m_barShader->color(), barColor); + m_barShader->setUniformValue(m_barShader->ambientS(), m_theme->m_ambientStrength); + +#if !defined(QT_OPENGL_ES_2) + if (m_shadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); + m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); + m_barShader->setUniformValue(m_barShader->lightS(), lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_barShader, m_barObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_barShader->setUniformValue(m_barShader->lightS(), lightStrength); + + // Draw the object + m_drawer->drawObject(m_barShader, m_barObj); + } + } + } + + // Release bar shader + m_barShader->release(); +#if 1 + // Bind background shader + m_backgroundShader->bind(); + if (m_bgrHasAlpha) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + // Draw background + if (m_backgroundObj) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(0.0f, -m_yAdjustment, zComp); + modelMatrix.scale(QVector3D(m_areaSize.width() / m_scaleFactor, + 1.0f, + m_areaSize.height() / m_scaleFactor)); + modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f); + itModelMatrix.scale(QVector3D(m_areaSize.width() / m_scaleFactor, + 1.0f, + m_areaSize.height() / m_scaleFactor)); + +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos); + m_backgroundShader->setUniformValue(m_backgroundShader->view(), viewMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->model(), modelMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->nModel(), + itModelMatrix.inverted().transposed()); + m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(), + m_theme->m_ambientStrength * 3.0f); + +#if !defined(QT_OPENGL_ES_2) + if (m_shadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), + m_shadowQualityToShader); + m_backgroundShader->setUniformValue(m_backgroundShader->depth(), + depthMVPMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), + m_theme->m_lightStrength / 25.0f); + + // Draw the object + m_drawer->drawObject(m_backgroundShader, m_backgroundObj, m_bgrTexture, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), + m_theme->m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_backgroundShader, m_backgroundObj, m_bgrTexture); + } + } + + // Disable textures + glDisable(GL_TEXTURE_2D); + if (m_bgrHasAlpha) + glDisable(GL_BLEND); + + // Release background shader + m_backgroundShader->release(); +#endif + + // Handle zoom activation and label drawing + if (!barSelectionFound) { + // We have no ownership, don't delete. Just NULL the pointer. + m_selectedBar = NULL; + //if (m_zoomActivated && Maps3DController::MouseOnOverview == m_mousePressed) { + //m_sceneViewPort = QRect(0, 0, width(), height()); + //m_zoomActivated = false; + //} + } /*else if (m_selectionMode >= ModeZoomRow + && Maps3DController::MouseOnScene == m_mousePressed) { + // Activate zoom mode + m_zoomActivated = true; + m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5); + + // Create label textures + for (int col = 0; col < m_zoomSelection->row().size(); col++) { + QDataItem *item = m_zoomSelection->getItem(col); + m_drawer->generateLabelTexture(item); + } + }*/ else { + // Print value of selected bar + m_labelShader->bind(); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + if (m_labelTransparency > QDataVis::TransparencyNone) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } +#ifndef DISPLAY_FULL_DATA_ON_SELECTION + // Draw just the value string of the selected bar + if (m_previouslySelectedBar != m_selectedBar || m_updateLabels) { + m_drawer->generateLabelTexture(m_selectedBar); + m_previouslySelectedBar = m_selectedBar; + } + + m_drawer->drawLabel(*m_selectedBar, m_selectedBar->labelItem(), + viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), + m_selectionMode, m_labelShader, + m_labelObj, m_camera, true); +#else + // Draw the value string followed by row label and column label + LabelItem &labelItem = m_selectedBar->selectionLabel(); + if (m_previouslySelectedBar != m_selectedBar || m_updateLabels || !labelItem.textureId()) { + QString labelText = m_selectedBar->label(); + // TODO More elaborate label? + m_drawer->generateLabelItem(&labelItem, labelText); + m_previouslySelectedBar = m_selectedBar; + } + + m_drawer->drawLabel(*m_selectedBar, labelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), + m_selectionMode, m_labelShader, + m_labelObj, true, false); +#endif + glDisable(GL_TEXTURE_2D); + if (m_labelTransparency > QDataVis::TransparencyNone) + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + + // Release label shader + m_labelShader->release(); + + // Reset label update flag; they should have been updated when we get here + m_updateLabels = false; + } +#if 0 + // TODO: Calculations done temporarily here. When optimizing, move to after data set addition? Keep drawing of the labels here. + // Bind label shader + m_labelShader->bind(); + + glEnable(GL_TEXTURE_2D); + if (m_labelTransparency > TransparencyNone) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + // Calculate the positions for row and column labels and store them into QDataItems (and QDataRows?) + for (int row = 0; row != m_sampleCount.second; row += 1) { + // Go through all rows and get position of max+1 or min-1 column, depending on x flip + // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems + rowPos = (row + 1) * (m_barSpacing.height()); + barPos = 0; + GLfloat rotLabelX = -90.0f; + GLfloat rotLabelY = 0.0f; + Qt::AlignmentFlag alignment = Qt::AlignRight; + if (m_zFlipped) + rotLabelY = 180.0f; + if (m_xFlipped) { + barPos = (m_sampleCount.first + 1) * (m_barSpacing.width()); + alignment = Qt::AlignLeft; + } + QVector3D labelPos = QVector3D((m_rowWidth - barPos) / m_scaleFactor, + -m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" + (m_columnDepth - rowPos) / m_scaleFactor + zComp); + + // TODO: Try it; draw the label here + + // Create a data item + QDataItem *label = new QDataItem(); + label->setTranslation(labelPos); + if (m_data->d_ptr->rowLabelItems().size() > row) { + label->setLabel(m_data->d_ptr->rowLabelItems().at(m_data->d_ptr->rowLabelItems().size() + - row - 1)); + } + + //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << m_dataSet->rowLabels().at(row); + + m_drawer->drawLabel(*label, label->label(), viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(rotLabelX, rotLabelY, 0.0f), m_heightNormalizer, + m_selectionMode, m_labelShader, + m_labelObj, true, true, Drawer::LabelMid, alignment); + + delete label; + } + for (int bar = 0; bar != m_sampleCount.first; bar += 1) { + // Go through all columns and get position of max+1 or min-1 row, depending on z flip + // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems + barPos = (bar + 1) * (m_barSpacing.width()); + rowPos = 0; + GLfloat rotLabelX = -90.0f; + GLfloat rotLabelY = 90.0f; + Qt::AlignmentFlag alignment = Qt::AlignLeft; + if (m_xFlipped) + rotLabelY = -90.0f; + if (m_zFlipped) { + rowPos = (m_sampleCount.second + 1) * (m_barSpacing.height()); + alignment = Qt::AlignRight; + } + QVector3D labelPos = QVector3D((m_rowWidth - barPos) / m_scaleFactor, + -m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" + (m_columnDepth - rowPos) / m_scaleFactor + zComp); + + // TODO: Try it; draw the label here + + // Create a data item + QDataItem *label = new QDataItem(); + label->setTranslation(labelPos); + if (m_data->d_ptr->columnLabelItems().size() > bar) { + label->setLabel(m_data->d_ptr->columnLabelItems().at( + m_data->d_ptr->columnLabelItems().size() - bar - 1)); + } + + //qDebug() << "labelPos, col" << bar + 1 << ":" << labelPos << m_dataSet->columnLabels().at(bar); + + m_drawer->drawLabel(*label, label->label(), viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(rotLabelX, rotLabelY, 0.0f), m_heightNormalizer, + m_selectionMode, m_labelShader, + m_labelObj, true, true, Drawer::LabelMid, alignment); + + delete label; + } + glDisable(GL_TEXTURE_2D); + if (m_labelTransparency > TransparencyNone) + glDisable(GL_BLEND); + + // Release label shader + m_labelShader->release(); +#endif +#endif +#endif +} + +#if defined(Q_OS_ANDROID) +/*! + * \internal + */ +void Maps3DController::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (!m_zoomActivated) { + m_mousePressed = Maps3DController::MouseOnScene; + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = event->pos(); + } +} + +/*! + * \internal + */ +void Maps3DController::touchEvent(QTouchEvent *event) +{ + static int prevDistance = 0; + + QList<QTouchEvent::TouchPoint> points; + points = event->touchPoints(); + + if (points.count() == 2) { + m_mousePressed = Maps3DController::MouseOnPinch; + + QPointF distance = points.at(0).pos() - points.at(1).pos(); + int newDistance = distance.manhattanLength(); + int zoomRate = 1; + if (m_zoomLevel > 100) + zoomRate = 5; + if (newDistance > prevDistance) + m_zoomLevel += zoomRate; + else + m_zoomLevel -= zoomRate; + if (m_zoomLevel > 500) + m_zoomLevel = 500; + else if (m_zoomLevel < 10) + m_zoomLevel = 10; + prevDistance = newDistance; + //qDebug() << "distance" << distance.manhattanLength(); + } +} +#endif + +/*! + * \internal + */ +void Maps3DController::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) +{ + if (Qt::LeftButton == event->button()) { + if (m_zoomActivated) { + //qDebug() << event->pos().x() << event->pos().y() << m_sceneViewPort << m_zoomViewPort; + if (mousePos.x() <= m_sceneViewPort.width() + && mousePos.y() <= m_sceneViewPort.height()) { + m_mousePressed = Maps3DController::MouseOnOverview; + //qDebug() << "Mouse pressed on overview"; + } else { + m_mousePressed = Maps3DController::MouseOnZoom; + //qDebug() << "Mouse pressed on zoom"; + } + } else { +#if !defined(Q_OS_ANDROID) + m_mousePressed = Maps3DController::MouseOnScene; +#else + m_mousePressed = Maps3DController::MouseRotating; +#endif + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = mousePos; + //qDebug() << "Mouse pressed on scene"; + } + } else if (Qt::MiddleButton == event->button()) { + // reset rotations + m_mousePos = QPoint(0, 0); + } else if (Qt::RightButton == event->button()) { +#if !defined(Q_OS_ANDROID) + m_mousePressed = Maps3DController::MouseRotating; +#else + m_mousePressed = Maps3DController::MouseOnScene; +#endif + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = mousePos; + } + m_camera->updateMousePos(m_mousePos); +} + +/*! + * \internal + */ +void Maps3DController::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event); + //qDebug() << "mouse button released" << event->button(); + if (Maps3DController::MouseRotating == m_mousePressed) { + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = mousePos; + m_camera->updateMousePos(mousePos); + } + m_mousePressed = Maps3DController::MouseNone; +} + +/*! + * \internal + */ +void Maps3DController::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event); + if (Maps3DController::MouseRotating == m_mousePressed) { + //qDebug() << "mouse moved while pressed" << event->pos(); + m_mousePos = mousePos; + } +#if 0 + // TODO: Testi - laske kursorin sijainti scenessä + QPointF mouse3D((2.0f * event->pos().x() - width()) / height(), + 1.0f - (2.0f * event->pos().y()) / height()); + //qDebug() << "mouse position in scene" << mouse3D; + + // TODO: Testi laske focal point + GLfloat focalPoint = tan(45.0f / 2.0f); + + // TODO: Testi - laske viewmatriisin kerroin + QVector3D worldRay = QVector3D(0.0f, 0.0f, 0.0f) - QVector3D(mouse3D.x(), mouse3D.y(), + -focalPoint); + //qDebug() << "worldRay" << worldRay; + // multiply viewmatrix with this to get something? +#endif +} + +/*! + * \internal + */ +void Maps3DController::wheelEvent(QWheelEvent *event) +{ + if (m_zoomLevel > 100) + m_zoomLevel += event->angleDelta().y() / 12; + else if (m_zoomLevel > 50) + m_zoomLevel += event->angleDelta().y() / 60; + else + m_zoomLevel += event->angleDelta().y() / 120; + if (m_zoomLevel > 500) + m_zoomLevel = 500; + else if (m_zoomLevel < 10) + m_zoomLevel = 10; +} + +/*! + * \internal + */ +void Maps3DController::resizeNotify() +{ + if (!m_isInitialized) + return; + + // Set view port + if (m_zoomActivated) + m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5); + else + m_sceneViewPort = QRect(0, 0, width(), height()); + m_zoomViewPort = QRect(0, 0, width(), height()); + + // Calculate zoom level based on aspect ratio + GLfloat div; + GLfloat zoomAdjustment; + div = qMin(width(), height()); + zoomAdjustment = defaultRatio * ((width() / div) / (height() / div)); + //qDebug() << "zoom adjustment" << zoomAdjustment; + m_autoScaleAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f + + // Re-init selection buffer + initSelectionBuffer(); + +#if !defined(QT_OPENGL_ES_2) + // Re-init depth buffer + initDepthBuffer(); +#endif +} + +void Maps3DController::setBarSpecs(const QVector3D &thickness, + Q3DMaps::AdjustmentDirection direction) +{ + m_barThickness = thickness; + m_adjustDirection = direction; +} + +void Maps3DController::setBarType(QDataVis::MeshStyle style, bool smooth) +{ + if (style == QDataVis::Bars) { + if (smooth) + m_objFile = QStringLiteral(":/defaultMeshes/barSmooth"); + else + m_objFile = QStringLiteral(":/defaultMeshes/bar"); + } else if (style == QDataVis::Pyramids) { + if (smooth) + m_objFile = QStringLiteral(":/defaultMeshes/pyramidSmooth"); + else + m_objFile = QStringLiteral(":/defaultMeshes/pyramid"); + } else if (style == QDataVis::Cones) { + if (smooth) + m_objFile = QStringLiteral(":/defaultMeshes/coneSmooth"); + else + m_objFile = QStringLiteral(":/defaultMeshes/cone"); + } else if (style == QDataVis::Cylinders) { + if (smooth) + m_objFile = QStringLiteral(":/defaultMeshes/cylinderSmooth"); + else + m_objFile = QStringLiteral(":/defaultMeshes/cylinder"); + } else if (style == QDataVis::BevelBars) { + if (smooth) + m_objFile = QStringLiteral(":/defaultMeshes/bevelbarSmooth"); + else + m_objFile = QStringLiteral(":/defaultMeshes/bevelbar"); + } else if (style == QDataVis::Spheres) { + if (smooth) + m_objFile = QStringLiteral(":/defaultMeshes/sphereSmooth"); + else + m_objFile = QStringLiteral(":/defaultMeshes/sphere"); + } + // Reload mesh data + if (m_isInitialized) + loadBarMesh(); +} + +void Maps3DController::setMeshFileName(const QString &objFileName) +{ + m_objFile = objFileName; +} + +void Maps3DController::setCameraPreset(QDataVis::CameraPreset preset) +{ + m_camera->setCameraPreset(preset); +} + +void Maps3DController::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) +{ + m_horizontalRotation = qBound(-180.0f, horizontal, 180.0f); + m_verticalRotation = qBound(0.0f, vertical, 90.0f); + m_zoomLevel = qBound(10, distance, 500); + m_camera->setCameraRotation(QPointF(m_horizontalRotation, m_verticalRotation)); + //qDebug() << "camera rotation set to" << m_horizontalRotation << m_verticalRotation; +} + +void Maps3DController::setTheme(QDataVis::ColorTheme colorTheme) +{ + m_theme->useColorTheme(colorTheme); + m_drawer->setTheme(*m_theme); +#if !defined(QT_OPENGL_ES_2) + if (m_shadowQuality > QDataVis::ShadowNone) { + // Re-init shaders + if (!m_theme->m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + } else { + // Re-init shaders + if (!m_theme->m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + } +#else + if (!m_theme->m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentColorOnYES2")); + } else { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); + } +#endif + m_updateLabels = true; +} + +void Maps3DController::setBarColor(QColor baseColor, QColor heightColor, bool uniform) +{ + m_theme->m_baseColor = baseColor; + m_theme->m_heightColor = heightColor; + if (m_theme->m_uniformColor != uniform) { +#if !defined(QT_OPENGL_ES_2) + if (m_shadowQuality > QDataVis::ShadowNone) { + // Re-init shaders + if (!m_theme->m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + } else { + // Re-init shaders + if (!m_theme->m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + } +#else + if (!m_theme->m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentColorOnYES2")); + } else { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); + } +#endif + } + m_theme->m_uniformColor = uniform; +} + +void Maps3DController::setAreaSpecs(const QRect &areaRect, const QImage &image) +{ + calculateSceneScalingFactors(areaRect); + setImage(image); +} + +void Maps3DController::setImage(const QImage &image) +{ + m_bgrHasAlpha = image.hasAlphaChannel(); + if (m_bgrTexture) + glDeleteTextures(1, &m_bgrTexture); + m_bgrTexture = m_textureHelper->create2DTexture(image, true, true); +} + +void Maps3DController::setSelectionMode(QDataVis::SelectionMode mode) +{ + m_selectionMode = mode; + // Disable zoom if mode changes + //m_zoomActivated = false; + //m_sceneViewPort = QRect(0, 0, width(), height()); +} + +QDataVis::SelectionMode Maps3DController::selectionMode() +{ + return m_selectionMode; +} + +void Maps3DController::setFontSize(float fontsize) +{ + m_font.setPointSizeF(fontsize); + m_drawer->setFont(m_font); + m_updateLabels = true; +} + +float Maps3DController::fontSize() +{ + return m_font.pointSizeF(); +} + +void Maps3DController::setFont(const QFont &font) +{ + m_font = font; + m_drawer->setFont(font); + m_updateLabels = true; +} + +QFont Maps3DController::font() +{ + return m_font; +} + +void Maps3DController::setLabelTransparency(QDataVis::LabelTransparency transparency) +{ + m_labelTransparency = transparency; + m_drawer->setTransparency(transparency); + m_updateLabels = true; +} + +QDataVis::LabelTransparency Maps3DController::labelTransparency() +{ + return m_labelTransparency; +} + +QDataVis::ShadowQuality Maps3DController::setShadowQuality(QDataVis::ShadowQuality quality) +{ + m_shadowQuality = quality; + switch (quality) { + case QDataVis::ShadowLow: + //qDebug() << "ShadowLow"; + m_shadowQualityToShader = 33.3f; + break; + case QDataVis::ShadowMedium: + //qDebug() << "ShadowMedium"; + m_shadowQualityToShader = 100.0f; + break; + case QDataVis::ShadowHigh: + //qDebug() << "ShadowHigh"; + m_shadowQualityToShader = 200.0f; + break; + default: + m_shadowQualityToShader = 0.0f; + break; + } + if (m_isInitialized) { +#if !defined(QT_OPENGL_ES_2) + if (m_shadowQuality > QDataVis::ShadowNone) { + // Re-init shaders + if (!m_theme->m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadow")); + } else { + // Re-init shaders + if (!m_theme->m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), + QStringLiteral(":/shaders/fragmentTexture")); + } + // Re-init depth buffer + initDepthBuffer(); +#else + if (!m_theme->m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentColorOnYES2")); + } else { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), // Same vertex shader ok for ES2 + QStringLiteral(":/shaders/fragmentTextureES2")); +#endif + } + return m_shadowQuality; +} + +QDataVis::ShadowQuality Maps3DController::shadowQuality() +{ + return m_shadowQuality; +} + + + +const QSize Maps3DController::size() +{ + return m_boundingRect.size(); +} + +const QRect Maps3DController::boundingRect() +{ + return m_boundingRect; +} + +void Maps3DController::setBoundingRect(const QRect boundingRect) +{ + m_boundingRect = boundingRect; + resizeNotify(); +} + +void Maps3DController::setWidth(const int width) +{ + m_boundingRect.setWidth(width); + resizeNotify(); +} + +int Maps3DController::width() +{ + return m_boundingRect.width(); +} + +void Maps3DController::setHeight(const int height) +{ + m_boundingRect.setHeight(height); + resizeNotify(); +} + +int Maps3DController::height() +{ + return m_boundingRect.height(); +} + +void Maps3DController::setX(const int x) +{ + m_boundingRect.setX(x); +} + +int Maps3DController::x() +{ + return m_boundingRect.x(); +} + +void Maps3DController::setY(const int y) +{ + m_boundingRect.setY(y); +} + +int Maps3DController::y() +{ + return m_boundingRect.y(); +} + +void Maps3DController::loadBarMesh() +{ + if (m_barObj) + delete m_barObj; + m_barObj = new ObjectHelper(m_objFile); + m_barObj->load(); +} + +void Maps3DController::loadBackgroundMesh() +{ + if (m_backgroundObj) + delete m_backgroundObj; + m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); + m_backgroundObj->load(); +} + +void Maps3DController::loadGridLineMesh() +{ + if (m_gridLineObj) + delete m_gridLineObj; + m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar")); + m_gridLineObj->load(); +} + +void Maps3DController::loadLabelMesh() +{ + if (m_labelObj) + delete m_labelObj; + m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); + m_labelObj->load(); +} + +void Maps3DController::initShaders(const QString &vertexShader, const QString &fragmentShader) +{ + if (m_barShader) + delete m_barShader; + m_barShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_barShader->initialize(); +} + +void Maps3DController::initSelectionShader() +{ + if (m_selectionShader) + delete m_selectionShader; + m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSelection"), + QStringLiteral(":/shaders/fragmentSelection")); + m_selectionShader->initialize(); +} + +void Maps3DController::initSelectionBuffer() +{ + if (m_selectionTexture) + m_textureHelper->deleteTexture(&m_selectionTexture); + + m_selectionTexture = m_textureHelper->createSelectionTexture(this->size(), + m_selectionFrameBuffer, + m_selectionDepthBuffer); +} + +#if !defined(QT_OPENGL_ES_2) +void Maps3DController::initDepthShader() +{ + if (m_depthShader) + delete m_depthShader; + m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"), + QStringLiteral(":/shaders/fragmentDepth")); + m_depthShader->initialize(); +} + +void Maps3DController::initDepthBuffer() +{ + if (!m_isInitialized) + return; + + if (m_depthTexture) { + m_textureHelper->deleteTexture(&m_depthTexture); + m_depthTexture = 0; + } + + if (m_shadowQuality > QDataVis::ShadowNone) { + m_depthTexture = m_textureHelper->createDepthTexture(this->size(), m_depthFrameBuffer, + m_shadowQuality); + if (!m_depthTexture) { + switch (m_shadowQuality) { + case QDataVis::ShadowHigh: + qWarning("Creating high quality shadows failed. Changing to medium quality."); + (void)setShadowQuality(QDataVis::ShadowMedium); + break; + case QDataVis::ShadowMedium: + qWarning("Creating medium quality shadows failed. Changing to low quality."); + (void)setShadowQuality(QDataVis::ShadowLow); + break; + case QDataVis::ShadowLow: + qWarning("Creating low quality shadows failed. Switching shadows off."); + (void)setShadowQuality(QDataVis::ShadowNone); + break; + default: + // Cannot get here + break; + } + } + } +} +#endif + +void Maps3DController::initBackgroundShaders(const QString &vertexShader, + const QString &fragmentShader) +{ + if (m_backgroundShader) + delete m_backgroundShader; + m_backgroundShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_backgroundShader->initialize(); +} + +void Maps3DController::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) +{ + if (m_labelShader) + delete m_labelShader; + m_labelShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_labelShader->initialize(); +} + +void Maps3DController::updateTextures() +{ + // Drawer has changed; this flag needs to be checked when checking if we need to update labels + m_updateLabels = true; +} + +void Maps3DController::calculateSceneScalingFactors(const QRect &areaRect) +{ + m_areaSize = areaRect.size(); + // Calculate scaling factor so that we can be sure the whole area fits to positive z space + if (zComp > 1.0f) + m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()) / zComp; + else + m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()); + //qDebug() << "scaleFactor" << m_scaleFactor; +} + +void Maps3DController::calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits) +{ + // 2.0f = max difference between minimum and maximum value after scaling with m_heightNormalizer + m_yAdjustment = 2.0f - ((limits.second - limits.first) / m_heightNormalizer); + //qDebug() << m_yAdjustment; +} + +void Maps3DController::calculateTranslation(MapRenderItem &item) +{ + // We need to convert position (which is in coordinates), to translation (which has origin in the center and is scaled) + // -> move pos(center, center) to trans(0, 0) and pos(0, 0) to trans(left, top) + GLfloat xTrans = 2.0f * (item.mapPosition().x() - (m_areaSize.width() / 2.0f)) + / m_scaleFactor; + GLfloat zTrans = 2.0f * (item.mapPosition().y() - (m_areaSize.height() / 2.0f)) + / m_scaleFactor; + //qDebug() << "x, y" << item.mapPosition().x() << item.mapPosition().y(); + item.setTranslation(QVector3D(xTrans, 0.0f, zTrans + zComp)); + //qDebug() << item.translation(); +} + +Maps3DController::SelectionType Maps3DController::isSelected(GLint bar, const QVector3D &selection) +{ + GLubyte barIdxRed = 0; + GLubyte barIdxGreen = 0; + GLubyte barIdxBlue = 0; + //static QVector3D prevSel = selection; // TODO: For debugging + SelectionType isSelectedType = SelectionNone; + + if (selection == skipColor) + return isSelectedType; // skip window + + if (bar <= 255) { + barIdxRed = bar; + } else if (bar <= 65535) { + barIdxGreen = bar / 256; + barIdxRed = bar % 256; + } else { + barIdxBlue = bar / 65535; + barIdxGreen = bar % 65535; + barIdxRed = bar % 256; + } + + QVector3D current = QVector3D(barIdxRed, barIdxGreen, barIdxBlue); + + // TODO: For debugging + //if (selection != prevSel) { + // qDebug() << selection.x() << selection .y() << selection.z(); + // prevSel = selection; + //} + + if (current == selection) + isSelectedType = SelectionBar; + + return isSelectedType; +} + +bool Maps3DController::isValid(const MapRenderItem &item) +{ + bool retval = true; + if (item.value() < 0) { + qCritical("Data item value out of range"); + retval = false; + } else if (item.mapPosition().x() < 0 || item.mapPosition().x() > m_areaSize.width()) { + qCritical("Data item x position out of range"); + retval = false; + } else if (item.mapPosition().y() < 0 || item.mapPosition().y() > m_areaSize.height()) { + qCritical("Data item y position out of range"); + retval = false; + } + return retval; +} + +void Maps3DController::setDataProxy(QMapDataProxy *proxy) +{ + delete m_data; + m_data = proxy; + + QObject::connect(m_data, &QMapDataProxy::arrayReset, this, &Maps3DController::handleArrayReset); + QObject::connect(m_data, &QMapDataProxy::itemsAdded, this, &Maps3DController::handleItemsAdded); + QObject::connect(m_data, &QMapDataProxy::itemsChanged, this, &Maps3DController::handleItemsChanged); + QObject::connect(m_data, &QMapDataProxy::itemsRemoved, this, &Maps3DController::handleItemsRemoved); + QObject::connect(m_data, &QMapDataProxy::itemsInserted, this, &Maps3DController::handleItemsInserted); + + // emit something? Renderer might be interested? +} + +QMapDataProxy *Maps3DController::dataProxy() +{ + return m_data; +} + +void Maps3DController::handleLimitChange() +{ + QPair<GLfloat, GLfloat> limits = m_data->dptr()->limitValues(); + m_heightNormalizer = qMax(qAbs(limits.second), qAbs(limits.first)); + calculateHeightAdjustment(limits); + + //emit limitsChanged(limits); +} + +void Maps3DController::handleArrayReset() +{ + handleLimitChange(); + m_valuesDirty = true; +} + +void Maps3DController::handleItemsAdded(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + handleLimitChange(); + m_valuesDirty = true; +} + +void Maps3DController::handleItemsChanged(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + handleLimitChange(); + m_valuesDirty = true; +} + +void Maps3DController::handleItemsRemoved(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + handleLimitChange(); + m_valuesDirty = true; +} + +void Maps3DController::handleItemsInserted(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + handleLimitChange(); + m_valuesDirty = true; +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/maps3dcontroller_p.h b/src/datavis3d/engine/maps3dcontroller_p.h new file mode 100644 index 00000000..d0c2e74e --- /dev/null +++ b/src/datavis3d/engine/maps3dcontroller_p.h @@ -0,0 +1,253 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 MAPS3DCONTROLLER_P_H +#define MAPS3DCONTROLLER_P_H + +#include "datavis3dglobal_p.h" +#include "q3dmaps.h" +#include "maprenderitem_p.h" +#include <QOpenGLFunctions> +#include <QFont> + +//#define DISPLAY_RENDER_SPEED + +class QPoint; +class QSizeF; + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class ShaderHelper; +class ObjectHelper; +class TextureHelper; +class Theme; +class Drawer; +class Maps3DRenderer; +class CameraHelper; +class QMapDataProxy; + +class QT_DATAVIS3D_EXPORT Maps3DController : public QObject, public QOpenGLFunctions +{ + Q_OBJECT +public: + enum SelectionType { + SelectionNone = 0, + SelectionBar, + SelectionRow, + SelectionColumn + }; + + enum MousePressType { + MouseNone = 0, + MouseOnScene, + MouseOnOverview, + MouseOnZoom, + MouseRotating, + MouseOnPinch + }; + +public: + Maps3DController(const QRect &rect); + ~Maps3DController(); + + void initializeOpenGL(); + virtual void synchDataToRenderer(); + void render(const GLuint defaultFboHandle = 0); + + // bar specifications; base thickness in x, y and z, enum to indicate which direction is increased with value + // TODO: Start using thickness also in adjustment direction; use it as a relative value. + // For example, in AdjustAll mode setting thickness to (0.1f, 1.0f, 0.5f) would apply value to + // x at 10%, y at 100% and z at 50%. If a dimension is not included, given thickness states its absolute value. + void setBarSpecs(const QVector3D &thickness = QVector3D(1.0f, 1.0f, 1.0f), + Q3DMaps::AdjustmentDirection direction = Q3DMaps::AdjustHeight); + + // bar type; bars (=cubes), pyramids, cones, cylinders, balls, etc. + void setBarType(QDataVis::MeshStyle style, bool smooth = false); + + // override bar type with own mesh + void setMeshFileName(const QString &objFileName); + + // Select preset camera placement + void setCameraPreset(QDataVis::CameraPreset preset); + + // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and + // vertical (0...90) angles and distance in percentage (10...500)) + void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); + + // Set theme (bar colors, shaders, window color, background colors, light intensity and text colors are affected) + void setTheme(QDataVis::ColorTheme theme); + + // Set color if you don't want to use themes. Set uniform to false if you want the (height) color to change from bottom to top + void setBarColor(QColor baseColor, QColor heightColor, bool uniform = true); + + // Set area specs + void setAreaSpecs(const QRect &areaRect, const QImage &image); + + // Set area image + void setImage(const QImage &image); + + // TODO: light placement API + + // Change selection mode; single bar, bar and row, bar and column, or all + void setSelectionMode(QDataVis::SelectionMode mode); + QDataVis::SelectionMode selectionMode(); + + // Font size adjustment + void setFontSize(float fontsize); + float fontSize(); + + // Set font + void setFont(const QFont &font); + QFont font(); + + // Label transparency adjustment + void setLabelTransparency(QDataVis::LabelTransparency transparency); + QDataVis::LabelTransparency labelTransparency(); + + // Adjust shadow quality + QDataVis::ShadowQuality setShadowQuality(QDataVis::ShadowQuality quality); + QDataVis::ShadowQuality shadowQuality(); + + // Size + const QSize size(); + const QRect boundingRect(); + void setBoundingRect(const QRect boundingRect); + void setWidth(const int width); + int width(); + void setHeight(const int height); + int height(); + void setX(const int x); + int x(); + void setY(const int y); + int y(); + +#if defined(Q_OS_ANDROID) + void mouseDoubleClickEvent(QMouseEvent *event); + void touchEvent(QTouchEvent *event); +#endif + void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); + void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); + void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); + void wheelEvent(QWheelEvent *event); + void resizeNotify(); + + void loadBarMesh(); + void loadBackgroundMesh(); + void loadGridLineMesh(); + void loadLabelMesh(); + void initShaders(const QString &vertexShader, const QString &fragmentShader); + void initSelectionShader(); + void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); + void initLabelShaders(const QString &vertexShader, const QString &fragmentShader); + void initSelectionBuffer(); +#if !defined(QT_OPENGL_ES_2) + void initDepthShader(); + void initDepthBuffer(); +#endif + void updateTextures(); + void calculateSceneScalingFactors(const QRect &areaRect); + void calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits); + void calculateTranslation(MapRenderItem &item); + SelectionType isSelected(GLint bar, const QVector3D &selection); + bool isValid(const MapRenderItem &item); + + // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. + void setDataProxy(QMapDataProxy *proxy); + QMapDataProxy *dataProxy(); + + void handleLimitChange(); + +public slots: + void handleArrayReset(); + void handleItemsAdded(int startIndex, int count); + void handleItemsChanged(int startIndex, int count); + void handleItemsRemoved(int startIndex, int count); + void handleItemsInserted(int startIndex, int count); + +private: + void drawScene(const GLuint defaultFboHandle); + + Maps3DRenderer *m_renderer; + CameraHelper *m_camera; + + ShaderHelper *m_barShader; + ShaderHelper *m_depthShader; + ShaderHelper *m_selectionShader; + ShaderHelper *m_backgroundShader; + ShaderHelper *m_labelShader; + ObjectHelper *m_barObj; + ObjectHelper *m_backgroundObj; + ObjectHelper *m_gridLineObj; + ObjectHelper *m_labelObj; + QString m_objFile; + MousePressType m_mousePressed; + QPoint m_mousePos; + GLint m_zoomLevel; + GLfloat m_autoScaleAdjustment; + GLfloat m_horizontalRotation; + GLfloat m_verticalRotation; + QVector3D m_barThickness; + GLfloat m_heightNormalizer; + GLfloat m_yAdjustment; + GLfloat m_scaleFactor; + Theme *m_theme; + bool m_isInitialized; + QDataVis::SelectionMode m_selectionMode; + BarRenderItem *m_selectedBar; // points to renderitem array + BarRenderItem *m_previouslySelectedBar; // points to renderitem array + QString m_axisLabelX; + QString m_axisLabelZ; + QString m_axisLabelY; + QRect m_sceneViewPort; + QRect m_zoomViewPort; + bool m_zoomActivated; + TextureHelper *m_textureHelper; + QDataVis::LabelTransparency m_labelTransparency; + QFont m_font; + Drawer *m_drawer; + QSizeF m_areaSize; + GLuint m_bgrTexture; + GLuint m_depthTexture; + GLuint m_selectionTexture; + GLuint m_depthFrameBuffer; + GLuint m_selectionFrameBuffer; + GLuint m_selectionDepthBuffer; + bool m_updateLabels; + Q3DMaps::AdjustmentDirection m_adjustDirection; + QDataVis::ShadowQuality m_shadowQuality; + GLfloat m_shadowQualityToShader; + bool m_bgrHasAlpha; + QRect m_boundingRect; + QMapDataProxy *m_data; + bool m_valuesDirty; + MapRenderItemArray m_renderItemArray; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/maps3drenderer.cpp b/src/datavis3d/engine/maps3drenderer.cpp new file mode 100644 index 00000000..c05f2f51 --- /dev/null +++ b/src/datavis3d/engine/maps3drenderer.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "maps3dcontroller_p.h" +#include "maps3drenderer_p.h" +#include "camerahelper_p.h" +#include "shaderhelper_p.h" +#include "objecthelper_p.h" +#include "texturehelper_p.h" +#include "theme_p.h" +#include "utils_p.h" +#include "drawer_p.h" + +#include <QOpenGLFunctions> +#include <QMatrix4x4> +#include <QOpenGLPaintDevice> +#include <QPainter> +#include <QScreen> +#include <QMouseEvent> + +#include <qmath.h> + +#include <QDebug> + +//#define DISPLAY_RENDER_SPEED + +// Uncommenting this draws the shadow map with wider FOV than scene itself, making the light +// seem to be closer to scene than it actually is. This way shadows look slightly better (to me anyway) +#define USE_WIDER_SHADOWS + +// You can verify that depth buffer drawing works correctly by uncommenting this. +// You should see the scene from where the light is +//#define SHOW_DEPTH_TEXTURE_SCENE + +#ifdef DISPLAY_RENDER_SPEED +#include <QTime> +#endif + +QT_DATAVIS3D_BEGIN_NAMESPACE + +//#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels + +Maps3DRenderer::Maps3DRenderer(Maps3DController *controller) : QObject(controller) +{ +} + +Maps3DRenderer::~Maps3DRenderer() +{ +} + +void Maps3DRenderer::render(CameraHelper *camera, const GLuint defaultFboHandle) +{ + Q_UNUSED(camera) + Q_UNUSED(defaultFboHandle) + // TODO: Implement +} + + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/maps3drenderer_p.h b/src/datavis3d/engine/maps3drenderer_p.h new file mode 100644 index 00000000..89054e83 --- /dev/null +++ b/src/datavis3d/engine/maps3drenderer_p.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 MAPS3DRENDERER_P_H +#define MAPS3DRENDERER_P_H + +#include <QOpenGLFunctions> + +#include "datavis3dglobal_p.h" +#include "camerahelper_p.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class Maps3DController; + +class QT_DATAVIS3D_EXPORT Maps3DRenderer : public QObject, public QOpenGLFunctions +{ + +public: + explicit Maps3DRenderer(Maps3DController *controller); + ~Maps3DRenderer(); + + void render(CameraHelper *camera, const GLuint defaultFboHandle); +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/meshes/scatterdot.obj b/src/datavis3d/engine/meshes/scatterdot.obj new file mode 100644 index 00000000..d994a80f --- /dev/null +++ b/src/datavis3d/engine/meshes/scatterdot.obj @@ -0,0 +1,28 @@ +# Blender v2.66 (sub 0) OBJ File: 'scatterdot.blend' +# www.blender.org +o Cone +v 0.000000 -0.500000 -1.000000 +v 0.866025 -0.500000 0.500000 +v 0.000000 0.500000 0.000000 +v -0.866025 -0.500000 0.500000 +vt 0.999727 0.000000 +vt 1.000000 0.492691 +vt 0.522886 0.369782 +vt 0.477114 0.973202 +vt 0.000000 1.096111 +vt 0.000273 0.603420 +vt 0.523159 0.985382 +vt 0.522886 0.492691 +vt 1.000000 0.615600 +vt 0.000000 0.603420 +vt 0.000617 0.000000 +vt 0.522886 0.302245 +vn -0.833033 -0.273293 0.480941 +vn 0.000000 0.999969 0.000000 +vn 0.000000 -0.273293 -0.961913 +vn 0.833033 -0.273293 0.480941 +s 1 +f 4/1/1 3/2/2 1/3/3 +f 1/4/3 3/5/2 2/6/4 +f 2/7/4 3/8/2 4/9/1 +f 1/10/3 2/11/4 4/12/1 diff --git a/src/datavis3d/engine/meshes/scatterdotFlat.obj b/src/datavis3d/engine/meshes/scatterdotFlat.obj new file mode 100644 index 00000000..4052738d --- /dev/null +++ b/src/datavis3d/engine/meshes/scatterdotFlat.obj @@ -0,0 +1,28 @@ +# Blender v2.66 (sub 0) OBJ File: 'scatterdot.blend' +# www.blender.org +o Cone +v 0.000000 -0.500000 -1.000000 +v 0.866025 -0.500000 0.500000 +v 0.000000 0.500000 0.000000 +v -0.866025 -0.500000 0.500000 +vt 0.999727 0.000000 +vt 1.000000 0.492691 +vt 0.522886 0.369782 +vt 0.477114 0.973202 +vt 0.000000 1.096111 +vt 0.000273 0.603420 +vt 0.523159 0.985382 +vt 0.522886 0.492691 +vt 1.000000 0.615600 +vt 0.000000 0.603420 +vt 0.000617 0.000000 +vt 0.522886 0.302245 +vn -0.774597 0.447214 -0.447214 +vn 0.774597 0.447214 -0.447214 +vn -0.000000 0.447214 0.894427 +vn 0.000000 -1.000000 -0.000000 +s off +f 4/1/1 3/2/1 1/3/1 +f 1/4/2 3/5/2 2/6/2 +f 2/7/3 3/8/3 4/9/3 +f 1/10/4 2/11/4 4/12/4 diff --git a/src/datavis3d/engine/q3dbars.cpp b/src/datavis3d/engine/q3dbars.cpp index 39750b38..e46d5d14 100644 --- a/src/datavis3d/engine/q3dbars.cpp +++ b/src/datavis3d/engine/q3dbars.cpp @@ -1,58 +1,31 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #include "q3dbars.h" #include "q3dbars_p.h" -#include "bars3dshared_p.h" +#include "bars3dcontroller_p.h" +#include "qvalueaxis.h" -#include <QOpenGLPaintDevice> -#include <QPainter> -#include <QScreen> #include <QMouseEvent> -#include <qmath.h> - #include <QDebug> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE /*! * \class Q3DBars @@ -104,138 +77,14 @@ QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE */ /*! - \enum BarStyle - - Predefined bar types. - - \value Bars - Basic cubic bar. - \value Pyramids - Four -sided pyramid. - \value Cones - Basic cone. - \value Cylinders - Basic cylinder. - \value BevelBars - Slilghtly beveled (rounded) cubic bar. - \value Spheres - Sphere. Not usable in Q3DBars. -*/ - -/*! - \enum CameraPreset - - Predefined positions for camera. - - \value PresetFrontLow - \value PresetFront - \value PresetFrontHigh - \value PresetLeftLow - \value PresetLeft - \value PresetLeftHigh - \value PresetRightLow - \value PresetRight - \value PresetRightHigh - \value PresetBehindLow - \value PresetBehind - \value PresetBehindHigh - \value PresetIsometricLeft - \value PresetIsometricLeftHigh - \value PresetIsometricRight - \value PresetIsometricRightHigh - \value PresetDirectlyAbove - \value PresetDirectlyAboveCW45 - \value PresetDirectlyAboveCCW45 - \value PresetFrontBelow - From PresetFrontBelow onward these only work for graphs including negative values. - They act as Preset...Low for positive-only values. - \value PresetLeftBelow - \value PresetRightBelow - \value PresetBehindBelow - \value PresetDirectlyBelow - Acts as PresetFrontLow for positive -only bars. -*/ - -/*! - \enum ColorTheme - - Predefined color themes. - - \value ThemeSystem - \value ThemeBlueCerulean - \value ThemeBlueIcy - \value ThemeBlueNcs - \value ThemeBrownSand - \value ThemeDark - \value ThemeHighContrast - \value ThemeLight -*/ - -/*! - \enum SelectionMode - - Bar selection modes. - - \value ModeNone - Selection mode disabled. - \value ModeBar - Selection selects a single bar. - \value ModeBarAndRow - Selection selects a single bar and highlights the row it is on. - \value ModeBarAndColumn - Selection selects a single bar and highlights the column it is on. - \value ModeBarRowAndColumn - Selection selects a single bar and highlights the row and the column it is on. - \value ModeZoomRow - Selection selects a single bar and displays the row it is on in a separate view. The - original view is shrunk into upper left corner. Original view is restored by clicking - on it. - \value ModeZoomColumn - Selection selects a single bar and displays the column it is on in a separate view. The - original view is shrunk into upper left corner. Original view is restored by clicking - on it. -*/ - -/*! - \enum ShadowQuality - - Quality of shadows. - - \value ShadowNone - Shadows are disabled. - \value ShadowLow - Shadows are rendered in low quality. - \value ShadowMedium - Shadows are rendered in medium quality. - \value ShadowHigh - Shadows are rendered in high quality. -*/ - -/*! - \enum LabelTransparency - - Label transparencies. - - \value TransparencyNone - Full solid, using colors from theme. - \value TransparencyFromTheme - Use colors and transparencies from theme. - \value TransparencyNoBackground - Draw just text on transparent background. -*/ - -/*! - * \a fbohandle Handle to QML2 scene graph's framebuffer object. Developers should not need to - * ever use this directly. Not used when using C++ API. - * - * \a windowsize QML2 window size Developers should not need to ever use this directly. Not - * used when using C++ API. - * - * Constructs a new 3D bar window. Parameters are not used unless instantiating from Qt Quick 2. + * Constructs a new 3D bar window. */ -Q3DBars::Q3DBars(GLuint fbohandle, const QSize &windowsize) - : d_ptr(new Q3DBarsPrivate(this, geometry(), fbohandle)) +Q3DBars::Q3DBars() + : d_ptr(new Q3DBarsPrivate(this, geometry())) { + d_ptr->m_shared->initializeOpenGL(); + QObject::connect(d_ptr->m_shared, &Bars3dController::shadowQualityChanged, this, + &Q3DBars::handleShadowQualityUpdate); } /*! @@ -248,19 +97,15 @@ Q3DBars::~Q3DBars() /*! * \internal */ -void Q3DBars::initialize() +void Q3DBars::render() { - d_ptr->m_shared->setWidth(width()); - d_ptr->m_shared->setHeight(height()); - d_ptr->m_shared->initializeOpenGL(); + d_ptr->m_shared->synchDataToRenderer(); + d_ptr->m_shared->render(); } -/*! - * \internal - */ -void Q3DBars::render() +void Q3DBars::handleShadowQualityUpdate(QDataVis::ShadowQuality quality) { - d_ptr->m_shared->render(); + emit shadowQualityChanged(quality); } #if defined(Q_OS_ANDROID) @@ -286,7 +131,7 @@ void Q3DBars::touchEvent(QTouchEvent *event) */ void Q3DBars::mousePressEvent(QMouseEvent *event) { - d_ptr->m_shared->mousePressEvent(event); + d_ptr->m_shared->mousePressEvent(event, event->pos()); } /*! @@ -294,7 +139,7 @@ void Q3DBars::mousePressEvent(QMouseEvent *event) */ void Q3DBars::mouseReleaseEvent(QMouseEvent *event) { - d_ptr->m_shared->mouseReleaseEvent(event); + d_ptr->m_shared->mouseReleaseEvent(event, event->pos()); } /*! @@ -302,7 +147,7 @@ void Q3DBars::mouseReleaseEvent(QMouseEvent *event) */ void Q3DBars::mouseMoveEvent(QMouseEvent *event) { - d_ptr->m_shared->mouseMoveEvent(event); + d_ptr->m_shared->mouseMoveEvent(event, event->pos()); } /*! @@ -319,10 +164,7 @@ void Q3DBars::wheelEvent(QWheelEvent *event) void Q3DBars::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); - d_ptr->m_shared->setWidth(width()); - d_ptr->m_shared->setHeight(height()); - if (d_ptr->m_shared->m_isInitialized) - d_ptr->m_shared->resizeNotify(); + d_ptr->m_shared->setSize(width(), height()); } // TODO: Document @@ -358,7 +200,7 @@ void Q3DBars::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative) } /*! - * \a style One of the values in \c BarStyle. \c Bars by default. + * \a style One of the values in \c MeshStyle. \c Bars by default. * * \a smooth A flag to set shading to smooth. \c false by default. * @@ -366,7 +208,7 @@ void Q3DBars::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative) * * \sa setMeshFileName() */ -void Q3DBars::setBarType(BarStyle style, bool smooth) +void Q3DBars::setBarType(QDataVis::MeshStyle style, bool smooth) { d_ptr->m_shared->setBarType(style, smooth); } @@ -376,30 +218,27 @@ void Q3DBars::setBarType(BarStyle style, bool smooth) * * \a samplesColumn How many items there are per row. * - * \a labelRow QString label for the rows, ie. x -axis label. - * - * \a labelColumn QString label for the columns, ie. z -axis label. - * - * \a labelHeight QString label for height, ie. y -axis label. - * * Set up sample space. This must be called to initialize the sample space before adding data to the * Q3DBars. * * \sa addDataRow(), addDataSet() */ -void Q3DBars::setupSampleSpace(int samplesRow, int samplesColumn, const QString &labelRow, - const QString &labelColumn, const QString &labelHeight) +void Q3DBars::setupSampleSpace(int samplesRow, int samplesColumn) { - d_ptr->m_shared->setupSampleSpace(samplesRow, samplesColumn, labelRow, labelColumn, - labelHeight); + d_ptr->m_shared->setupSampleSpace(samplesRow, samplesColumn); +} + +QSize Q3DBars::sampleSpace() const +{ + return QSize(d_ptr->m_shared->rowCount(), d_ptr->m_shared->columnCount()); } /*! - * \a preset Move camera to a predefined position from \c CameraPreset. + * \a preset Move camera to a predefined position from \c QDataVis::CameraPreset. * * Moves camera to a predefined position. */ -void Q3DBars::setCameraPreset(CameraPreset preset) +void Q3DBars::setCameraPreset(QDataVis::CameraPreset preset) { d_ptr->m_shared->setCameraPreset(preset); } @@ -416,20 +255,20 @@ void Q3DBars::setCameraPreset(CameraPreset preset) * on data values. Negative vertical angles are allowed only if there are negative bar values. * Distance is adjustable between 10 and 500. */ -void Q3DBars::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) +void Q3DBars::setCameraPosition(qreal horizontal, qreal vertical, int distance) { - d_ptr->m_shared->setCameraPosition(horizontal, vertical, distance); + d_ptr->m_shared->setCameraPosition(GLfloat(horizontal), GLfloat(vertical), GLint(distance)); } /*! - * \a theme Apply a predefined theme from \c ColorTheme. + * \a theme Apply a predefined theme from \c QDataVis::ColorTheme. * * Sets a predefined theme. Theme affects bar colors, label colors, text color, background color, * window color and grid color. Lighting is also adjusted by themes. */ -void Q3DBars::setTheme(ColorTheme theme) +void Q3DBars::setTheme(QDataVis::ColorTheme theme) { - d_ptr->m_shared->setTheme(theme); + d_ptr->m_shared->setColorTheme(theme); } /*! @@ -449,23 +288,22 @@ void Q3DBars::setTheme(ColorTheme theme) */ void Q3DBars::setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, bool uniform) { - d_ptr->m_shared->setBarColor(baseColor, heightColor, depthColor, uniform); + d_ptr->m_shared->setObjectColor(baseColor, heightColor, depthColor, uniform); } /*! - * \a mode Set bar selection mode from \c SelectionMode. \c ModeBar by default. + * \property Q3DBars::selectionMode + * + * \a mode Set bar selection mode from \c QDataVis::SelectionMode. \c ModeItem by default. * * Sets bar selection mode to be used. */ -void Q3DBars::setSelectionMode(SelectionMode mode) +void Q3DBars::setSelectionMode(QDataVis::SelectionMode mode) { d_ptr->m_shared->setSelectionMode(mode); } -/*! - * \return \c SelectionMode. - */ -SelectionMode Q3DBars::selectionMode() +QDataVis::SelectionMode Q3DBars::selectionMode() const { return d_ptr->m_shared->selectionMode(); } @@ -482,7 +320,7 @@ void Q3DBars::setWindowTitle(const QString &title) setTitle(title); } -QString Q3DBars::windowTitle() +QString Q3DBars::windowTitle() const { return title(); } @@ -527,192 +365,116 @@ void Q3DBars::setFont(const QFont &font) d_ptr->m_shared->setFont(font); } -QFont Q3DBars::font() +QFont Q3DBars::font() const { return d_ptr->m_shared->font(); } /*! - * \a transparency Transparency level of labels from \c LabelTransparency. + * \property Q3DBars::labelTransparency + * + * \a transparency Transparency level of labels from \c QDataVis::LabelTransparency. * \c TransparencyFromTheme by default. * * Sets label transparency. */ -void Q3DBars::setLabelTransparency(LabelTransparency transparency) +void Q3DBars::setLabelTransparency(QDataVis::LabelTransparency transparency) { d_ptr->m_shared->setLabelTransparency(transparency); } -/*! - * \return \c LabelTransparency. - */ -LabelTransparency Q3DBars::labelTransparency() +QDataVis::LabelTransparency Q3DBars::labelTransparency() const { return d_ptr->m_shared->labelTransparency(); } /*! - * \property Q3DBars::grid + * \property Q3DBars::gridVisible * - * \a enable Flag to enable or disable grid. \c true by default. + * \a visible Flag to enable or disable grid. \c true by default. * * Sets grid drawing on or off. */ -void Q3DBars::setGridEnabled(bool enable) +void Q3DBars::setGridVisible(bool visible) { - d_ptr->m_shared->setGridEnabled(enable); + d_ptr->m_shared->setGridEnabled(visible); } -bool Q3DBars::gridEnabled() +bool Q3DBars::isGridVisible() const { return d_ptr->m_shared->gridEnabled(); } /*! - * \property Q3DBars::background + * \property Q3DBars::backgroundVisible * - * \a enable Flag to enable or disable background. \c true by default. + * \a visible Flag to enable or disable background. \c true by default. * * Sets backround rendering on or off. */ -void Q3DBars::setBackgroundEnabled(bool enable) +void Q3DBars::setBackgroundVisible(bool visible) { - d_ptr->m_shared->setBackgroundEnabled(enable); + d_ptr->m_shared->setBackgroundEnabled(visible); } -bool Q3DBars::backgroundEnabled() +bool Q3DBars::isBackgroundVisible() const { return d_ptr->m_shared->backgroundEnabled(); } /*! - * \a quality Shadow quality from \c ShadowQuality. \c ShadowLow by default. + * \property Q3DBars::shadowQuality + * + * \a quality Shadow quality from \c QDataVis::ShadowQuality. \c ShadowLow by default. + * + * Sets shadow quality. If setting QDataVis::ShadowQuality of a certain level fails, a level is lowered + * until it is successful and shadowQualityChanged signal is emitted for each time the change is done. */ -void Q3DBars::setShadowQuality(ShadowQuality quality) +void Q3DBars::setShadowQuality(QDataVis::ShadowQuality quality) { - d_ptr->m_shared->setShadowQuality(quality); + return d_ptr->m_shared->setShadowQuality(quality); } -/*! - * \return \c ShadowQuality. - */ -ShadowQuality Q3DBars::shadowQuality() +QDataVis::ShadowQuality Q3DBars::shadowQuality() const { return d_ptr->m_shared->shadowQuality(); } -/*! - * \a tickCount How many ticks will be drawn. \c 5 by default. - * - * \a step How large a step each tick is. - * - * \a minimum Minimum value a bar in data set can have. Setting this correctly is especially - * important if values can be negative, or autoscaling won't work correctly. - * - * Sets tick count and step. Note; tickCount * step should be the maximum possible value of data - * set. - */ -void Q3DBars::setTickCount(GLint tickCount, GLfloat step, GLfloat minimum) +QCategoryAxis *Q3DBars::rowAxis() { - d_ptr->m_shared->setTickCount(tickCount, step, minimum); + return reinterpret_cast<QCategoryAxis *>(d_ptr->m_shared->axisX()); } -/*! - * \a dataRow A vector of floats representing a single row of data. Sample space must be large - * enough to hold the row. - * - * \a labelRow A QString label for the row. - * - * \a labelsColumn A vector of strings, one for each item in the row. - * - * Add a row of data. Each new row is added to the front of the sample space, moving previous - * rows back (if sample space is more than one row deep). - */ -void Q3DBars::addDataRow(const QVector<float> &dataRow, const QString &labelRow, - const QVector<QString> &labelsColumn) +QCategoryAxis *Q3DBars::columnAxis() { - d_ptr->m_shared->addDataRow(dataRow, labelRow, labelsColumn); + return reinterpret_cast<QCategoryAxis *>(d_ptr->m_shared->axisZ()); } -/*! - * \a dataRow A vector of QDataItems representing a single row of data. Sample space must be - * large enough to hold the row. Ownership of QDataItems is transferred to Q3DBars. - * - * \a labelRow A QString label for the row. - * - * \a labelsColumn A vector of strings, one for each item in the row. - * - * Add a row of data. Each new row is added to the front of the sample space, moving previous - * rows back (if sample space is more than one row deep). - */ -void Q3DBars::addDataRow(const QVector<QDataItem*> &dataRow, const QString &labelRow, - const QVector<QString> &labelsColumn) +void Q3DBars::setValueAxis(QValueAxis *axis) { - d_ptr->m_shared->addDataRow(dataRow, labelRow, labelsColumn); -} + Q_ASSERT(axis); -/*! - * \a dataRow A QDataRow instance representing a single row of data. Sample space must be - * large enough to hold the row. Ownership of QDataRow is transferred to Q3DBars. - * - * Add a row of data. Each new row is added to the front of the sample space, moving previous - * rows back (if sample space is more than one row deep). - */ -void Q3DBars::addDataRow(QDataRow *dataRow) -{ - d_ptr->m_shared->addDataRow(dataRow); + return d_ptr->m_shared->setAxisY(axis); } -/*! - * \a data A vector of vector of floats representing the whole data set. Sample space must be - * large enough to hold the set. - * - * \a labelsRow A vector of strings, one for each column in the row. - * - * \a labelsColumn A vector of strings, one for each row in the column. - * - * Adds a whole data set at once. If an old data set exists, it is deleted and replaced with the - * new one. - */ -void Q3DBars::addDataSet(const QVector< QVector<float> > &data, const QVector<QString> &labelsRow, - const QVector<QString> &labelsColumn) +QValueAxis *Q3DBars::valueAxis() { - d_ptr->m_shared->addDataSet(data, labelsRow, labelsColumn); + return static_cast<QValueAxis *>(d_ptr->m_shared->axisY()); } -/*! - * \a data A vector of vector of QDataItems representing the whole data set. Sample space must - * be large enough to hold the set. Ownership of QDataItems is transferred to Q3DBars. - * - * \a labelsRow A vector of strings, one for each column in the row. - * - * \a labelsColumn A vector of strings, one for each row in the column. - * - * Adds a whole data set at once. If an old data set exists, it is deleted and replaced with the - * new one. - */ -void Q3DBars::addDataSet(const QVector< QVector<QDataItem*> > &data, - const QVector<QString> &labelsRow, - const QVector<QString> &labelsColumn) +void Q3DBars::setDataProxy(QBarDataProxy *proxy) { - d_ptr->m_shared->addDataSet(data, labelsRow, labelsColumn); + d_ptr->m_shared->setDataProxy(proxy); } -/*! - * \a dataSet A QDataSet instance holding the whole data set. Sample space must - * be large enough to hold the set. Ownership of QDataSet is transferred to Q3DBars. - * - * Adds a whole data set at once. If an old data set exists, it is deleted and replaced with the - * new one. - */ -void Q3DBars::addDataSet(QDataSet *dataSet) +QBarDataProxy *Q3DBars::dataProxy() { - d_ptr->m_shared->addDataSet(dataSet); + return d_ptr->m_shared->dataProxy(); } -Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q, QRect rect, GLuint fbohandle) +Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q, QRect rect) : q_ptr(q), - m_shared(new Bars3dShared(rect, fbohandle)) + m_shared(new Bars3dController(rect)) { } @@ -722,4 +484,4 @@ Q3DBarsPrivate::~Q3DBarsPrivate() delete m_shared; } -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dbars.h b/src/datavis3d/engine/q3dbars.h index 03635e4d..a0eb9cb5 100644 --- a/src/datavis3d/engine/q3dbars.h +++ b/src/datavis3d/engine/q3dbars.h @@ -1,147 +1,97 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #ifndef Q3DBARS_H #define Q3DBARS_H -#include "QtDataVis3D/qdatavis3dglobal.h" -#include "QtDataVis3D/qdatavis3namespace.h" -#include "q3dwindow.h" - +#include <QtDataVis3D/qdatavis3denums.h> +#include <QtDataVis3D/q3dwindow.h> #include <QFont> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE class Q3DBarsPrivate; -class QDataItem; -class QDataRow; -class QDataSet; -class LabelItem; +class QCategoryAxis; +class QValueAxis; +class QBarDataProxy; -class QTENTERPRISE_DATAVIS3D_EXPORT Q3DBars : public Q3DWindow +class QT_DATAVIS3D_EXPORT Q3DBars : public Q3DWindow { Q_OBJECT + Q_PROPERTY(QtDataVis3D::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + Q_PROPERTY(QtDataVis3D::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) + Q_PROPERTY(QtDataVis3D::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) Q_PROPERTY(QFont font READ font WRITE setFont) Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) - Q_PROPERTY(bool grid READ gridEnabled WRITE setGridEnabled) - Q_PROPERTY(bool background READ backgroundEnabled WRITE setBackgroundEnabled) + Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) + Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) + Q_ENUMS(QtDataVis3D::QDataVis::SelectionMode) + Q_ENUMS(QtDataVis3D::QDataVis::ShadowQuality) + Q_ENUMS(QtDataVis3D::QDataVis::LabelTransparency) public: - explicit Q3DBars(GLuint fbohandle = 0, const QSize &windowsize = QSize()); + explicit Q3DBars(); ~Q3DBars(); - // Add a row of data. Each new row is added to the front of the sample space, moving previous - // rows back (if sample space is more than one row deep) - Q_INVOKABLE void addDataRow(const QVector<float> &dataRow, - const QString &labelRow = QString(), - const QVector<QString> &labelsColumn = QVector<QString>()); - // ownership of dataItems is transferred - Q_INVOKABLE void addDataRow(const QVector<QDataItem*> &dataRow, - const QString &labelRow = QString(), - const QVector<QString> &labelsColumn = QVector<QString>()); - // ownership of dataRow is transferred - Q_INVOKABLE void addDataRow(QDataRow *dataRow); - - // Add complete data set at a time, as a vector of data rows - Q_INVOKABLE void addDataSet(const QVector< QVector<float> > &data, - const QVector<QString> &labelsRow = QVector<QString>(), - const QVector<QString> &labelsColumn = QVector<QString>()); - - // ownership of dataItems is transferred - Q_INVOKABLE void addDataSet(const QVector< QVector<QDataItem*> > &data, - const QVector<QString> &labelsRow = QVector<QString>(), - const QVector<QString> &labelsColumn = QVector<QString>()); - // ownership of dataSet is transferred - Q_INVOKABLE void addDataSet(QDataSet* dataSet); - // bar thickness, spacing between bars, and is spacing relative to thickness or absolute // y -component sets the thickness/spacing of z -direction // With relative 0.0f means side-to-side, 1.0f = one thickness in between - Q_INVOKABLE void setBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f), - QSizeF spacing = QSizeF(1.0f, 1.0f), - bool relative = true); + void setBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f), + QSizeF spacing = QSizeF(1.0f, 1.0f), + bool relative = true); // bar type; bars (=cubes), pyramids, cones, cylinders, etc. - Q_INVOKABLE void setBarType(BarStyle style, bool smooth = false); + void setBarType(QDataVis::MeshStyle style, bool smooth = false); // how many samples per row and column, and names for axes - Q_INVOKABLE void setupSampleSpace(int samplesRow, int samplesColumn, - const QString &labelRow = QString(), - const QString &labelColumn = QString(), - const QString &labelHeight = QString()); + // TODO: This defines the data window, needs additional parameters startRow, startColumn + void setupSampleSpace(int samplesRow, int samplesColumn); + QSize sampleSpace() const; // TODO: Return QRect once data window properly implemented? // Select preset camera placement - Q_INVOKABLE void setCameraPreset(CameraPreset preset); + void setCameraPreset(QDataVis::CameraPreset preset); // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and // vertical (0...90) (or (-90...90) if there are negative values) angles and distance in // percentage (10...500)) - Q_INVOKABLE void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); + void setCameraPosition(qreal horizontal, qreal vertical, int distance = 100); // Set theme (bar colors, shaders, window color, background colors, light intensity and text // colors are affected) - Q_INVOKABLE void setTheme(ColorTheme theme); + void setTheme(QDataVis::ColorTheme theme); // Set color if you don't want to use themes. Set uniform to false if you want the (height) // color to change from bottom to top - Q_INVOKABLE void setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, - bool uniform = true); - - // Set tick count and step. Note; tickCount * step should be the maximum possible value of data - // set. Minimum is the absolute minimum possible value a bar can have. This is especially - // important to set if values can be negative. - Q_INVOKABLE void setTickCount(GLint tickCount, GLfloat step, GLfloat minimum = 0.0f); + void setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, + bool uniform = true); // override bar type with own mesh - Q_INVOKABLE void setMeshFileName(const QString &objFileName); + void setMeshFileName(const QString &objFileName); // TODO: light placement API // Change selection mode; single bar, bar and row, bar and column, or all - void setSelectionMode(SelectionMode mode); - SelectionMode selectionMode(); + void setSelectionMode(QDataVis::SelectionMode mode); + QDataVis::SelectionMode selectionMode() const; // Set window title void setWindowTitle(const QString &title); - QString windowTitle(); + QString windowTitle() const; // Font size adjustment void setFontSize(float fontsize); @@ -149,31 +99,48 @@ public: // Set font void setFont(const QFont &font); - QFont font(); + QFont font() const; // Label transparency adjustment - void setLabelTransparency(LabelTransparency transparency); - LabelTransparency labelTransparency(); + void setLabelTransparency(QDataVis::LabelTransparency transparency); + QDataVis::LabelTransparency labelTransparency() const; // Enable or disable background grid - void setGridEnabled(bool enable); - bool gridEnabled(); + void setGridVisible(bool visible); + bool isGridVisible() const; - // TODO: Do these need to be public? Where are they called from? // Size void setWidth(const int width); void setHeight(const int height); // Enable or disable background mesh - void setBackgroundEnabled(bool enable); - bool backgroundEnabled(); + void setBackgroundVisible(bool visible); + bool isBackgroundVisible() const; // Adjust shadow quality - void setShadowQuality(ShadowQuality quality); - ShadowQuality shadowQuality(); + void setShadowQuality(QDataVis::ShadowQuality quality); + QDataVis::ShadowQuality shadowQuality() const; + + // Axes - row & column axes are fixed to category axes, value axis can be + // customized. + QCategoryAxis *rowAxis(); + QCategoryAxis *columnAxis(); + void setValueAxis(QValueAxis *axis); + QValueAxis *valueAxis(); + + // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. + void setDataProxy(QBarDataProxy *proxy); + QBarDataProxy *dataProxy(); + +public slots: + // Used to detect when shadow quality changes autonomously due to e.g. resizing. + void handleShadowQualityUpdate(QDataVis::ShadowQuality quality); + +signals: + // Signals shadow quality changes. + void shadowQualityChanged(QDataVis::ShadowQuality quality); protected: - void initialize(); void render(); #if defined(Q_OS_ANDROID) @@ -187,12 +154,10 @@ protected: void resizeEvent(QResizeEvent *event); private: - void drawZoomScene(); - void drawScene(); QScopedPointer<Q3DBarsPrivate> d_ptr; Q_DISABLE_COPY(Q3DBars) }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/engine/q3dbars_p.h b/src/datavis3d/engine/q3dbars_p.h index f5d0cf38..9eed8162 100644 --- a/src/datavis3d/engine/q3dbars_p.h +++ b/src/datavis3d/engine/q3dbars_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,28 +29,23 @@ #ifndef Q3DBARS_p_H #define Q3DBARS_p_H -#include "bars3dshared_p.h" -#include "qdatavis3namespace.h" - -class QOpenGLPaintDevice; - -class QPoint; -class QSizeF; +#include "bars3dcontroller_p.h" +#include "qdatavis3denums.h" -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE class Q3DBars; class Q3DBarsPrivate : public QObject { public: - Q3DBarsPrivate(Q3DBars *q, QRect rect, GLuint fbohandle); + Q3DBarsPrivate(Q3DBars *q, QRect rect); ~Q3DBarsPrivate(); Q3DBars *q_ptr; - Bars3dShared *m_shared; + Bars3dController *m_shared; }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/engine/q3dmaps.cpp b/src/datavis3d/engine/q3dmaps.cpp index 0a1ca7ff..ffa5ed1b 100644 --- a/src/datavis3d/engine/q3dmaps.cpp +++ b/src/datavis3d/engine/q3dmaps.cpp @@ -1,89 +1,30 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #include "q3dmaps.h" #include "q3dmaps_p.h" -#include "camerahelper_p.h" -#include "qdataitem_p.h" -#include "qdatarow_p.h" -#include "qdataset_p.h" -#include "shaderhelper_p.h" -#include "objecthelper_p.h" -#include "texturehelper_p.h" -#include "theme_p.h" -#include "utils_p.h" -#include "drawer_p.h" +#include "maps3dcontroller_p.h" -#include <QOpenGLFunctions> -#include <QMatrix4x4> -#include <QOpenGLPaintDevice> -#include <QPainter> -#include <QScreen> #include <QMouseEvent> -#include <qmath.h> - #include <QDebug> -//#define DISPLAY_RENDER_SPEED - -// Uncommenting this draws the shadow map with wider FOV than scene itself, making the light -// seem to be closer to scene than it actually is. This way shadows look slightly better (to me anyway) -#define USE_WIDER_SHADOWS - -// You can verify that depth buffer drawing works correctly by uncommenting this. -// You should see the scene from where the light is -//#define SHOW_DEPTH_TEXTURE_SCENE - -#ifdef DISPLAY_RENDER_SPEED -#include <QTime> -#endif - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -//#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels - -const GLfloat gridLineWidth = 0.005f; -GLfloat distanceMod = 0.0f; -static QVector3D skipColor = QVector3D(255, 255, 255); // Selection texture's background color +QT_DATAVIS3D_BEGIN_NAMESPACE /*! * \class Q3DMaps @@ -104,8 +45,9 @@ static QVector3D skipColor = QVector3D(255, 255, 255); // Selection texture's ba * Constructs Q3DMaps. */ Q3DMaps::Q3DMaps() - : d_ptr(new Q3DMapsPrivate(this)) + : d_ptr(new Q3DMapsPrivate(this, geometry())) { + d_ptr->m_shared->initializeOpenGL(); } /*! @@ -118,840 +60,9 @@ Q3DMaps::~Q3DMaps() /*! * \internal */ -void Q3DMaps::initialize() -{ - // Initialize shaders -#if !defined(QT_OPENGL_ES_2) - if (d_ptr->m_shadowQuality > ShadowNone) { - if (!d_ptr->m_theme->m_uniformColor) { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadow")); - // Init the depth buffer (for shadows) - d_ptr->initDepthBuffer(); - } else { - if (!d_ptr->m_theme->m_uniformColor) { - d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), - QStringLiteral(":/shaders/fragmentTexture")); - } -#else - if (!d_ptr->m_theme->m_uniformColor) { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } - d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), // Same vertex shader ok for ES2 - QStringLiteral(":/shaders/fragmentTextureES2")); -#endif - d_ptr->initLabelShaders(QStringLiteral(":/shaders/vertexLabel"), - QStringLiteral(":/shaders/fragmentLabel")); - -#if !defined(QT_OPENGL_ES_2) - // Init depth shader (for shadows). Init in any case, easier to handle shadow activation if done via api. - d_ptr->initDepthShader(); -#endif - - // Init selection shader - d_ptr->initSelectionShader(); - - // Init the selection buffer - d_ptr->initSelectionBuffer(); - - // Load default mesh - d_ptr->loadBarMesh(); - - // Load background mesh - d_ptr->loadBackgroundMesh(); - - // Load grid line mesh - d_ptr->loadGridLineMesh(); - - // Load label mesh - d_ptr->loadLabelMesh(); - - // Set OpenGL features - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - -#if !defined(QT_OPENGL_ES_2) - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); -#endif - - // Set initial camera position - // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later - CameraHelper::setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 1.0f + 2.9f * zComp), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - - // Adjust to default rotation - setCameraPosition(d_ptr->m_horizontalRotation, d_ptr->m_verticalRotation, d_ptr->m_zoomLevel); - - // Set view port - glViewport(0, 0, width(), height()); - - // Set initialized -flag - d_ptr->m_isInitialized = true; - - d_ptr->m_drawer->initializeOpenGL(); - - // Update default light position -#ifndef USE_WIDER_SHADOWS - distanceMod = 1.0f; -#endif -} - -/*! - * \internal - */ void Q3DMaps::render() { - if (!d_ptr->m_isInitialized) - return; - -#ifdef DISPLAY_RENDER_SPEED - // For speed computation - static bool firstRender = true; - static QTime lastTime; - static GLint nbFrames = 0; - if (firstRender) { - lastTime.start(); - firstRender = false; - } - - // Measure speed (as milliseconds per frame) - nbFrames++; - if (lastTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago - qDebug() << qreal(lastTime.elapsed()) / qreal(nbFrames) << "ms/frame (=" << qreal(nbFrames) << "fps)"; - nbFrames = 0; - lastTime.restart(); - } -#endif - - // Draw scene - drawScene(); -} - -/*! - * \internal - */ -void Q3DMaps::drawScene() -{ - // Set clear color - QVector3D clearColor = Utils::vectorFromColor(d_ptr->m_theme->m_windowColor); - glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - static QVector3D selection = skipColor; - - // Specify viewport - glViewport(d_ptr->m_sceneViewPort.x(), d_ptr->m_sceneViewPort.y(), - d_ptr->m_sceneViewPort.width(), d_ptr->m_sceneViewPort.height()); - - // Set up projection matrix - QMatrix4x4 projectionMatrix; - projectionMatrix.perspective(45.0f, (GLfloat)d_ptr->m_sceneViewPort.width() - / (GLfloat)d_ptr->m_sceneViewPort.height(), 0.1f, 100.0f); - - // Calculate view matrix - QMatrix4x4 viewMatrix = CameraHelper::calculateViewMatrix(d_ptr->m_mousePos, - d_ptr->m_zoomLevel - * d_ptr->m_zoomAdjustment, - d_ptr->m_sceneViewPort.width(), - d_ptr->m_sceneViewPort.height()); - - // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) - QVector3D lightPos = CameraHelper::calculateLightPosition(defaultLightPos, 0.0f, distanceMod); - - // Map adjustment direction to model matrix scaling - GLfloat heightMultiplier = 0.0f; - GLfloat widthMultiplier = 0.0f; - GLfloat depthMultiplier = 0.0f; - GLfloat heightScaler = 0.0f; - GLfloat widthScaler = 0.0f; - GLfloat depthScaler = 0.0f; - switch (d_ptr->m_adjustDirection) { - case AdjustHeight: - widthMultiplier = 0.0f; - heightMultiplier = 1.0f; - depthMultiplier = 0.0f; - widthScaler = d_ptr->m_barThickness.x() / d_ptr->m_scaleFactor; - heightScaler = 0.0f; - depthScaler = d_ptr->m_barThickness.z() / d_ptr->m_scaleFactor; - break; - case AdjustWidth: - widthMultiplier = 1.0f; - heightMultiplier = 0.0f; - depthMultiplier = 0.0f; - widthScaler = 0.0f; - heightScaler = d_ptr->m_barThickness.y() / d_ptr->m_scaleFactor; - depthScaler = d_ptr->m_barThickness.z() / d_ptr->m_scaleFactor; - break; - case AdjustDepth: - widthMultiplier = 0.0f; - heightMultiplier = 0.0f; - depthMultiplier = 1.0f; - widthScaler = d_ptr->m_barThickness.x() / d_ptr->m_scaleFactor; - heightScaler = d_ptr->m_barThickness.y() / d_ptr->m_scaleFactor; - depthScaler = 0.0f; - break; - case AdjustRadius: - widthMultiplier = 1.0f; - heightMultiplier = 0.0f; - depthMultiplier = 1.0f; - widthScaler = 0.0f; - heightScaler = d_ptr->m_barThickness.y() / d_ptr->m_scaleFactor; - depthScaler = 0.0f; - break; - case AdjustAll: - widthMultiplier = 1.0f; - heightMultiplier = 1.0f; - depthMultiplier = 1.0f; - widthScaler = 0.0f; - heightScaler = 0.0f; - depthScaler = 0.0f; - break; - } - - // Introduce regardless of shadow quality to simplify logic - QMatrix4x4 depthViewMatrix; - QMatrix4x4 depthProjectionMatrix; - -#if !defined(QT_OPENGL_ES_2) - if (d_ptr->m_shadowQuality > ShadowNone) { - // Render scene into a depth texture for using with shadow mapping - // Bind depth shader - d_ptr->m_depthShader->bind(); - - // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. - glViewport(d_ptr->m_sceneViewPort.x(), d_ptr->m_sceneViewPort.y(), - d_ptr->m_sceneViewPort.width() * d_ptr->m_shadowQuality, - d_ptr->m_sceneViewPort.height() * d_ptr->m_shadowQuality); - - // Enable drawing to framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, d_ptr->m_depthFrameBuffer); - glClear(GL_DEPTH_BUFFER_BIT); - - // Set front face culling to reduce self-shadowing issues - glCullFace(GL_FRONT); - - // Get the depth view matrix - // It may be possible to hack lightPos here if we want to make some tweaks to shadow - depthViewMatrix.lookAt(lightPos, QVector3D(0.0f, -d_ptr->m_yAdjustment, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed - //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); - // Set the depth projection matrix -#ifdef USE_WIDER_SHADOWS - // Use this for a bit exaggerated shadows - depthProjectionMatrix.perspective(60.0f, (GLfloat)d_ptr->m_sceneViewPort.width() - / (GLfloat)d_ptr->m_sceneViewPort.height(), 3.0f, 100.0f); -#else - // Use these for normal shadows, with the light further away - depthProjectionMatrix = projectionMatrix; -#endif -#if 0 - // Draw background to depth buffer (You don't want to do this, except maybe for debugging purposes) - if (d_ptr->m_backgroundObj) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - - modelMatrix.translate(0.0f, -d_ptr->m_yAdjustment, zComp); - modelMatrix.scale(QVector3D(d_ptr->m_areaSize.width() / d_ptr->m_scaleFactor, - 1.0f, - d_ptr->m_areaSize.height() / d_ptr->m_scaleFactor)); - modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f); - - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - d_ptr->m_depthShader->setUniformValue(d_ptr->m_depthShader->MVP(), MVPMatrix); - - // 1st attribute buffer : vertices - glEnableVertexAttribArray(d_ptr->m_depthShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_backgroundObj->vertexBuf()); - glVertexAttribPointer(d_ptr->m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_backgroundObj->elementBuf()); - - // Draw the triangles - glDrawElements(GL_TRIANGLES, d_ptr->m_backgroundObj->indexCount(), GL_UNSIGNED_SHORT, - (void *)0); - - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glDisableVertexAttribArray(d_ptr->m_depthShader->posAtt()); - } -#endif - // Draw bars to depth buffer - for (int bar = 0; bar < d_ptr->m_data->d_ptr->row().size(); bar++) { - QDataItem *item = d_ptr->m_data->d_ptr->getItem(bar); - if (!item) - continue; - - GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer; - - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - - modelMatrix.translate(item->d_ptr->translation().x(), - heightMultiplier * barHeight + heightScaler - - d_ptr->m_yAdjustment, - item->d_ptr->translation().z()); - modelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler, - heightMultiplier * barHeight + heightScaler, - depthMultiplier * barHeight + depthScaler)); - - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - d_ptr->m_depthShader->setUniformValue(d_ptr->m_depthShader->MVP(), MVPMatrix); - - // 1st attribute buffer : vertices - glEnableVertexAttribArray(d_ptr->m_depthShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf()); - glVertexAttribPointer(d_ptr->m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_barObj->elementBuf()); - - // Draw the triangles - glDrawElements(GL_TRIANGLES, d_ptr->m_barObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); - - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glDisableVertexAttribArray(d_ptr->m_depthShader->posAtt()); - } - - // Disable drawing to framebuffer (= enable drawing to screen) - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - // Reset culling to normal - glCullFace(GL_BACK); - - // Release depth shader - d_ptr->m_depthShader->release(); - - // Revert to original viewport - glViewport(d_ptr->m_sceneViewPort.x(), d_ptr->m_sceneViewPort.y(), - d_ptr->m_sceneViewPort.width(), d_ptr->m_sceneViewPort.height()); - -#if 0 // Use this if you want to see what is being drawn to the framebuffer - // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it) - d_ptr->m_labelShader->bind(); - glEnable(GL_TEXTURE_2D); - QMatrix4x4 modelMatrix; - QMatrix4x4 viewmatrix; - viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.5f + zComp), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - modelMatrix.translate(0.0, 0.0, zComp); - QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; - d_ptr->m_labelShader->setUniformValue(d_ptr->m_labelShader->MVP(), MVPMatrix); - d_ptr->m_drawer->drawObject(d_ptr->m_labelShader, d_ptr->m_labelObj, - d_ptr->m_depthTexture); - glDisable(GL_TEXTURE_2D); - d_ptr->m_labelShader->release(); -#endif - } -#endif - -#if 1 - // Skip selection mode drawing if we're zoomed or have no selection mode - if (!d_ptr->m_zoomActivated && d_ptr->m_selectionMode > ModeNone) { - // Bind selection shader - d_ptr->m_selectionShader->bind(); - - // Draw bars to selection buffer - glBindFramebuffer(GL_FRAMEBUFFER, d_ptr->m_selectionFrameBuffer); - glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used - glClearColor(skipColor.x() / 255, skipColor.y() / 255, skipColor.z() / 255, 1.0f); // Set clear color to white (= skipColor) - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer - glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled - GLint barIdxRed = 0; - GLint barIdxGreen = 0; - GLint barIdxBlue = 0; - for (int bar = 0; bar < d_ptr->m_data->d_ptr->row().size(); bar++, barIdxRed++) { - QDataItem *item = d_ptr->m_data->d_ptr->getItem(bar); - if (!item) - continue; - - GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer; - - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - - modelMatrix.translate(item->d_ptr->translation().x(), - heightMultiplier * barHeight + heightScaler - - d_ptr->m_yAdjustment, - item->d_ptr->translation().z()); - modelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler, - heightMultiplier * barHeight + heightScaler, - depthMultiplier * barHeight + depthScaler)); - - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - - if (barIdxRed > 0 && barIdxRed % 256 == 0) { - barIdxRed = 0; - barIdxGreen++; - } - if (barIdxGreen > 0 && barIdxGreen % 256 == 0) { - barIdxGreen = 0; - barIdxBlue++; - } - if (barIdxBlue > 255) - qFatal("Too many objects"); - - QVector3D barColor = QVector3D((GLfloat)barIdxRed / 255.0f, - (GLfloat)barIdxGreen / 255.0f, - (GLfloat)barIdxBlue / 255.0f); - - d_ptr->m_selectionShader->setUniformValue(d_ptr->m_selectionShader->MVP(), - MVPMatrix); - d_ptr->m_selectionShader->setUniformValue(d_ptr->m_selectionShader->color(), - barColor); - - // 1st attribute buffer : vertices - glEnableVertexAttribArray(d_ptr->m_selectionShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf()); - glVertexAttribPointer(d_ptr->m_selectionShader->posAtt(), - 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_barObj->elementBuf()); - - // Draw the triangles - glDrawElements(GL_TRIANGLES, d_ptr->m_barObj->indexCount(), GL_UNSIGNED_SHORT, - (void *)0); - - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glDisableVertexAttribArray(d_ptr->m_selectionShader->posAtt()); - } - glEnable(GL_DITHER); - - // Read color under cursor - if (Q3DMapsPrivate::MouseOnScene == d_ptr->m_mousePressed) - selection = Utils::getSelection(d_ptr->m_mousePos, height()); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - // Release selection shader - d_ptr->m_selectionShader->release(); - -#if 0 // Use this if you want to see what is being drawn to the framebuffer - d_ptr->m_labelShader->bind(); - glDisable(GL_DEPTH_TEST); - glEnable(GL_TEXTURE_2D); - QMatrix4x4 modelMatrix; - QMatrix4x4 viewmatrix; - viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f + zComp), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - modelMatrix.translate(0.0, 0.0, zComp); - QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; - d_ptr->m_labelShader->setUniformValue(d_ptr->m_labelShader->MVP(), MVPMatrix); - d_ptr->m_drawer->drawObject(d_ptr->m_labelShader, d_ptr->m_labelObj, - d_ptr->m_selectionTexture); - glDisable(GL_TEXTURE_2D); - d_ptr->m_labelShader->release(); -#endif - } -#if 1 - // Bind bar shader - d_ptr->m_barShader->bind(); - - // Enable texture - glEnable(GL_TEXTURE_2D); - - // Draw bars - // TODO: Handle zoom by camera transformations - //if (!d_ptr->m_zoomActivated) - - bool barSelectionFound = false; - for (int bar = 0; bar < d_ptr->m_data->d_ptr->row().size(); bar++) { - QDataItem *item = d_ptr->m_data->d_ptr->getItem(bar); - if (!item) - continue; - - GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer; - - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; - - modelMatrix.translate(item->d_ptr->translation().x(), - heightMultiplier * barHeight + heightScaler - d_ptr->m_yAdjustment, - item->d_ptr->translation().z()); - modelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler, - heightMultiplier * barHeight + heightScaler, - depthMultiplier * barHeight + depthScaler)); - itModelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler, - heightMultiplier * barHeight + heightScaler, - depthMultiplier * barHeight + depthScaler)); - -#ifdef SHOW_DEPTH_TEXTURE_SCENE - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; -#else - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; -#endif - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - QVector3D baseColor = Utils::vectorFromColor(d_ptr->m_theme->m_baseColor); - QVector3D heightColor = Utils::vectorFromColor(d_ptr->m_theme->m_heightColor) - * barHeight; - - QVector3D barColor = baseColor + heightColor; - - GLfloat lightStrength = d_ptr->m_theme->m_lightStrength; - if (d_ptr->m_selectionMode > ModeNone) { - Q3DMapsPrivate::SelectionType selectionType = d_ptr->isSelected(bar, selection); - switch (selectionType) { - case Q3DMapsPrivate::SelectionBar: { - barColor = Utils::vectorFromColor(d_ptr->m_theme->m_highlightBarColor); - lightStrength = d_ptr->m_theme->m_highlightLightStrength; - // Insert data to QDataItem. We have no ownership, don't delete the previous one - if (!d_ptr->m_zoomActivated) { - d_ptr->m_selectedBar = item; - barSelectionFound = true; - } - break; - } - case Q3DMapsPrivate::SelectionNone: { - // Current bar is not selected, nor on a row or column - // do nothing - break; - } - default: { - // Unsupported selection mode - // do nothing - break; - } - } - } - - if (barHeight != 0) { - // Set shader bindings - d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightP(), lightPos); - d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->view(), viewMatrix); - d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix); - d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix); - d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->color(), barColor); - d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->ambientS(), - d_ptr->m_theme->m_ambientStrength); - -#if !defined(QT_OPENGL_ES_2) - if (d_ptr->m_shadowQuality > ShadowNone) { - // Set shadow shader bindings - d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->shadowQ(), - d_ptr->m_shadowQualityToShader); - d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->depth(), - depthMVPMatrix); - d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), - lightStrength / 10.0f); - - // Draw the object - d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_barObj, - 0, d_ptr->m_depthTexture); - } else -#endif - { - // Set shadowless shader bindings - d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), lightStrength); - - // Draw the object - d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_barObj); - } - } - } - - // Release bar shader - d_ptr->m_barShader->release(); -#if 1 - // Bind background shader - d_ptr->m_backgroundShader->bind(); - if (d_ptr->m_bgrHasAlpha) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - // Draw background - if (d_ptr->m_backgroundObj) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; - - modelMatrix.translate(0.0f, -d_ptr->m_yAdjustment, zComp); - modelMatrix.scale(QVector3D(d_ptr->m_areaSize.width() / d_ptr->m_scaleFactor, - 1.0f, - d_ptr->m_areaSize.height() / d_ptr->m_scaleFactor)); - modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f); - itModelMatrix.scale(QVector3D(d_ptr->m_areaSize.width() / d_ptr->m_scaleFactor, - 1.0f, - d_ptr->m_areaSize.height() / d_ptr->m_scaleFactor)); - -#ifdef SHOW_DEPTH_TEXTURE_SCENE - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; -#else - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; -#endif - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - // Set shader bindings - d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightP(), lightPos); - d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->view(), viewMatrix); - d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->model(), modelMatrix); - d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->nModel(), - itModelMatrix.inverted().transposed()); - d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->MVP(), MVPMatrix); - d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->ambientS(), - d_ptr->m_theme->m_ambientStrength * 3.0f); - -#if !defined(QT_OPENGL_ES_2) - if (d_ptr->m_shadowQuality > ShadowNone) { - // Set shadow shader bindings - d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->shadowQ(), - d_ptr->m_shadowQualityToShader); - d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->depth(), - depthMVPMatrix); - d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightS(), - d_ptr->m_theme->m_lightStrength / 25.0f); - - // Draw the object - d_ptr->m_drawer->drawObject(d_ptr->m_backgroundShader, d_ptr->m_backgroundObj, - d_ptr->m_bgrTexture, d_ptr->m_depthTexture); - } else -#endif - { - // Set shadowless shader bindings - d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightS(), - d_ptr->m_theme->m_lightStrength); - - // Draw the object - d_ptr->m_drawer->drawObject(d_ptr->m_backgroundShader, d_ptr->m_backgroundObj, - d_ptr->m_bgrTexture); - } - } - - // Disable textures - glDisable(GL_TEXTURE_2D); - if (d_ptr->m_bgrHasAlpha) - glDisable(GL_BLEND); - - // Release background shader - d_ptr->m_backgroundShader->release(); -#endif - - // Handle zoom activation and label drawing - if (!barSelectionFound) { - // We have no ownership, don't delete. Just NULL the pointer. - d_ptr->m_selectedBar = NULL; - //if (d_ptr->m_zoomActivated && Q3DMapsPrivate::MouseOnOverview == d_ptr->m_mousePressed) { - //d_ptr->m_sceneViewPort = QRect(0, 0, width(), height()); - //d_ptr->m_zoomActivated = false; - //} - } /*else if (d_ptr->m_selectionMode >= ModeZoomRow - && Q3DMapsPrivate::MouseOnScene == d_ptr->m_mousePressed) { - // Activate zoom mode - d_ptr->m_zoomActivated = true; - d_ptr->m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5); - - // Create label textures - for (int col = 0; col < d_ptr->m_zoomSelection->d_ptr->row().size(); col++) { - QDataItem *item = d_ptr->m_zoomSelection->d_ptr->getItem(col); - d_ptr->m_drawer->generateLabelTexture(item); - } - }*/ else { - // Print value of selected bar - static QDataItem *prevItem = d_ptr->m_selectedBar; - d_ptr->m_labelShader->bind(); - glDisable(GL_DEPTH_TEST); - glEnable(GL_TEXTURE_2D); - if (d_ptr->m_labelTransparency > TransparencyNone) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } -#ifndef DISPLAY_FULL_DATA_ON_SELECTION - // Draw just the value string of the selected bar - if (prevItem != d_ptr->m_selectedBar || d_ptr->m_updateLabels) { - d_ptr->m_drawer->generateLabelTexture(d_ptr->m_selectedBar); - prevItem = d_ptr->m_selectedBar; - } - - d_ptr->m_drawer->drawLabel(*d_ptr->m_selectedBar, d_ptr->m_selectedBar->d_ptr->label(), - viewMatrix, projectionMatrix, - QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer, - d_ptr->m_selectionMode, d_ptr->m_labelShader, - d_ptr->m_labelObj, true); -#else - static bool firstSelection = true; - // Draw the value string followed by row label and column label - LabelItem labelItem = d_ptr->m_selectedBar->d_ptr->selectionLabel(); - if (firstSelection || prevItem != d_ptr->m_selectedBar || d_ptr->m_updateLabels) { - QString labelText = d_ptr->m_selectedBar->d_ptr->valueStr(); - // if ((d_ptr->m_data->d_ptr->columnLabels().size() - // > d_ptr->m_selectedBar->d_ptr->position().y()) - // && (d_ptr->m_data->d_ptr->rowLabels().size() - // > d_ptr->m_selectedBar->d_ptr->position().x())) { - // labelText.append(QStringLiteral(" (")); - // labelText.append(d_ptr->m_data->d_ptr->rowLabels().at( - // d_ptr->m_selectedBar->d_ptr->position().x())); - // labelText.append(QStringLiteral(", ")); - // labelText.append(d_ptr->m_data->d_ptr->columnLabels().at( - // d_ptr->m_selectedBar->d_ptr->position().y())); - // labelText.append(QStringLiteral(")")); - // //qDebug() << labelText; - // } - d_ptr->m_drawer->generateLabelItem(&labelItem, labelText); - d_ptr->m_selectedBar->d_ptr->setSelectionLabel(labelItem); - prevItem = d_ptr->m_selectedBar; - firstSelection = false; - } - - d_ptr->m_drawer->drawLabel(*d_ptr->m_selectedBar, labelItem, viewMatrix, projectionMatrix, - QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer, - d_ptr->m_selectionMode, d_ptr->m_labelShader, - d_ptr->m_labelObj, true, false); -#endif - glDisable(GL_TEXTURE_2D); - if (d_ptr->m_labelTransparency > TransparencyNone) - glDisable(GL_BLEND); - glEnable(GL_DEPTH_TEST); - - // Release label shader - d_ptr->m_labelShader->release(); - - // Reset label update flag; they should have been updated when we get here - d_ptr->m_updateLabels = false; - } -#if 0 - // TODO: Calculations done temporarily here. When optimizing, move to after data set addition? Keep drawing of the labels here. - // Bind label shader - d_ptr->m_labelShader->bind(); - - glEnable(GL_TEXTURE_2D); - if (d_ptr->m_labelTransparency > TransparencyNone) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - // Calculate the positions for row and column labels and store them into QDataItems (and QDataRows?) - for (int row = 0; row != d_ptr->m_sampleCount.second; row += 1) { - // Go through all rows and get position of max+1 or min-1 column, depending on x flip - // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems - rowPos = (row + 1) * (d_ptr->m_barSpacing.height()); - barPos = 0; - GLfloat rotLabelX = -90.0f; - GLfloat rotLabelY = 0.0f; - Qt::AlignmentFlag alignment = Qt::AlignRight; - if (d_ptr->m_zFlipped) - rotLabelY = 180.0f; - if (d_ptr->m_xFlipped) { - barPos = (d_ptr->m_sampleCount.first + 1) * (d_ptr->m_barSpacing.width()); - alignment = Qt::AlignLeft; - } - QVector3D labelPos = QVector3D((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor, - -d_ptr->m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" - (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor - + zComp); - - // TODO: Try it; draw the label here - - // Create a data item - QDataItem *label = new QDataItem(); - label->d_ptr->setTranslation(labelPos); - if (d_ptr->m_data->d_ptr->rowLabelItems().size() > row) { - label->d_ptr->setLabel(d_ptr->m_data->d_ptr->rowLabelItems().at( - d_ptr->m_data->d_ptr->rowLabelItems().size() - row - 1)); - } - - //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << d_ptr->m_dataSet->d_ptr->rowLabels().at(row); - - d_ptr->m_drawer->drawLabel(*label, label->d_ptr->label(), viewMatrix, projectionMatrix, - QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), - QVector3D(rotLabelX, rotLabelY, 0.0f), d_ptr->m_heightNormalizer, - d_ptr->m_selectionMode, d_ptr->m_labelShader, - d_ptr->m_labelObj, true, true, LabelMid, alignment); - - delete label; - } - for (int bar = 0; bar != d_ptr->m_sampleCount.first; bar += 1) { - // Go through all columns and get position of max+1 or min-1 row, depending on z flip - // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems - barPos = (bar + 1) * (d_ptr->m_barSpacing.width()); - rowPos = 0; - GLfloat rotLabelX = -90.0f; - GLfloat rotLabelY = 90.0f; - Qt::AlignmentFlag alignment = Qt::AlignLeft; - if (d_ptr->m_xFlipped) - rotLabelY = -90.0f; - if (d_ptr->m_zFlipped) { - rowPos = (d_ptr->m_sampleCount.second + 1) * (d_ptr->m_barSpacing.height()); - alignment = Qt::AlignRight; - } - QVector3D labelPos = QVector3D((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor, - -d_ptr->m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" - (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor - + zComp); - - // TODO: Try it; draw the label here - - // Create a data item - QDataItem *label = new QDataItem(); - label->d_ptr->setTranslation(labelPos); - if (d_ptr->m_data->d_ptr->columnLabelItems().size() > bar) { - label->d_ptr->setLabel(d_ptr->m_data->d_ptr->columnLabelItems().at( - d_ptr->m_data->d_ptr->columnLabelItems().size() - - bar - 1)); - } - - //qDebug() << "labelPos, col" << bar + 1 << ":" << labelPos << d_ptr->m_dataSet->d_ptr->columnLabels().at(bar); - - d_ptr->m_drawer->drawLabel(*label, label->d_ptr->label(), viewMatrix, projectionMatrix, - QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), - QVector3D(rotLabelX, rotLabelY, 0.0f), d_ptr->m_heightNormalizer, - d_ptr->m_selectionMode, d_ptr->m_labelShader, - d_ptr->m_labelObj, true, true, LabelMid, alignment); - - delete label; - } - glDisable(GL_TEXTURE_2D); - if (d_ptr->m_labelTransparency > TransparencyNone) - glDisable(GL_BLEND); - - // Release label shader - d_ptr->m_labelShader->release(); -#endif -#endif -#endif + d_ptr->m_shared->render(); } #if defined(Q_OS_ANDROID) @@ -960,11 +71,7 @@ void Q3DMaps::drawScene() */ void Q3DMaps::mouseDoubleClickEvent(QMouseEvent *event) { - if (!d_ptr->m_zoomActivated) { - d_ptr->m_mousePressed = Q3DMapsPrivate::MouseOnScene; - // update mouse positions to prevent jumping when releasing or repressing a button - d_ptr->m_mousePos = event->pos(); - } + d_ptr->m_shared->mouseDoubleClickEvent(event); } /*! @@ -972,30 +79,7 @@ void Q3DMaps::mouseDoubleClickEvent(QMouseEvent *event) */ void Q3DMaps::touchEvent(QTouchEvent *event) { - static int prevDistance = 0; - - QList<QTouchEvent::TouchPoint> points; - points = event->touchPoints(); - - if (points.count() == 2) { - d_ptr->m_mousePressed = Q3DMapsPrivate::MouseOnPinch; - - QPointF distance = points.at(0).pos() - points.at(1).pos(); - int newDistance = distance.manhattanLength(); - int zoomRate = 1; - if (d_ptr->m_zoomLevel > 100) - zoomRate = 5; - if (newDistance > prevDistance) - d_ptr->m_zoomLevel += zoomRate; - else - d_ptr->m_zoomLevel -= zoomRate; - if (d_ptr->m_zoomLevel > 500) - d_ptr->m_zoomLevel = 500; - else if (d_ptr->m_zoomLevel < 10) - d_ptr->m_zoomLevel = 10; - prevDistance = newDistance; - //qDebug() << "distance" << distance.manhattanLength(); - } + d_ptr->m_shared->touchEvent(event); } #endif @@ -1004,40 +88,7 @@ void Q3DMaps::touchEvent(QTouchEvent *event) */ void Q3DMaps::mousePressEvent(QMouseEvent *event) { - if (Qt::LeftButton == event->button()) { - if (d_ptr->m_zoomActivated) { - //qDebug() << event->pos().x() << event->pos().y() << d_ptr->m_sceneViewPort << d_ptr->m_zoomViewPort; - if (event->pos().x() <= d_ptr->m_sceneViewPort.width() - && event->pos().y() <= d_ptr->m_sceneViewPort.height()) { - d_ptr->m_mousePressed = Q3DMapsPrivate::MouseOnOverview; - //qDebug() << "Mouse pressed on overview"; - } else { - d_ptr->m_mousePressed = Q3DMapsPrivate::MouseOnZoom; - //qDebug() << "Mouse pressed on zoom"; - } - } else { -#if !defined(Q_OS_ANDROID) - d_ptr->m_mousePressed = Q3DMapsPrivate::MouseOnScene; -#else - d_ptr->m_mousePressed = Q3DMapsPrivate::MouseRotating; -#endif - // update mouse positions to prevent jumping when releasing or repressing a button - d_ptr->m_mousePos = event->pos(); - //qDebug() << "Mouse pressed on scene"; - } - } else if (Qt::MiddleButton == event->button()) { - // reset rotations - d_ptr->m_mousePos = QPoint(0, 0); - } else if (Qt::RightButton == event->button()) { -#if !defined(Q_OS_ANDROID) - d_ptr->m_mousePressed = Q3DMapsPrivate::MouseRotating; -#else - d_ptr->m_mousePressed = Q3DMapsPrivate::MouseOnScene; -#endif - // update mouse positions to prevent jumping when releasing or repressing a button - d_ptr->m_mousePos = event->pos(); - } - CameraHelper::updateMousePos(d_ptr->m_mousePos); + d_ptr->m_shared->mousePressEvent(event, event->pos()); } /*! @@ -1045,13 +96,7 @@ void Q3DMaps::mousePressEvent(QMouseEvent *event) */ void Q3DMaps::mouseReleaseEvent(QMouseEvent *event) { - //qDebug() << "mouse button released" << event->button(); - if (Q3DMapsPrivate::MouseRotating == d_ptr->m_mousePressed) { - // update mouse positions to prevent jumping when releasing or repressing a button - d_ptr->m_mousePos = event->pos(); - CameraHelper::updateMousePos(event->pos()); - } - d_ptr->m_mousePressed = Q3DMapsPrivate::MouseNone; + d_ptr->m_shared->mouseReleaseEvent(event, event->pos()); } /*! @@ -1059,25 +104,7 @@ void Q3DMaps::mouseReleaseEvent(QMouseEvent *event) */ void Q3DMaps::mouseMoveEvent(QMouseEvent *event) { - if (Q3DMapsPrivate::MouseRotating == d_ptr->m_mousePressed) { - //qDebug() << "mouse moved while pressed" << event->pos(); - d_ptr->m_mousePos = event->pos(); - } -#if 0 - // TODO: Testi - laske kursorin sijainti scenessä - QPointF mouse3D((2.0f * event->pos().x() - width()) / height(), - 1.0f - (2.0f * event->pos().y()) / height()); - //qDebug() << "mouse position in scene" << mouse3D; - - // TODO: Testi laske focal point - GLfloat focalPoint = tan(45.0f / 2.0f); - - // TODO: Testi - laske viewmatriisin kerroin - QVector3D worldRay = QVector3D(0.0f, 0.0f, 0.0f) - - QVector3D(mouse3D.x(), mouse3D.y(), -focalPoint); - //qDebug() << "worldRay" << worldRay; - // multiply viewmatrix with this to get something? -#endif + d_ptr->m_shared->mouseMoveEvent(event, event->pos()); } /*! @@ -1085,16 +112,7 @@ void Q3DMaps::mouseMoveEvent(QMouseEvent *event) */ void Q3DMaps::wheelEvent(QWheelEvent *event) { - if (d_ptr->m_zoomLevel > 100) - d_ptr->m_zoomLevel += event->angleDelta().y() / 12; - else if (d_ptr->m_zoomLevel > 50) - d_ptr->m_zoomLevel += event->angleDelta().y() / 60; - else - d_ptr->m_zoomLevel += event->angleDelta().y() / 120; - if (d_ptr->m_zoomLevel > 500) - d_ptr->m_zoomLevel = 500; - else if (d_ptr->m_zoomLevel < 10) - d_ptr->m_zoomLevel = 10; + d_ptr->m_shared->wheelEvent(event); } /*! @@ -1103,195 +121,78 @@ void Q3DMaps::wheelEvent(QWheelEvent *event) void Q3DMaps::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); + d_ptr->m_shared->setWidth(width()); + d_ptr->m_shared->setHeight(height()); + d_ptr->m_shared->resizeNotify(); +} - // Set view port - if (d_ptr->m_zoomActivated) - d_ptr->m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5); - else - d_ptr->m_sceneViewPort = QRect(0, 0, width(), height()); - d_ptr->m_zoomViewPort = QRect(0, 0, width(), height()); - - // Calculate zoom level based on aspect ratio - GLfloat div; - GLfloat zoomAdjustment; - div = qMin(width(), height()); - zoomAdjustment = defaultRatio * ((width() / div) / (height() / div)); - //qDebug() << "zoom adjustment" << zoomAdjustment; - d_ptr->m_zoomAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f - - // Re-init selection buffer - d_ptr->initSelectionBuffer(); +// TODO: Document +// Size +void Q3DMaps::setWidth(const int width) +{ + d_ptr->m_shared->setWidth(width); + QWindow::setWidth(width); +} -#if !defined(QT_OPENGL_ES_2) - // Re-init depth buffer - if (d_ptr->m_isInitialized && d_ptr->m_shadowQuality > ShadowNone) - d_ptr->initDepthBuffer(); -#endif +void Q3DMaps::setHeight(const int height) +{ + d_ptr->m_shared->setHeight(height); + QWindow::setHeight(height); } void Q3DMaps::setBarSpecs(const QVector3D &thickness, AdjustmentDirection direction) { - d_ptr->m_barThickness = thickness; - d_ptr->m_adjustDirection = direction; + d_ptr->m_shared->setBarSpecs(thickness, direction); } -void Q3DMaps::setBarType(BarStyle style, bool smooth) +void Q3DMaps::setBarType(QDataVis::MeshStyle style, bool smooth) { - if (style == Bars) { - if (smooth) - d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/barSmooth"); - else - d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/bar"); - } else if (style == Pyramids) { - if (smooth) - d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/pyramidSmooth"); - else - d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/pyramid"); - } else if (style == Cones) { - if (smooth) - d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/coneSmooth"); - else - d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/cone"); - } else if (style == Cylinders) { - if (smooth) - d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/cylinderSmooth"); - else - d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/cylinder"); - } else if (style == BevelBars) { - if (smooth) - d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/bevelbarSmooth"); - else - d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/bevelbar"); - } else if (style == Spheres) { - if (smooth) - d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/sphereSmooth"); - else - d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/sphere"); - } - // Reload mesh data - if (d_ptr->m_isInitialized) - d_ptr->loadBarMesh(); + d_ptr->m_shared->setBarType(style, smooth); } void Q3DMaps::setMeshFileName(const QString &objFileName) { - d_ptr->m_objFile = objFileName; + d_ptr->m_shared->setMeshFileName(objFileName); } -void Q3DMaps::setCameraPreset(CameraPreset preset) +void Q3DMaps::setCameraPreset(QDataVis::CameraPreset preset) { - CameraHelper::setCameraPreset(preset); + d_ptr->m_shared->setCameraPreset(preset); } void Q3DMaps::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) { - d_ptr->m_horizontalRotation = qBound(-180.0f, horizontal, 180.0f); - d_ptr->m_verticalRotation = qBound(0.0f, vertical, 90.0f); - d_ptr->m_zoomLevel = qBound(10, distance, 500); - CameraHelper::setCameraRotation(QPointF(d_ptr->m_horizontalRotation, - d_ptr->m_verticalRotation)); - //qDebug() << "camera rotation set to" << d_ptr->m_horizontalRotation << d_ptr->m_verticalRotation; + d_ptr->m_shared->setCameraPosition(horizontal, vertical, distance); } -void Q3DMaps::setTheme(ColorTheme theme) +void Q3DMaps::setTheme(QDataVis::ColorTheme theme) { - d_ptr->m_theme->useTheme(theme); - d_ptr->m_drawer->setTheme(*d_ptr->m_theme); -#if !defined(QT_OPENGL_ES_2) - if (d_ptr->m_shadowQuality > ShadowNone) { - // Re-init shaders - if (!d_ptr->m_theme->m_uniformColor) { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - } else { - // Re-init shaders - if (!d_ptr->m_theme->m_uniformColor) { - d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - } -#else - if (!d_ptr->m_theme->m_uniformColor) { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } -#endif - d_ptr->m_updateLabels = true; + d_ptr->m_shared->setTheme(theme); } void Q3DMaps::setBarColor(QColor baseColor, QColor heightColor, bool uniform) { - d_ptr->m_theme->m_baseColor = baseColor; - d_ptr->m_theme->m_heightColor = heightColor; - if (d_ptr->m_theme->m_uniformColor != uniform) { -#if !defined(QT_OPENGL_ES_2) - if (d_ptr->m_shadowQuality > ShadowNone) { - // Re-init shaders - if (!d_ptr->m_theme->m_uniformColor) { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - } else { - // Re-init shaders - if (!d_ptr->m_theme->m_uniformColor) { - d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - } -#else - if (!d_ptr->m_theme->m_uniformColor) { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } -#endif - } - d_ptr->m_theme->m_uniformColor = uniform; + d_ptr->m_shared->setBarColor(baseColor, heightColor, uniform); } void Q3DMaps::setAreaSpecs(const QRect &areaRect, const QImage &image) { - d_ptr->calculateSceneScalingFactors(areaRect); - setImage(image); + d_ptr->m_shared->setAreaSpecs(areaRect, image); } void Q3DMaps::setImage(const QImage &image) { - d_ptr->m_bgrHasAlpha = image.hasAlphaChannel(); - if (d_ptr->m_bgrTexture) - glDeleteTextures(1, &d_ptr->m_bgrTexture); - d_ptr->m_bgrTexture = d_ptr->m_textureHelper->create2DTexture(image, true, true); + d_ptr->m_shared->setImage(image); } -void Q3DMaps::setSelectionMode(SelectionMode mode) +void Q3DMaps::setSelectionMode(QDataVis::SelectionMode mode) { - d_ptr->m_selectionMode = mode; - // Disable zoom if mode changes - //d_ptr->m_zoomActivated = false; - //d_ptr->m_sceneViewPort = QRect(0, 0, width(), height()); + d_ptr->m_shared->setSelectionMode(mode); } -SelectionMode Q3DMaps::selectionMode() +QDataVis::SelectionMode Q3DMaps::selectionMode() const { - return d_ptr->m_selectionMode; + return d_ptr->m_shared->selectionMode(); } void Q3DMaps::setWindowTitle(const QString &title) @@ -1299,478 +200,71 @@ void Q3DMaps::setWindowTitle(const QString &title) setTitle(title); } -QString Q3DMaps::windowTitle() +QString Q3DMaps::windowTitle() const { return title(); } void Q3DMaps::setFontSize(float fontsize) { - d_ptr->m_font.setPointSizeF(fontsize); - d_ptr->m_drawer->setFont(d_ptr->m_font); - d_ptr->m_updateLabels = true; + d_ptr->m_shared->setFontSize(fontsize); } -float Q3DMaps::fontSize() +float Q3DMaps::fontSize() const { - return d_ptr->m_font.pointSizeF(); + return d_ptr->m_shared->fontSize(); } void Q3DMaps::setFont(const QFont &font) { - d_ptr->m_font = font; - d_ptr->m_drawer->setFont(font); - d_ptr->m_updateLabels = true; -} - -QFont Q3DMaps::font() -{ - return d_ptr->m_font; -} - -void Q3DMaps::setLabelTransparency(LabelTransparency transparency) -{ - d_ptr->m_labelTransparency = transparency; - d_ptr->m_drawer->setTransparency(transparency); - d_ptr->m_updateLabels = true; -} - -LabelTransparency Q3DMaps::labelTransparency() -{ - return d_ptr->m_labelTransparency; + d_ptr->m_shared->setFont(font); } -void Q3DMaps::setShadowQuality(ShadowQuality quality) +QFont Q3DMaps::font() const { - d_ptr->m_shadowQuality = quality; - switch (quality) { - case ShadowLow: - //qDebug() << "ShadowLow"; - d_ptr->m_shadowQualityToShader = 33.3f; - break; - case ShadowMedium: - //qDebug() << "ShadowMedium"; - d_ptr->m_shadowQualityToShader = 100.0f; - break; - case ShadowHigh: - //qDebug() << "ShadowHigh"; - d_ptr->m_shadowQualityToShader = 200.0f; - break; - default: - d_ptr->m_shadowQualityToShader = 0.0f; - break; - } - if (d_ptr->m_isInitialized) { -#if !defined(QT_OPENGL_ES_2) - if (d_ptr->m_shadowQuality > ShadowNone) { - // Re-init depth buffer - d_ptr->initDepthBuffer(); - // Re-init shaders - if (!d_ptr->m_theme->m_uniformColor) { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadow")); - } else { - // Re-init shaders - if (!d_ptr->m_theme->m_uniformColor) { - d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), - QStringLiteral(":/shaders/fragmentTexture")); - } -#else - if (!d_ptr->m_theme->m_uniformColor) { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - d_ptr->initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } - d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), // Same vertex shader ok for ES2 - QStringLiteral(":/shaders/fragmentTextureES2")); -#endif - } + return d_ptr->m_shared->font(); } -ShadowQuality Q3DMaps::shadowQuality() +void Q3DMaps::setLabelTransparency(QDataVis::LabelTransparency transparency) { - return d_ptr->m_shadowQuality; + d_ptr->m_shared->setLabelTransparency(transparency); } -bool Q3DMaps::addDataItem(QDataItem* dataItem) +QDataVis::LabelTransparency Q3DMaps::labelTransparency() const { - // Check validity - if (!d_ptr->isValid(*dataItem)) - return false; - // Convert position to translation - d_ptr->calculateTranslation(dataItem); - // Add item - d_ptr->m_data->addItem(dataItem); - // Get the limits - QPair<GLfloat, GLfloat> limits = d_ptr->m_data->d_ptr->limitValues(); - d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); - d_ptr->calculateHeightAdjustment(limits); - return true; + return d_ptr->m_shared->labelTransparency(); } -bool Q3DMaps::addData(const QVector<QDataItem*> &data) +QDataVis::ShadowQuality Q3DMaps::setShadowQuality(QDataVis::ShadowQuality quality) { - // Convert to QDataRow - for (int i = 0; i < data.size(); i++) { - QDataItem *item = data.at(i); - // Check validity - if (!d_ptr->isValid(*item)) { - return false; - } else { - // Convert position to translation - d_ptr->calculateTranslation(item); - // Add item - d_ptr->m_data->addItem(item); - } - } - // Get the limits - QPair<GLfloat, GLfloat> limits = d_ptr->m_data->d_ptr->limitValues(); - d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); - d_ptr->calculateHeightAdjustment(limits); - return true; + return d_ptr->m_shared->setShadowQuality(quality); } -bool Q3DMaps::addData(const QDataRow &dataRow) +QDataVis::ShadowQuality Q3DMaps::shadowQuality() const { - for (int itemIdx = 0; itemIdx < dataRow.d_ptr->row().size(); itemIdx++) { - QDataItem *item = dataRow.d_ptr->getItem(itemIdx); - // Check validity - if (!d_ptr->isValid(*item)) { - return false; - } else { - // Convert position to translation - d_ptr->calculateTranslation(item); - // Add item - d_ptr->m_data->addItem(item); - } - } - // Get the limits - QPair<GLfloat, GLfloat> limits = d_ptr->m_data->d_ptr->limitValues(); - d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); - d_ptr->calculateHeightAdjustment(limits); - return true; + return d_ptr->m_shared->shadowQuality(); } -bool Q3DMaps::setData(const QVector<QDataItem*> &dataRow) +void Q3DMaps::setDataProxy(QMapDataProxy *proxy) { - // Delete previous data - delete d_ptr->m_data; - // Convert to QDataRow - d_ptr->m_data = new QDataRow(); - for (int i = 0; i < dataRow.size(); i++) { - QDataItem *item = dataRow.at(i); - // Check validity - if (!d_ptr->isValid(*item)) { - return false; - } else { - // Convert position to translation - d_ptr->calculateTranslation(item); - // Add item - d_ptr->m_data->addItem(item); - } - } - // Get the limits - QPair<GLfloat, GLfloat> limits = d_ptr->m_data->d_ptr->limitValues(); - d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); - d_ptr->calculateHeightAdjustment(limits); - return true; + d_ptr->m_shared->setDataProxy(proxy); } -bool Q3DMaps::setData(QDataRow *dataRow) +QMapDataProxy *Q3DMaps::dataProxy() { - // Check validity - for (int i = 0; i < dataRow->d_ptr->row().size(); i++) { - if (!d_ptr->isValid(*dataRow->d_ptr->row().at(i))) - return false; - else - d_ptr->calculateTranslation(dataRow->d_ptr->row()[i]); - } - // Delete previous data - delete d_ptr->m_data; - // Set give data as new data - d_ptr->m_data = dataRow; - // Get the limits - QPair<GLfloat, GLfloat> limits = d_ptr->m_data->d_ptr->limitValues(); - d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); - d_ptr->calculateHeightAdjustment(limits); - return true; + return d_ptr->m_shared->dataProxy(); } -Q3DMapsPrivate::Q3DMapsPrivate(Q3DMaps *q) +Q3DMapsPrivate::Q3DMapsPrivate(Q3DMaps *q, const QRect &rect) : q_ptr(q), - m_paintDevice(0), - m_barShader(0), - m_depthShader(0), - m_selectionShader(0), - m_backgroundShader(0), - m_labelShader(0), - m_barObj(0), - m_backgroundObj(0), - m_gridLineObj(0), - m_labelObj(0), - m_objFile(QStringLiteral(":/defaultMeshes/bar")), - m_mousePressed(MouseNone), - m_mousePos(QPoint(0, 0)), - m_zoomLevel(100), - m_zoomAdjustment(1.0f), - m_horizontalRotation(0.0f), - m_verticalRotation(45.0f), - m_barThickness(QVector3D(1.0f, 0.0f, 1.0f)), - m_heightNormalizer(0.0f), - m_yAdjustment(0.0f), - m_scaleFactor(1.0f), - m_theme(new Theme()), - m_isInitialized(false), - m_selectionMode(ModeBar), - m_selectedBar(0), - m_data(new QDataRow()), - m_axisLabelX(QStringLiteral("X")), - m_axisLabelZ(QStringLiteral("Z")), - m_axisLabelY(QStringLiteral("Y")), - m_sceneViewPort(0, 0, q->width(), q->height()), - m_zoomViewPort(0, 0, q->width(), q->height()), - m_zoomActivated(false), - m_textureHelper(new TextureHelper()), - m_labelTransparency(TransparencyFromTheme), - m_font(QFont(QStringLiteral("Arial"))), - m_drawer(new Drawer(*m_theme, m_font, m_labelTransparency)), - m_areaSize(QSizeF(1.0f, 1.0f)), - m_bgrTexture(0), - m_depthTexture(0), - m_selectionTexture(0), - m_depthFrameBuffer(0), - m_selectionFrameBuffer(0), - m_selectionDepthBuffer(0), - m_updateLabels(true), - m_shadowQuality(ShadowLow), - m_shadowQualityToShader(33.3f), - m_bgrHasAlpha(false) + m_shared(new Maps3DController(rect)) { - //m_data->d_ptr->setDrawer(m_drawer); - //QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Q3DMapsPrivate::updateTextures); } Q3DMapsPrivate::~Q3DMapsPrivate() { - m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); - m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); - m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); - m_textureHelper->deleteTexture(&m_selectionTexture); - m_textureHelper->deleteTexture(&m_bgrTexture); - delete m_data; - delete m_barShader; - delete m_selectionShader; - delete m_backgroundShader; - delete m_barObj; - delete m_backgroundObj; - delete m_gridLineObj; - delete m_textureHelper; - delete m_drawer; -} - -void Q3DMapsPrivate::loadBarMesh() -{ - if (m_barObj) - delete m_barObj; - m_barObj = new ObjectHelper(m_objFile); - m_barObj->load(); -} - -void Q3DMapsPrivate::loadBackgroundMesh() -{ - if (m_backgroundObj) - delete m_backgroundObj; - m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); - m_backgroundObj->load(); -} - -void Q3DMapsPrivate::loadGridLineMesh() -{ - if (m_gridLineObj) - delete m_gridLineObj; - m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar")); - m_gridLineObj->load(); -} - -void Q3DMapsPrivate::loadLabelMesh() -{ - if (m_labelObj) - delete m_labelObj; - m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); - m_labelObj->load(); -} - -void Q3DMapsPrivate::initShaders(const QString &vertexShader, const QString &fragmentShader) -{ - if (m_barShader) - delete m_barShader; - m_barShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader); - m_barShader->initialize(); -} - -void Q3DMapsPrivate::initSelectionShader() -{ - if (m_selectionShader) - delete m_selectionShader; - m_selectionShader = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/vertexSelection"), - QStringLiteral(":/shaders/fragmentSelection")); - m_selectionShader->initialize(); -} - -void Q3DMapsPrivate::initSelectionBuffer() -{ - if (m_selectionTexture) { - - m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); - m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); - m_textureHelper->deleteTexture(&m_selectionTexture); - } - m_selectionTexture = m_textureHelper->createSelectionTexture(q_ptr->size(), - m_selectionFrameBuffer, - m_selectionDepthBuffer); -} - -#if !defined(QT_OPENGL_ES_2) -void Q3DMapsPrivate::initDepthShader() -{ - if (m_depthShader) - delete m_depthShader; - m_depthShader = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/vertexDepth"), - QStringLiteral(":/shaders/fragmentDepth")); - m_depthShader->initialize(); -} - -void Q3DMapsPrivate::initDepthBuffer() -{ - if (m_depthTexture) { - m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); - m_textureHelper->deleteTexture(&m_depthTexture); - } - m_depthTexture = m_textureHelper->createDepthTexture(q_ptr->size(), m_depthFrameBuffer, - m_shadowQuality); -} -#endif - -void Q3DMapsPrivate::initBackgroundShaders(const QString &vertexShader, - const QString &fragmentShader) -{ - if (m_backgroundShader) - delete m_backgroundShader; - m_backgroundShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader); - m_backgroundShader->initialize(); -} - -void Q3DMapsPrivate::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) -{ - if (m_labelShader) - delete m_labelShader; - m_labelShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader); - // m_labelShader = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/testDepthVert"), - // QStringLiteral(":/shaders/testDepthFrag")); - m_labelShader->initialize(); -} - -void Q3DMapsPrivate::updateTextures() -{ - // Drawer has changed; this flag needs to be checked when checking if we need to update labels - m_updateLabels = true; -} - -void Q3DMapsPrivate::calculateSceneScalingFactors(const QRect &areaRect) -{ - m_areaSize = areaRect.size(); - // Calculate scaling factor so that we can be sure the whole area fits to positive z space - if (zComp > 1.0f) - m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()) / zComp; - else - m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()); - //qDebug() << "scaleFactor" << m_scaleFactor; -} - -void Q3DMapsPrivate::calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits) -{ - // 2.0f = max difference between minimum and maximum value after scaling with m_heightNormalizer - m_yAdjustment = 2.0f - ((limits.second - limits.first) / m_heightNormalizer); - //qDebug() << m_yAdjustment; -} - -void Q3DMapsPrivate::calculateTranslation(QDataItem *item) -{ - // We need to convert position (which is in coordinates), to translation (which has origin in the center and is scaled) - // -> move pos(center, center) to trans(0, 0) and pos(0, 0) to trans(left, top) - GLfloat xTrans = 2.0f * (item->d_ptr->position().x() - (m_areaSize.width() / 2.0f)) - / m_scaleFactor; - GLfloat zTrans = 2.0f * (item->d_ptr->position().y() - (m_areaSize.height() / 2.0f)) - / m_scaleFactor; - //qDebug() << "x, y" << item->d_ptr->position().x() << item->d_ptr->position().y(); - item->d_ptr->setTranslation(QVector3D(xTrans, 0.0f, zTrans + zComp)); - //qDebug() << item->d_ptr->translation(); -} - -Q3DMapsPrivate::SelectionType Q3DMapsPrivate::isSelected(GLint bar, const QVector3D &selection) -{ - GLubyte barIdxRed = 0; - GLubyte barIdxGreen = 0; - GLubyte barIdxBlue = 0; - //static QVector3D prevSel = selection; // TODO: For debugging - SelectionType isSelectedType = SelectionNone; - - if (selection == skipColor) - return isSelectedType; // skip window - - if (bar <= 255) { - barIdxRed = bar; - } else if (bar <= 65535) { - barIdxGreen = bar / 256; - barIdxRed = bar % 256; - } else { - barIdxBlue = bar / 65535; - barIdxGreen = bar % 65535; - barIdxRed = bar % 256; - } - - QVector3D current = QVector3D(barIdxRed, barIdxGreen, barIdxBlue); - - // TODO: For debugging - //if (selection != prevSel) { - // qDebug() << selection.x() << selection .y() << selection.z(); - // prevSel = selection; - //} - - if (current == selection) - isSelectedType = SelectionBar; - - return isSelectedType; -} - -bool Q3DMapsPrivate::isValid(const QDataItem &item) -{ - bool retval = true; - if (item.d_ptr->value() < 0) { - qCritical("Data item value out of range"); - retval = false; - } else if (item.d_ptr->position().x() < 0 || item.d_ptr->position().x() > m_areaSize.width()) { - qCritical("Data item x position out of range"); - retval = false; - } else if (item.d_ptr->position().y() < 0 || item.d_ptr->position().y() > m_areaSize.height()) { - qCritical("Data item y position out of range"); - retval = false; - } - return retval; + qDebug() << "Destroying Q3DMapsPrivate"; + delete m_shared; } -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dmaps.h b/src/datavis3d/engine/q3dmaps.h index 67c8860b..195b91e0 100644 --- a/src/datavis3d/engine/q3dmaps.h +++ b/src/datavis3d/engine/q3dmaps.h @@ -1,66 +1,40 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #ifndef Q3DMAPS_H #define Q3DMAPS_H -#include "QtDataVis3D/qdatavis3dglobal.h" -#include "QtDataVis3D/qdatavis3namespace.h" -#include "q3dwindow.h" +#include <QtDataVis3D/qdatavis3denums.h> +#include <QtDataVis3D/q3dwindow.h> #include <QFont> +#include <QVector3D> -class QOpenGLShaderProgram; class QImage; class QRect; -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE +class Maps3DController; class Q3DMapsPrivate; -class QDataItem; -class QDataRow; -class QDataSet; -class LabelItem; +class QMapDataProxy; -class QTENTERPRISE_DATAVIS3D_EXPORT Q3DMaps : public Q3DWindow +class QT_DATAVIS3D_EXPORT Q3DMaps : public Q3DWindow { Q_OBJECT Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) @@ -68,6 +42,7 @@ class QTENTERPRISE_DATAVIS3D_EXPORT Q3DMaps : public Q3DWindow Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) public: + enum AdjustmentDirection { AdjustHeight = 0, // map value to y AdjustWidth, // map value to x @@ -80,82 +55,72 @@ public: explicit Q3DMaps(); ~Q3DMaps(); - // Add data item. New data item is appended to old data. - // ownership of data is transferred - Q_INVOKABLE bool addDataItem(QDataItem *dataItem); - - // Add data set. New data is appended to old data. - // ownership of data is transferred - Q_INVOKABLE bool addData(const QVector<QDataItem*> &data); - // ownership of data is transferred - Q_INVOKABLE bool addData(const QDataRow &data); - - // Add data set. Old data is deleted. - // ownership of data is transferred - Q_INVOKABLE bool setData(const QVector<QDataItem*> &data); - // ownership of data is transferred - Q_INVOKABLE bool setData(QDataRow *data); + void setWidth(const int width); + void setHeight(const int height); // bar specifications; base thickness in x, y and z, enum to indicate which direction is increased with value // TODO: Start using thickness also in adjustment direction; use it as a relative value. // For example, in AdjustAll mode setting thickness to (0.1f, 1.0f, 0.5f) would apply value to // x at 10%, y at 100% and z at 50%. If a dimension is not included, given thickness states its absolute value. - Q_INVOKABLE void setBarSpecs(const QVector3D &thickness = QVector3D(1.0f, 1.0f, 1.0f), - AdjustmentDirection direction = AdjustHeight); + void setBarSpecs(const QVector3D &thickness = QVector3D(1.0f, 1.0f, 1.0f), + AdjustmentDirection direction = AdjustHeight); // bar type; bars (=cubes), pyramids, cones, cylinders, balls, etc. - Q_INVOKABLE void setBarType(BarStyle style, bool smooth = false); + void setBarType(QDataVis::MeshStyle style, bool smooth = false); // override bar type with own mesh - Q_INVOKABLE void setMeshFileName(const QString &objFileName); + void setMeshFileName(const QString &objFileName); // Select preset camera placement - Q_INVOKABLE void setCameraPreset(CameraPreset preset); + void setCameraPreset(QDataVis::CameraPreset preset); // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and // vertical (0...90) angles and distance in percentage (10...500)) - Q_INVOKABLE void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); + void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); // Set theme (bar colors, shaders, window color, background colors, light intensity and text colors are affected) - Q_INVOKABLE void setTheme(ColorTheme theme); + void setTheme(QDataVis::ColorTheme theme); // Set color if you don't want to use themes. Set uniform to false if you want the (height) color to change from bottom to top - Q_INVOKABLE void setBarColor(QColor baseColor, QColor heightColor, bool uniform = true); + void setBarColor(QColor baseColor, QColor heightColor, bool uniform = true); // Set area specs - Q_INVOKABLE void setAreaSpecs(const QRect &areaRect, const QImage &image); + void setAreaSpecs(const QRect &areaRect, const QImage &image); // Set area image - Q_INVOKABLE void setImage(const QImage &image); + void setImage(const QImage &image); // TODO: light placement API // Change selection mode; single bar, bar and row, bar and column, or all - void setSelectionMode(SelectionMode mode); - SelectionMode selectionMode(); + void setSelectionMode(QDataVis::SelectionMode mode); + QDataVis::SelectionMode selectionMode() const; // Set window title void setWindowTitle(const QString &title); - QString windowTitle(); + QString windowTitle() const; // Font size adjustment void setFontSize(float fontsize); - float fontSize(); + float fontSize() const; // Set font void setFont(const QFont &font); - QFont font(); + QFont font() const; // Label transparency adjustment - void setLabelTransparency(LabelTransparency transparency); - LabelTransparency labelTransparency(); + void setLabelTransparency(QDataVis::LabelTransparency transparency); + QDataVis::LabelTransparency labelTransparency() const; // Adjust shadow quality - void setShadowQuality(ShadowQuality quality); - ShadowQuality shadowQuality(); + QDataVis::ShadowQuality setShadowQuality(QDataVis::ShadowQuality quality); + QDataVis::ShadowQuality shadowQuality() const; + + // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. + void setDataProxy(QMapDataProxy *proxy); + QMapDataProxy *dataProxy(); protected: - void initialize(); void render(); #if defined(Q_OS_ANDROID) @@ -169,11 +134,10 @@ protected: void resizeEvent(QResizeEvent *event); private: - void drawScene(); QScopedPointer<Q3DMapsPrivate> d_ptr; - Q_DISABLE_COPY(Q3DMaps); + Q_DISABLE_COPY(Q3DMaps) }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/engine/q3dmaps_p.h b/src/datavis3d/engine/q3dmaps_p.h index 4c94d85e..166ed8f7 100644 --- a/src/datavis3d/engine/q3dmaps_p.h +++ b/src/datavis3d/engine/q3dmaps_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,123 +29,23 @@ #ifndef Q3DMAPS_P_H #define Q3DMAPS_P_H -#include "qdatavis3dglobal.h" -#include "qdatavis3namespace.h" -#include <QOpenGLFunctions> -#include <QFont> - -class QOpenGLPaintDevice; - -class QPoint; -class QSizeF; +#include "maps3dcontroller_p.h" +#include "qdatavis3denums.h" -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE class Q3DMaps; -class QDataItem; -class QDataRow; -class QDataSet; -class ShaderHelper; -class ObjectHelper; -class TextureHelper; -class Theme; -class Drawer; class Q3DMapsPrivate : public QObject { public: - enum SelectionType { - SelectionNone = 0, - SelectionBar, - SelectionRow, - SelectionColumn - }; - - enum MousePressType { - MouseNone = 0, - MouseOnScene, - MouseOnOverview, - MouseOnZoom, - MouseRotating, - MouseOnPinch - }; - -public: - Q3DMapsPrivate(Q3DMaps *q); + Q3DMapsPrivate(Q3DMaps *q, const QRect &rect); ~Q3DMapsPrivate(); - void loadBarMesh(); - void loadBackgroundMesh(); - void loadGridLineMesh(); - void loadLabelMesh(); - void initShaders(const QString &vertexShader, const QString &fragmentShader); - void initSelectionShader(); - void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); - void initLabelShaders(const QString &vertexShader, const QString &fragmentShader); - void initSelectionBuffer(); -#if !defined(QT_OPENGL_ES_2) - void initDepthShader(); - void initDepthBuffer(); -#endif - void updateTextures(); - void calculateSceneScalingFactors(const QRect &areaRect); - void calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits); - void calculateTranslation(QDataItem *item); - SelectionType isSelected(GLint bar, const QVector3D &selection); - bool isValid(const QDataItem &item); - Q3DMaps *q_ptr; - - QOpenGLPaintDevice *m_paintDevice; - ShaderHelper *m_barShader; - ShaderHelper *m_depthShader; - ShaderHelper *m_selectionShader; - ShaderHelper *m_backgroundShader; - ShaderHelper *m_labelShader; - ObjectHelper *m_barObj; - ObjectHelper *m_backgroundObj; - ObjectHelper *m_gridLineObj; - ObjectHelper *m_labelObj; - QString m_objFile; - MousePressType m_mousePressed; - QPoint m_mousePos; - GLint m_zoomLevel; - GLfloat m_zoomAdjustment; - GLfloat m_horizontalRotation; - GLfloat m_verticalRotation; - QVector3D m_barThickness; - GLfloat m_heightNormalizer; - GLfloat m_yAdjustment; - GLfloat m_scaleFactor; - Theme *m_theme; - bool m_isInitialized; - SelectionMode m_selectionMode; - QDataItem *m_selectedBar; - QDataRow *m_data; - QString m_axisLabelX; - QString m_axisLabelZ; - QString m_axisLabelY; - QRect m_sceneViewPort; - QRect m_zoomViewPort; - bool m_zoomActivated; - TextureHelper *m_textureHelper; - LabelTransparency m_labelTransparency; - QFont m_font; - Drawer *m_drawer; - QSizeF m_areaSize; - GLuint m_bgrTexture; - GLuint m_depthTexture; - GLuint m_selectionTexture; - GLuint m_depthFrameBuffer; - GLuint m_selectionFrameBuffer; - GLuint m_selectionDepthBuffer; - bool m_updateLabels; - Q3DMaps::AdjustmentDirection m_adjustDirection; - ShadowQuality m_shadowQuality; - GLfloat m_shadowQualityToShader; - bool m_bgrHasAlpha; + Maps3DController *m_shared; }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/engine/q3dscatter.cpp b/src/datavis3d/engine/q3dscatter.cpp new file mode 100644 index 00000000..a9c4a1b0 --- /dev/null +++ b/src/datavis3d/engine/q3dscatter.cpp @@ -0,0 +1,463 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "q3dscatter.h" +#include "q3dscatter_p.h" +#include "scatter3dcontroller_p.h" +#include "qvalueaxis.h" + +#include <QMouseEvent> + +#include <QDebug> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +/*! + * \class Q3DScatter + * \inmodule QtDataVis3D + * \brief The Q3DScatter class provides methods for rendering 3D scatter graphs. + * \since 1.0.0 + * + * This class enables developers to render bar graphs in 3D and to view them by rotating the scene + * freely. Rotation is done by holding down the right mouse button and moving the mouse. Zooming + * is done by mouse wheel. Selection, if enabled, is done by left mouse button. The scene can be + * reset to default camera view by clicking mouse wheel. In touch devices rotation is done + * by tap-and-move, selection by tap-and-hold and zoom by pinch. + * + * Methods are provided for changing bar types, themes, bar selection modes and so on. See the + * methods for more detailed descriptions. + * + * \section1 How to construct a minimal Q3DScatter chart + * + * After constructing Q3DScatter, you need to set up sample space using setupSampleSpace(). Let's + * set the sample space to 5 rows and 5 columns: + * + * \snippet doc_src_q3dscatter_construction.cpp 0 + * + * Now Q3DScatter is ready to receive data to be rendered. Add one row of 5 floats into the data + * set: + * + * \snippet doc_src_q3dscatter_construction.cpp 1 + * + * \note We set the sample space to 5 x 5, but we are inserting only one row of data. This is ok, + * the rest of the rows will just be blank. + * + * Finally you will need to set it visible: + * + * \snippet doc_src_q3dscatter_construction.cpp 2 + * + * The complete code needed to create and display this chart is: + * + * \snippet doc_src_q3dscatter_construction.cpp 3 + * + * And this is what those few lines of code produce: + * + * \image q3dscatter-minimal.png + * + * The scene can be rotated and zoomed into, but no other interaction is included in this minimal + * code example. You can learn more by familiarizing yourself with the examples provided, like + * the \l{Rainfall Example} or the \l{Widget Example}. + * + * \sa Q3DMaps, {Qt Data Visualization 3D C++ Classes} + */ + +/*! + * Constructs a new 3D scatter window. + */ +Q3DScatter::Q3DScatter() + : d_ptr(new Q3DScatterPrivate(this, geometry())) +{ + d_ptr->m_shared->initializeOpenGL(); + QObject::connect(d_ptr->m_shared, &Scatter3DController::shadowQualityChanged, this, + &Q3DScatter::handleShadowQualityUpdate); +} + +/*! + * Destroys the 3D scatter window. + */ +Q3DScatter::~Q3DScatter() +{ +} + +/*! + * \internal + */ +void Q3DScatter::render() +{ + d_ptr->m_shared->synchDataToRenderer(); + d_ptr->m_shared->render(); +} + +void Q3DScatter::handleShadowQualityUpdate(QDataVis::ShadowQuality quality) +{ + emit shadowQualityChanged(quality); +} + +#if defined(Q_OS_ANDROID) +/*! + * \internal + */ +void Q3DScatter::mouseDoubleClickEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseDoubleClickEvent(event); +} + +/*! + * \internal + */ +void Q3DScatter::touchEvent(QTouchEvent *event) +{ + d_ptr->m_shared->touchEvent(event); +} +#endif + +/*! + * \internal + */ +void Q3DScatter::mousePressEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mousePressEvent(event, event->pos()); +} + +/*! + * \internal + */ +void Q3DScatter::mouseReleaseEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseReleaseEvent(event, event->pos()); +} + +/*! + * \internal + */ +void Q3DScatter::mouseMoveEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseMoveEvent(event, event->pos()); +} + +/*! + * \internal + */ +void Q3DScatter::wheelEvent(QWheelEvent *event) +{ + d_ptr->m_shared->wheelEvent(event); +} + +/*! + * \internal + */ +void Q3DScatter::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + d_ptr->m_shared->setSize(width(), height()); +} + +// TODO: Document +// Size +void Q3DScatter::setWidth(const int width) +{ + d_ptr->m_shared->setWidth(width); + QWindow::setWidth(width); +} + +void Q3DScatter::setHeight(const int height) +{ + d_ptr->m_shared->setHeight(height); + QWindow::setHeight(height); +} + +/*! + * \a style One of the values in \c QDataVis::MeshStyle. \c Spheres by default. + * + * \a smooth A flag to set shading to smooth. \c false by default. + * + * Sets the object type to one of the supplied ones. + * + * \sa setMeshFileName() + */ +void Q3DScatter::setObjectType(QDataVis::MeshStyle style, bool smooth) +{ + d_ptr->m_shared->setObjectType(style, smooth); +} + +/*! + * \a preset Move camera to a predefined position from \c QDataVis::CameraPreset. + * + * Moves camera to a predefined position. + */ +void Q3DScatter::setCameraPreset(QDataVis::CameraPreset preset) +{ + d_ptr->m_shared->setCameraPreset(preset); +} + +/*! + * \a horizontal Horizontal angle for camera. + * + * \a vertical Vertical angle for camera. + * + * \a distance Distance from the center. \c 100 by default. + * + * Move camera to a wanted position based on horizontal and veritcal angles. Angles are limited + * to -180...180 in horizontal direction and -90...90 in vertical. + * Distance is adjustable between 10 and 500. + */ +void Q3DScatter::setCameraPosition(qreal horizontal, qreal vertical, int distance) +{ + d_ptr->m_shared->setCameraPosition(GLfloat(horizontal), GLfloat(vertical), GLint(distance)); +} + +/*! + * \a theme Apply a predefined theme from \c QDataVis::ColorTheme. + * + * Sets a predefined theme. Theme affects object colors, label colors, text color, background color, + * window color and grid color. Lighting is also adjusted by themes. + */ +void Q3DScatter::setTheme(QDataVis::ColorTheme theme) +{ + d_ptr->m_shared->setColorTheme(theme); +} + +/*! + * \a baseColor The base color of an object. If all other colors are black, this sets the final + * color of the object. + * + * \a heightColor This color is added to the object based on its y-position. The higher the object, + * the more prominent this color becomes. Setting this black keeps the color unchanged regardless + * of y-position. + * + * \a depthColor This color becomes more prominent the further back in z-position the object is. + * Setting this black keeps objects the same color regardless of "depth" in the set. + * + * \a uniform A flag to define if color needs to be uniform throughout object's length, or will the + * colors be applied by height. \c true by default. + * + * Set object color using your own colors. This overrides colors from theme. + */ +void Q3DScatter::setObjectColor(QColor baseColor, QColor heightColor, QColor depthColor, bool uniform) +{ + d_ptr->m_shared->setObjectColor(baseColor, heightColor, depthColor, uniform); +} + +/*! + * \property Q3DScatter::selectionMode + * + * \a mode Set object selection mode from \c QDataVis::SelectionMode. \c ModeItem by default. + * + * Sets object selection mode to be used. + */ +void Q3DScatter::setSelectionMode(QDataVis::SelectionMode mode) +{ + d_ptr->m_shared->setSelectionMode(mode); +} + +QDataVis::SelectionMode Q3DScatter::selectionMode() const +{ + return d_ptr->m_shared->selectionMode(); +} + +/*! + * \property Q3DScatter::windowTitle + * + * \a title QString label to be used as window title. + * + * Sets the window title. The default is application executable name. + */ +void Q3DScatter::setWindowTitle(const QString &title) +{ + setTitle(title); +} + +QString Q3DScatter::windowTitle() const +{ + return title(); +} + +/*! + * \a objFileName File name of a mesh object. Object needs to be in Wavefront obj format + * and include vertices, normals and UVs. It also needs to be in triangles. + * + * Override object type with an object mesh. \sa setObjectType() + */ +void Q3DScatter::setMeshFileName(const QString &objFileName) +{ + d_ptr->m_shared->setMeshFileName(objFileName); +} + +/*! + * \property Q3DScatter::fontSize + * + * \a fontsize Size of the font. + * + * Sets font size. + */ +void Q3DScatter::setFontSize(float fontsize) +{ + d_ptr->m_shared->setFontSize(fontsize); +} + +float Q3DScatter::fontSize() const +{ + return d_ptr->m_shared->fontSize(); +} + +/*! + * \property Q3DScatter::font + * + * \a font QFont to be used for labels. \c Arial by default. + * + * Sets the font for labels. + */ +void Q3DScatter::setFont(const QFont &font) +{ + d_ptr->m_shared->setFont(font); +} + +QFont Q3DScatter::font() const +{ + return d_ptr->m_shared->font(); +} + +/*! + * \property Q3DScatter::labelTransparency + * + * \a transparency Transparency level of labels from \c QDataVis::LabelTransparency. + * \c TransparencyFromTheme by default. + * + * Sets label transparency. + */ +void Q3DScatter::setLabelTransparency(QDataVis::LabelTransparency transparency) +{ + d_ptr->m_shared->setLabelTransparency(transparency); +} + +QDataVis::LabelTransparency Q3DScatter::labelTransparency() const +{ + return d_ptr->m_shared->labelTransparency(); +} + +/*! + * \property Q3DScatter::gridVisible + * + * \a visible Flag to enable or disable grid. \c true by default. + * + * Sets grid drawing on or off. + */ +void Q3DScatter::setGridVisible(bool visible) +{ + d_ptr->m_shared->setGridEnabled(visible); +} + +bool Q3DScatter::isGridVisible() const +{ + return d_ptr->m_shared->gridEnabled(); +} + +/*! + * \property Q3DScatter::backgroundVisible + * + * \a visible Flag to enable or disable background. \c true by default. + * + * Sets backround rendering on or off. + */ +void Q3DScatter::setBackgroundVisible(bool visible) +{ + d_ptr->m_shared->setBackgroundEnabled(visible); +} + +bool Q3DScatter::isBackgroundVisible() const +{ + return d_ptr->m_shared->backgroundEnabled(); +} + +/*! + * \property Q3DScatter::shadowQuality + * + * \a quality Shadow quality from \c QDataVis::ShadowQuality. \c ShadowLow by default. + * + * Sets shadow quality. If setting QDataVis::ShadowQuality of a certain level fails, a level is lowered + * until it is successful and shadowQualityChanged signal is emitted for each time the change is done. + */ +void Q3DScatter::setShadowQuality(QDataVis::ShadowQuality quality) +{ + return d_ptr->m_shared->setShadowQuality(quality); +} + +QDataVis::ShadowQuality Q3DScatter::shadowQuality() const +{ + return d_ptr->m_shared->shadowQuality(); +} + +void Q3DScatter::setValueAxisX(QValueAxis *axis) +{ + Q_ASSERT(axis); + + return d_ptr->m_shared->setAxisX(axis); +} + +QValueAxis *Q3DScatter::valueAxisX() +{ + return static_cast<QValueAxis *>(d_ptr->m_shared->axisX()); +} + +void Q3DScatter::setValueAxisY(QValueAxis *axis) +{ + Q_ASSERT(axis); + + return d_ptr->m_shared->setAxisY(axis); +} + +QValueAxis *Q3DScatter::valueAxisY() +{ + return static_cast<QValueAxis *>(d_ptr->m_shared->axisY()); +} + +void Q3DScatter::setValueAxisZ(QValueAxis *axis) +{ + Q_ASSERT(axis); + + return d_ptr->m_shared->setAxisZ(axis); +} + +QValueAxis *Q3DScatter::valueAxisZ() +{ + return static_cast<QValueAxis *>(d_ptr->m_shared->axisZ()); +} + +void Q3DScatter::setDataProxy(QScatterDataProxy *proxy) +{ + d_ptr->m_shared->setDataProxy(proxy); +} + +QScatterDataProxy *Q3DScatter::dataProxy() +{ + return d_ptr->m_shared->dataProxy(); +} + +Q3DScatterPrivate::Q3DScatterPrivate(Q3DScatter *q, QRect rect) + : q_ptr(q), + m_shared(new Scatter3DController(rect)) +{ +} + +Q3DScatterPrivate::~Q3DScatterPrivate() +{ + qDebug() << "Destroying Q3DScatterPrivate"; + delete m_shared; +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dscatter.h b/src/datavis3d/engine/q3dscatter.h new file mode 100644 index 00000000..73a7d214 --- /dev/null +++ b/src/datavis3d/engine/q3dscatter.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef Q3DSCATTER_H +#define Q3DSCATTER_H + +#include <QtDataVis3D/qdatavis3denums.h> +#include <QtDataVis3D/q3dwindow.h> +#include <QFont> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class Q3DScatterPrivate; +class LabelItem; +class QValueAxis; +class QCategoryAxis; +class QScatterDataProxy; + +class QT_DATAVIS3D_EXPORT Q3DScatter : public Q3DWindow +{ + Q_OBJECT + Q_PROPERTY(QtDataVis3D::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + Q_PROPERTY(QtDataVis3D::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) + Q_PROPERTY(QtDataVis3D::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) + Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) + Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) + Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) + Q_ENUMS(QtDataVis3D::QDataVis::SelectionMode) + Q_ENUMS(QtDataVis3D::QDataVis::ShadowQuality) + Q_ENUMS(QtDataVis3D::QDataVis::LabelTransparency) + +public: + explicit Q3DScatter(); + ~Q3DScatter(); + + // object type; spheres, dots + void setObjectType(QDataVis::MeshStyle style, bool smooth = false); + + // Select preset camera placement + void setCameraPreset(QDataVis::CameraPreset preset); + + // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and + // vertical (-90...90) angles and distance in percentage (10...500)) + void setCameraPosition(qreal horizontal, qreal vertical, int distance = 100); + + // Set theme (object colors, shaders, window color, background colors, light intensity and text + // colors are affected) + void setTheme(QDataVis::ColorTheme theme); + + // Set color if you don't want to use themes. Set uniform to false if you want the (height) + // color to change from bottom to top + void setObjectColor(QColor baseColor, QColor heightColor, QColor depthColor, + bool uniform = true); + + // override object type with own mesh + void setMeshFileName(const QString &objFileName); + + // Change selection mode + void setSelectionMode(QDataVis::SelectionMode mode); + QDataVis::SelectionMode selectionMode() const; + + // Set window title + void setWindowTitle(const QString &title); + QString windowTitle() const; + + // Font size adjustment + void setFontSize(float fontsize); + float fontSize() const; + + // Set font + void setFont(const QFont &font); + QFont font() const; + + // Label transparency adjustment + void setLabelTransparency(QDataVis::LabelTransparency transparency); + QDataVis::LabelTransparency labelTransparency() const; + + // Enable or disable background grid + void setGridVisible(bool visible); + bool isGridVisible() const; + + // Size + void setWidth(const int width); + void setHeight(const int height); + + // Enable or disable background mesh + void setBackgroundVisible(bool visible); + bool isBackgroundVisible() const; + + // Adjust shadow quality + void setShadowQuality(QDataVis::ShadowQuality quality); + QDataVis::ShadowQuality shadowQuality() const; + + // Axes + void setValueAxisX(QValueAxis *axis); + QValueAxis *valueAxisX(); + + void setValueAxisY(QValueAxis *axis); + QValueAxis *valueAxisY(); + + void setValueAxisZ(QValueAxis *axis); + QValueAxis *valueAxisZ(); + + // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. + void setDataProxy(QtDataVis3D::QScatterDataProxy *proxy); + QScatterDataProxy *dataProxy(); + +public slots: + // Used to detect when shadow quality changes autonomously due to e.g. resizing. + void handleShadowQualityUpdate(QDataVis::ShadowQuality quality); + +signals: + // Signals shadow quality changes. + void shadowQualityChanged(QDataVis::ShadowQuality quality); + +protected: + void render(); + +#if defined(Q_OS_ANDROID) + void mouseDoubleClickEvent(QMouseEvent *event); + void touchEvent(QTouchEvent *event); +#endif + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + void resizeEvent(QResizeEvent *event); + +private: + QScopedPointer<Q3DScatterPrivate> d_ptr; + Q_DISABLE_COPY(Q3DScatter) +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/q3dscatter_p.h b/src/datavis3d/engine/q3dscatter_p.h new file mode 100644 index 00000000..ab2e2b06 --- /dev/null +++ b/src/datavis3d/engine/q3dscatter_p.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 Q3DSCATTER_p_H +#define Q3DSCATTER_p_H + +#include "scatter3dcontroller_p.h" +#include "qdatavis3denums.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class Q3DScatter; + +class Q3DScatterPrivate : public QObject +{ +public: + Q3DScatterPrivate(Q3DScatter *q, QRect rect); + ~Q3DScatterPrivate(); + + Q3DScatter *q_ptr; + Scatter3DController *m_shared; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/q3dsurface.cpp b/src/datavis3d/engine/q3dsurface.cpp new file mode 100644 index 00000000..7647ad10 --- /dev/null +++ b/src/datavis3d/engine/q3dsurface.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "q3dsurface.h" +#include "q3dsurface_p.h" + +#include <QMouseEvent> + +#include <QDebug> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +Q3DSurface::Q3DSurface() + : d_ptr(new Q3DSurfacePrivate(this, geometry())) +{ + d_ptr->m_shared->initializeOpenGL(); +} + +Q3DSurface::~Q3DSurface() +{ +} + +void Q3DSurface::render() +{ + d_ptr->m_shared->render(); +} + +#if defined(Q_OS_ANDROID) +void Q3DSurface::mouseDoubleClickEvent(QMouseEvent *event) +{ +} +void Q3DSurface::touchEvent(QTouchEvent *event) +{ +} +#endif + +void Q3DSurface::mousePressEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mousePressEvent(event, event->pos()); +} + +void Q3DSurface::mouseReleaseEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseReleaseEvent(event, event->pos()); +} + +void Q3DSurface::mouseMoveEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseMoveEvent(event, event->pos()); +} + +void Q3DSurface::wheelEvent(QWheelEvent *event) +{ + Q_UNUSED(event) +} + +void Q3DSurface::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + d_ptr->m_shared->setWidth(width()); + d_ptr->m_shared->setHeight(height()); +} + +void Q3DSurface::setSmoothSurface(bool enable) +{ + d_ptr->m_shared->setSmoothSurface(enable); +} + +bool Q3DSurface::smoothSurface() const +{ + return d_ptr->m_shared->smoothSurface(); +} + +void Q3DSurface::setSurfaceGrid(bool enable) +{ + d_ptr->m_shared->setSurfaceGrid(enable); +} + +bool Q3DSurface::surfaceGrid() const +{ + return d_ptr->m_shared->surfaceGrid(); +} + +void Q3DSurface::setWidth(const int width) +{ + d_ptr->m_shared->setWidth(width); + QWindow::setWidth(width); +} + +void Q3DSurface::setHeight(const int height) +{ + d_ptr->m_shared->setHeight(height); + QWindow::setHeight(height); +} + +/*! + * \a segmentCount How many segments will be drawn. \c 5 by default. + * + * \a step How large a step each segment is. + * + * \a minimum Minimum value a bar in data set can have. Setting this correctly is especially + * important if values can be negative, or autoscaling won't work correctly. + * + * Sets segment count and step. Note; segmentCount * step should be the maximum possible value of data + * set. + */ +void Q3DSurface::setSegmentCount(int segmentCount, qreal step, qreal minimum) +{ + d_ptr->m_shared->setSegmentCount(GLint(segmentCount), GLfloat(step), GLfloat(minimum)); +} + +void Q3DSurface::setGradientColorAt(qreal pos, const QColor &color) +{ + d_ptr->m_shared->setGradientColorAt(pos, color); +} + +// TODO ///////////////////////////////////////// +void Q3DSurface::appendSeries(QList<qreal> series, int width, int depth ) +{ + d_ptr->appendSeries(series); + d_ptr->m_shared->setData(series, width, depth); +} + +void Q3DSurface::showData() const +{ + for (int i = 0; i < d_ptr->numOfSeries(); i++) { + QList<qreal> s = d_ptr->seriesAt(i); + qDebug() << "Series = "; + foreach (qreal val, s) { + qDebug() << val; + } + } +} + +// TODO END ////////////////////////////////////////// + +/////////////////// PRIVATE /////////////////////////////////// + +Q3DSurfacePrivate::Q3DSurfacePrivate(Q3DSurface *q, QRect rect) + : q_ptr(q), + m_shared(new Surface3dController(rect)) +{ +} + +Q3DSurfacePrivate::~Q3DSurfacePrivate() +{ + qDebug() << "Q3DSurfacePrivate::~Q3DSurfacePrivate"; + delete m_shared; +} + +void Q3DSurfacePrivate::appendSeries(QList<qreal> series) +{ + m_seriesList.append(series); +} + +QList<qreal> Q3DSurfacePrivate::seriesAt(int i) +{ + return m_seriesList.at(i); +} + +int Q3DSurfacePrivate::numOfSeries() +{ + return m_seriesList.count(); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dsurface.h b/src/datavis3d/engine/q3dsurface.h new file mode 100644 index 00000000..c2deea9a --- /dev/null +++ b/src/datavis3d/engine/q3dsurface.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef Q3DSURFACE_H +#define Q3DSURFACE_H + +#include <QtDataVis3D/qdatavis3denums.h> +#include <QtDataVis3D/q3dwindow.h> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class Q3DSurfacePrivate; + +class QT_DATAVIS3D_EXPORT Q3DSurface : public Q3DWindow +{ + Q_OBJECT + Q_PROPERTY(bool smoothSurface READ smoothSurface WRITE setSmoothSurface) + Q_PROPERTY(bool surfaceGrid READ surfaceGrid WRITE setSurfaceGrid) + +public: + explicit Q3DSurface(); + ~Q3DSurface(); + + // Enable or disable the smoothes of the surface + void setSmoothSurface(bool enable); + bool smoothSurface() const; + + // Enable or disable the grid on the surface + void setSurfaceGrid(bool enable); + bool surfaceGrid() const; + + void setGradientColorAt(qreal pos, const QColor &color); + + // Set segment count and step. Note; segmentCount * step should be the maximum possible value of data + // set. Minimum is the absolute minimum possible value a bar can have. This is especially + // important to set if values can be negative. + void setSegmentCount(int segmentCount, qreal step, qreal minimum = 0.0f); + +//TODO part + void appendSeries(QList<qreal> series, int width, int depth); + void showData() const; +//END TODO + + // TODO: Do these need to be public? Where are they called from? + // Size + void setWidth(const int width); + void setHeight(const int height); + +protected: + void render(); + +#if defined(Q_OS_ANDROID) + void mouseDoubleClickEvent(QMouseEvent *event); + void touchEvent(QTouchEvent *event); +#endif + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + void resizeEvent(QResizeEvent *event); + +private: + QScopedPointer<Q3DSurfacePrivate> d_ptr; + Q_DISABLE_COPY(Q3DSurface) +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // Q3DSURFACE_H diff --git a/src/datavis3d/engine/q3dsurface_p.h b/src/datavis3d/engine/q3dsurface_p.h new file mode 100644 index 00000000..1e132416 --- /dev/null +++ b/src/datavis3d/engine/q3dsurface_p.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 Q3DSURFACE_P_H +#define Q3DSURFACE_P_H + +#include "surface3dcontroller_p.h" +#include "qdatavis3denums.h" + +#include <QList> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class Q3DSurface; + +class Q3DSurfacePrivate : public QObject +{ +public: + Q3DSurfacePrivate(Q3DSurface *q, QRect rect); + ~Q3DSurfacePrivate(); + + // TODO + void appendSeries(QList<qreal> series); + QList<qreal> seriesAt(int i); + int numOfSeries(); + // TODO + + Surface3dController *m_shared; + +private: + Q3DSurface *q_ptr; + QList<QList<qreal> > m_seriesList; // Temp to be replaced by dataset +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // Q3DSURFACE_P_H diff --git a/src/datavis3d/engine/q3dwindow.cpp b/src/datavis3d/engine/q3dwindow.cpp index af975cb1..5b2b70ab 100644 --- a/src/datavis3d/engine/q3dwindow.cpp +++ b/src/datavis3d/engine/q3dwindow.cpp @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -50,7 +27,7 @@ #include <QDebug> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE /*! * \class Q3DWindow @@ -95,28 +72,13 @@ Q3DWindow::Q3DWindow(QWindow *parent) qDebug() << "initializeOpenGLFunctions()"; initializeOpenGLFunctions(); - initialize(); -} - -/*! - * Destroys Q3DWindow. - */ -Q3DWindow::~Q3DWindow() -{ -} - -/*! - * \internal - */ -void Q3DWindow::initialize() -{ const GLubyte *version = glGetString(GL_VERSION); qDebug() << "OpenGL version:" << (const char *)version; version = glGetString(GL_SHADING_LANGUAGE_VERSION); qDebug() << "GLSL version:" << (const char *)version; #if !defined(QT_OPENGL_ES_2) // If we have real OpenGL, GLSL version must be 1.2 or over. Quit if not. - QStringList splitversionstr = QString((const char *)version).split(" "); + QStringList splitversionstr = QString::fromLatin1((const char *)version).split(QChar::fromLatin1(' ')); if (splitversionstr[0].toFloat() < 1.2) qFatal("GLSL version must be 1.20 or higher. Try installing latest display drivers."); #endif @@ -124,6 +86,13 @@ void Q3DWindow::initialize() } /*! + * Destroys Q3DWindow. + */ +Q3DWindow::~Q3DWindow() +{ +} + +/*! * \internal */ void Q3DWindow::render() @@ -174,17 +143,10 @@ void Q3DWindow::renderNow() if (!isExposed()) return; - static bool needsInit = true; - d_ptr->m_updatePending = false; d_ptr->m_context->makeCurrent(this); - if (needsInit) { - initialize(); - needsInit = false; - } - render(); d_ptr->m_context->swapBuffers(this); @@ -216,4 +178,4 @@ Q3DWindowPrivate::~Q3DWindowPrivate() { } -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dwindow.h b/src/datavis3d/engine/q3dwindow.h index bf7d8f74..e9f8fe1d 100644 --- a/src/datavis3d/engine/q3dwindow.h +++ b/src/datavis3d/engine/q3dwindow.h @@ -1,59 +1,36 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #ifndef Q3DWINDOW_H #define Q3DWINDOW_H -#include "QtDataVis3D/qdatavis3dglobal.h" +#include <QtDataVis3D/qdatavis3denums.h> #include <QWindow> #include <QOpenGLFunctions> class QPainter; -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE class Q3DWindowPrivate; -class QTENTERPRISE_DATAVIS3D_EXPORT Q3DWindow : public QWindow, protected QOpenGLFunctions +class QT_DATAVIS3D_EXPORT Q3DWindow : public QWindow, protected QOpenGLFunctions { Q_OBJECT @@ -67,7 +44,6 @@ private slots: protected: virtual void render(); - virtual void initialize(); void setAnimating(bool animating); bool event(QEvent *event); @@ -80,6 +56,6 @@ private: friend class Q3DBars; }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/engine/q3dwindow_p.h b/src/datavis3d/engine/q3dwindow_p.h index 4c6c5209..d32facfa 100644 --- a/src/datavis3d/engine/q3dwindow_p.h +++ b/src/datavis3d/engine/q3dwindow_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,12 +29,12 @@ #ifndef Q3DWINDOW_p_H #define Q3DWINDOW_p_H -#include "qdatavis3dglobal.h" +#include "datavis3dglobal_p.h" class QOpenGLContext; class QOpenGLPaintDevice; -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE class Q3DWindow; @@ -76,6 +53,6 @@ public: QOpenGLContext *m_context; }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/engine/qdataitem.cpp b/src/datavis3d/engine/qdataitem.cpp deleted file mode 100644 index 883c190c..00000000 --- a/src/datavis3d/engine/qdataitem.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdataitem.h" -#include "qdataitem_p.h" - -#include <QPoint> -#include <QString> - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -/*! - * \class QDataItem - * \inmodule QtDataVis3D - * \brief The QDataItem class provides a container for data to be added to graphs. - * \since 1.0.0 - * - * A QDataItem holds data for a single bar in a Q3DMaps or Q3DBars graph. - * - * \sa QDataRow, QDataSet, {Qt Data Visualization 3D C++ Classes} - */ - -/*! - * \a value A float value of the data item. - * - * \a label A QString label for the item. - * - * Constructs QDataItem. - */ -QDataItem::QDataItem(float value, const QString &label) - : d_ptr(new QDataItemPrivate(this, value, label)) -{ -} - -/*! - * Destroys QDataItem. - */ -QDataItem::~QDataItem() -{ -} - -/*! - * \property QDataItem::label - * - * \a label A QString label for the data item. Unit, for example. - * - * \a prepend A flag to indicate if the label is to be prepended or appended to the value. - * \c false by default. - * - * Sets label for the data item. - */ -void QDataItem::setLabel(const QString &label, bool prepend) -{ - d_ptr->m_labelString = label; - d_ptr->m_prependLabel = prepend; -} - -QString QDataItem::label() -{ - return d_ptr->m_labelString; -} - -/*! - * \property QDataItem::value - * - * \a value A float value for the data item. - * - * Sets value for the data item. - */ -void QDataItem::setValue(float value) -{ - d_ptr->m_value = value; -} - -/*! - * \overload QDataItem::value - * - * \a value An int value for the data item. - * - * Sets value for the data item. - */ -void QDataItem::setValue(int value) -{ - d_ptr->m_value = (float)value; -} - -float QDataItem::value() -{ - return d_ptr->m_value; -} - -/*! - * \property QDataItem::position - * - * \a position A QPointF position for the data item. - * - * Sets position for the data item. Has no effect in Q3DBars. - */ -void QDataItem::setPosition(const QPointF &position) -{ - d_ptr->m_position = position; -} - -/*! - * \overload QDataItem::position - * - * \a position A QPoint position for the data item. - * - * Sets position for the data item. Has no effect in Q3DBars. - */ -void QDataItem::setPosition(const QPoint &position) -{ - d_ptr->m_position = (QPointF)position; -} - -QPointF QDataItem::position() -{ - return d_ptr->m_position; -} - -QDataItemPrivate::QDataItemPrivate(QDataItem *q, float value, const QString &label) - : q_ptr(q), - m_value(value), - m_labelString(label), - m_prependLabel(false), - m_translation(QVector3D(0, 0, 0)), - m_label(LabelItem()), - m_selectionLabel(LabelItem()) -{ -} - -QDataItemPrivate::~QDataItemPrivate() -{ -} - -void QDataItemPrivate::setTranslation(const QVector3D &translation) -{ - m_translation = translation; -} - -QVector3D QDataItemPrivate::translation() -{ - return m_translation; -} - -float QDataItemPrivate::value() -{ - return m_value; -} - -QString QDataItemPrivate::valueStr() -{ - QString strVal; - QString numStr; - numStr.setNum(m_value); - if (m_prependLabel) { - strVal.append(m_labelString); - strVal.append(QStringLiteral(" ")); - strVal.append(numStr); - } else { - strVal.append(numStr); - strVal.append(m_labelString); - } - return strVal; -} - -void QDataItemPrivate::setLabel(const LabelItem &label) -{ - m_label = label; -} - -LabelItem QDataItemPrivate::label() -{ - return m_label; -} - -void QDataItemPrivate::setSelectionLabel(const LabelItem &label) -{ - m_selectionLabel = label; -} - -LabelItem QDataItemPrivate::selectionLabel() -{ - return m_selectionLabel; -} - -QPointF QDataItemPrivate::position() -{ - return m_position; -} - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/qdataitem.h b/src/datavis3d/engine/qdataitem.h deleted file mode 100644 index 7c8302f4..00000000 --- a/src/datavis3d/engine/qdataitem.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDATAITEM_H -#define QDATAITEM_H - -#include "QtDataVis3D/qdatavis3dglobal.h" -#include <QScopedPointer> -#include <QString> -#include <QObject> -#include <QPointF> - -class QPoint; - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -class QDataItemPrivate; - -class QTENTERPRISE_DATAVIS3D_EXPORT QDataItem : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString label READ label WRITE setLabel) - Q_PROPERTY(float value READ value WRITE setValue) - Q_PROPERTY(int value READ value WRITE setValue) - Q_PROPERTY(QPointF position READ position WRITE setPosition) - -public: - explicit QDataItem(float value = 0.0f, const QString &label = QString()); - ~QDataItem(); - - // TODO: Provide a Q_INVOKABLE version of this, or move prepend to it's own property. - void setLabel(const QString &label, bool prepend = false); // label for value, unit for example - QString label(); - void setValue(float value); - void setValue(int value); - float value(); - // Has no effect in Q3DBars - void setPosition(const QPointF &position); - void setPosition(const QPoint &position); - QPointF position(); - -private: - QScopedPointer<QDataItemPrivate> d_ptr; - friend class Bars3dShared; - friend class Q3DMaps; - friend class Q3DMapsPrivate; - friend class QDataRowPrivate; - friend class Drawer; -}; - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/qdataitem_p.h b/src/datavis3d/engine/qdataitem_p.h deleted file mode 100644 index 6b8a9b83..00000000 --- a/src/datavis3d/engine/qdataitem_p.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt 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 QDATAITEM_P_H -#define QDATAITEM_P_H - -#include "qdatavis3dglobal.h" -#include "qdataitem.h" -#include "labelitem_p.h" - -#include <QOpenGLFunctions> -#include <QSize> -#include <QString> -#include <QVector3D> - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -class QDataItemPrivate -{ - public: - explicit QDataItemPrivate(QDataItem *q, float value = 0.0f, - const QString &label = QString()); - ~QDataItemPrivate(); - - // Position in 3D scene - void setTranslation(const QVector3D &translation); - QVector3D translation(); - // Value of bar - float value(); - // Value and label appended into a string. If label has prepend -flag set, append label and value - QString valueStr(); - // Label item (containing valueStr as texture) - void setLabel(const LabelItem &label); - LabelItem label(); - // Selection label item (containing specialar selection texture, if mode is activated) - void setSelectionLabel(const LabelItem &label); - LabelItem selectionLabel(); - QPointF position(); - - private: - QDataItem *q_ptr; - float m_value; - QString m_labelString; - bool m_prependLabel; - QVector3D m_translation; - LabelItem m_label; - LabelItem m_selectionLabel; - QPointF m_position; - friend class QDataItem; -}; - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/qdatarow.cpp b/src/datavis3d/engine/qdatarow.cpp deleted file mode 100644 index 6bdd6d14..00000000 --- a/src/datavis3d/engine/qdatarow.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdatarow.h" -#include "qdatarow_p.h" -#include "qdataitem.h" -#include "qdataitem_p.h" - -#include <QString> - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -/*! - * \class QDataRow - * \inmodule QtDataVis3D - * \brief The QDataRow class provides a container for data items to be added to graphs. - * \since 1.0.0 - * - * A QDataRow is a container for all data to be added to a Q3DMaps instance, or a single row to - * be added to a QDataSet. It holds instances of QDataItem and has no knowledge of possible - * sample space sizes set for a Q3DBars instance. The ownership of QDataItem added is transferred - * to QDataRow. - * - * \sa QDataItem, QDataSet, {Qt Data Visualization 3D C++ Classes} - */ - -/*! - * \a label A QString label for the row. - * - * Constructs QDataRow. - */ -QDataRow::QDataRow(const QString &label) - : d_ptr(new QDataRowPrivate(this, label)) -{ -} - -/*! - * Destroys QDataRow and all instances of QDataItem it may hold. - */ -QDataRow::~QDataRow() -{ -} - -/*! - * \property QDataRow::label - * - * \a label A QString label for the row. - * - * Sets a label for the row. - */ -void QDataRow::setLabel(const QString &label) -{ - d_ptr->m_label = label; -} - -QString QDataRow::label() -{ - return d_ptr->m_label; -} - -/*! - * \a item A QDataItem instance. - * - * Adds a QDataItem to the QDataRow. Ownership of QDataItem is transferred to QDataRow. - */ -void QDataRow::addItem(QDataItem *item) -{ - d_ptr->m_row.prepend(item); -} - -QDataRowPrivate::QDataRowPrivate(QDataRow *q, const QString &label) - : q_ptr(q), - m_label(label), - m_labelItem(LabelItem()) -{ -} - -QDataRowPrivate::~QDataRowPrivate() -{ - for (int itemCount = 0; itemCount < m_row.size(); itemCount++) - delete m_row.at(itemCount); - m_row.clear(); -} - -QVector<QDataItem*> QDataRowPrivate::row() -{ - return m_row; -} - -void QDataRowPrivate::clear() -{ - m_row.clear(); -} - -QDataItem *QDataRowPrivate::getItem(int itemIndex) -{ - QDataItem *item = NULL; - if (m_row.size() > itemIndex) - item = m_row.at(itemIndex); - return item; -} - -void QDataRowPrivate::verifySize(int size) -{ - if (size > m_row.size()) { - // QVector's resize doesn't delete data contained in it - // Delete contents of items to be removed - int nbrToBeRemoved = m_row.size() - size; - for (int itemCount = 0; itemCount < nbrToBeRemoved; itemCount++) { - int itemToBeRemoved = m_row.size() - itemCount - 1; // -1 to compensate index 0 - delete m_row.at(itemToBeRemoved); - } - // Resize vector - m_row.resize(size); - } else if (size < m_row.size()) { - qCritical("Check your sample space size! Your row is too short."); - } -} - -QPair<GLfloat, GLfloat> QDataRowPrivate::limitValues() -{ - QPair<GLfloat, GLfloat> limits = qMakePair(100.0f, -100.0f); - for (int i = 0; i < m_row.size(); i++) { - QDataItem *item = m_row.at(i); - float itemValue = item->d_ptr->value(); - if (limits.second < itemValue) - limits.second = itemValue; - if (limits.first > itemValue) - limits.first = itemValue; - } - return limits; -} - -QString QDataRowPrivate::label() -{ - return m_label; -} - -void QDataRowPrivate::setLabelItem(const LabelItem &item) -{ - m_labelItem = item; -} - -LabelItem QDataRowPrivate::labelItem() -{ - return m_labelItem; -} - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/qdatarow.h b/src/datavis3d/engine/qdatarow.h deleted file mode 100644 index 72fa5f55..00000000 --- a/src/datavis3d/engine/qdatarow.h +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDATAROW_H -#define QDATAROW_H - -#include "QtDataVis3D/qdatavis3dglobal.h" -#include <QScopedPointer> -#include <QString> -#include <QObject> - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -class QDataRowPrivate; -class QDataItem; - -class QTENTERPRISE_DATAVIS3D_EXPORT QDataRow : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString label READ label WRITE setLabel) - -public: - explicit QDataRow(const QString &label = QString()); - ~QDataRow(); - - void setLabel(const QString &label); // label for value, unit for example - QString label(); - Q_INVOKABLE void addItem(QDataItem *item); - -private: - QScopedPointer<QDataRowPrivate> d_ptr; - friend class Bars3dShared; - friend class Q3DMaps; - friend class Q3DMapsPrivate; - friend class QDataSetPrivate; -}; - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/qdatarow_p.h b/src/datavis3d/engine/qdatarow_p.h deleted file mode 100644 index d563fe8a..00000000 --- a/src/datavis3d/engine/qdatarow_p.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt 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 QDATAROW_P_H -#define QDATAROW_P_H - -#include "qdatavis3dglobal.h" -#include "qdatarow.h" -#include "labelitem_p.h" -#include <QVector> -#include <QString> - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -class QDataItem; - -class QDataRowPrivate -{ -public: - explicit QDataRowPrivate(QDataRow *q, const QString &label = QString()); - ~QDataRowPrivate(); - - QVector<QDataItem*> row(); - // Clears vector, doesn't delete items - void clear(); - QDataItem *getItem(int itemIndex); - void verifySize(int size); - QPair<GLfloat, GLfloat> limitValues(); - QString label(); - void setLabelItem(const LabelItem &item); - LabelItem labelItem(); - -private: - QDataRow *q_ptr; - QVector<QDataItem*> m_row; - QString m_label; - LabelItem m_labelItem; - friend class QDataRow; -}; - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/qdataset.cpp b/src/datavis3d/engine/qdataset.cpp deleted file mode 100644 index 6fd59baf..00000000 --- a/src/datavis3d/engine/qdataset.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdataset.h" -#include "qdataset_p.h" -#include "qdatarow.h" -#include "qdatarow_p.h" - -#include <QPoint> -#include <QString> - -//#include <QDebug> - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -const QString empty; - -/*! - * \class QDataSet - * \inmodule QtDataVis3D - * \brief The QDataSet class provides a container for data rows to be added to graphs. - * \since 1.0.0 - * - * A QDataSet is a container for data to be added into a Q3DBars instance. It holds instances of - * QDataRow and has no knowledge of sample space size set for Q3DBars. The ownership of QDataRow - * added is transferred to QDataSet. - * - * \sa QDataItem, QDataRow, {Qt Data Visualization 3D C++ Classes} - */ - -/*! - * Constructs QDataSet. - */ -QDataSet::QDataSet() - : d_ptr(new QDataSetPrivate(this)) -{ -} - -/*! - * Destroys QDataSet, including all QDataRow instances it may hold. - */ -QDataSet::~QDataSet() -{ -} - -/*! - * \a xAxis A QString label for x axis. - * - * \a zAxis A QString label for z axis. - * - * \a yAxis A QString label for y axis. - * - * \a labelsRow A QVector of QStrings, one for each row. - * - * \a labelsColumn A QVector of QStrings, one for each column. - * - * Sets labels for the QDataSet. - */ -void QDataSet::setLabels(const QString &xAxis, - const QString &zAxis, - const QString &yAxis, - const QVector<QString> &labelsRow, - const QVector<QString> &labelsColumn) -{ - // skip empty labels, keep the previous ones - if (xAxis != empty && d_ptr->m_xAxis != xAxis) { - d_ptr->m_xAxis = xAxis; - // Generate axis label texture - if (d_ptr->m_drawer) - d_ptr->m_drawer->generateLabelItem(&d_ptr->m_xAxisItem, xAxis); - } - if (zAxis != empty && d_ptr->m_zAxis != zAxis) { - d_ptr->m_zAxis = zAxis; - // Generate axis label texture - if (d_ptr->m_drawer) - d_ptr->m_drawer->generateLabelItem(&d_ptr->m_zAxisItem, zAxis); - } - if (yAxis != empty && d_ptr->m_yAxis != yAxis) { - d_ptr->m_yAxis = yAxis; - // Generate axis label texture - if (d_ptr->m_drawer) - d_ptr->m_drawer->generateLabelItem(&d_ptr->m_yAxisItem, yAxis); - } - d_ptr->m_labelsRow = labelsRow; - d_ptr->m_labelsColumn = labelsColumn; - // Generate row and column label textures - if (d_ptr->m_drawer) { - for (int itemCount = 0; itemCount < labelsColumn.size(); itemCount++) { - d_ptr->m_labelItemsColumn.append(LabelItem()); - d_ptr->m_drawer->generateLabelItem(&d_ptr->m_labelItemsColumn[itemCount], - labelsColumn.at(itemCount)); - } - for (int itemCount = 0; itemCount < labelsRow.size(); itemCount++) { - d_ptr->m_labelItemsRow.append(LabelItem()); - d_ptr->m_drawer->generateLabelItem(&d_ptr->m_labelItemsRow[itemCount], - labelsRow.at(itemCount)); - } - } -} - -/*! - * \a row A QDataRow instance. - * - * Adds a QDataRow instance to QDataSet. Ownership of the QDataRow instance is transferred to - * QDataSet. - */ -void QDataSet::addRow(QDataRow *row) -{ - d_ptr->m_set.prepend(row); -} - -QDataSetPrivate::QDataSetPrivate(QDataSet *q) - : q_ptr(q), - m_set(QVector<QDataRow*>()), - m_xAxis(QString()), - m_zAxis(QString()), - m_yAxis(QString()), - m_labelsRow(QVector<QString>()), - m_labelsColumn(QVector<QString>()), - m_xAxisItem(LabelItem()), - m_zAxisItem(LabelItem()), - m_yAxisItem(LabelItem()), - m_labelItemsRow(QVector<LabelItem>()), - m_labelItemsColumn(QVector<LabelItem>()), - m_drawer(0) -{ -} - -QDataSetPrivate::~QDataSetPrivate() -{ - for (int itemCount = 0; itemCount < m_set.size(); itemCount++) - delete m_set.at(itemCount); - m_set.clear(); - // Delete axis textures - GLuint textureid = m_xAxisItem.textureId(); - if (textureid) - glDeleteTextures(1, &textureid); - textureid = m_zAxisItem.textureId(); - if (textureid) - glDeleteTextures(1, &textureid); - textureid = m_yAxisItem.textureId(); - if (textureid) - glDeleteTextures(1, &textureid); - // Delete row and column textures - for (int itemCount = 0; itemCount < m_labelItemsColumn.size(); itemCount++) { - LabelItem item = m_labelItemsColumn.at(itemCount); - textureid = item.textureId(); - if (textureid) - glDeleteTextures(1, &textureid); - } - for (int itemCount = 0; itemCount < m_labelItemsRow.size(); itemCount++) { - LabelItem item = m_labelItemsRow.at(itemCount); - textureid = item.textureId(); - if (textureid) - glDeleteTextures(1, &textureid); - } -} - -void QDataSetPrivate::setDrawer(Drawer *drawer) -{ - m_drawer = drawer; - connect(m_drawer, SIGNAL(drawerChanged()), this, SLOT(updateTextures())); - updateTextures(); -} - -QVector<QDataRow*> QDataSetPrivate::set() -{ - return m_set; -} - -QDataRow *QDataSetPrivate::getRow(int rowIndex) -{ - QDataRow *row = NULL; - if (m_set.size() > rowIndex) - row = m_set.at(rowIndex); - return row; -} - -QVector<QString> QDataSetPrivate::rowLabels() -{ - return m_labelsRow; -} - -QVector<QString> QDataSetPrivate::columnLabels() -{ - return m_labelsColumn; -} - -QVector<LabelItem> QDataSetPrivate::rowLabelItems() -{ - return m_labelItemsRow; -} - -QVector<LabelItem> QDataSetPrivate::columnLabelItems() -{ - return m_labelItemsColumn; -} - -void QDataSetPrivate::axisLabels(QString *xAxis, QString *zAxis, QString *yAxis) -{ - *xAxis = m_xAxis; - *zAxis = m_zAxis; - *yAxis = m_yAxis; -} - -void QDataSetPrivate::axisLabelItems(LabelItem *xAxisItem, LabelItem *zAxisItem, - LabelItem *yAxisItem) -{ - *xAxisItem = m_xAxisItem; - *zAxisItem = m_zAxisItem; - *yAxisItem = m_yAxisItem; -} - -void QDataSetPrivate::verifySize(int colSize, int rowSize) -{ - // First verify columns - // QVector's resize doesn't delete data contained in it - // Delete contents of rows to be removed - if (colSize < m_set.size()) { - int nbrToBeRemoved = m_set.size() - colSize; - for (int rowCount = 0; rowCount < nbrToBeRemoved; rowCount++) { - int rowToBeRemoved = m_set.size() - rowCount - 1; // -1 to compensate index 0 - delete m_set.at(rowToBeRemoved); - } - // Resize vector - m_set.resize(colSize); - } - // Then verify each row left - if (rowSize) { - for (int i = 0; i < m_set.size(); i++) - m_set.at(i)->d_ptr->verifySize(rowSize); - } -} - -QPair<GLfloat, GLfloat> QDataSetPrivate::limitValues() -{ - QPair<GLfloat, GLfloat> limits = qMakePair(100.0f, -100.0f); - QPair<GLfloat, GLfloat> rowLimits; - for (int i = 0; i < m_set.size(); i++) { - rowLimits = m_set.at(i)->d_ptr->limitValues(); - if (limits.second < rowLimits.second) - limits.second = rowLimits.second; - if (limits.first > rowLimits.first) - limits.first = rowLimits.first; - } - return limits; -} - -void QDataSetPrivate::updateTextures() -{ - if (m_xAxis != empty) - m_drawer->generateLabelItem(&m_xAxisItem, m_xAxis); - if (m_zAxis != empty) - m_drawer->generateLabelItem(&m_zAxisItem, m_zAxis); - if (m_yAxis != empty) - m_drawer->generateLabelItem(&m_yAxisItem, m_yAxis); - for (int itemCount = 0; itemCount < m_labelsColumn.size(); itemCount++) { - if (m_labelItemsColumn.size() < itemCount + 1) - m_labelItemsColumn.append(LabelItem()); - m_drawer->generateLabelItem(&m_labelItemsColumn[itemCount], m_labelsColumn.at(itemCount)); - } - for (int itemCount = 0; itemCount < m_labelsRow.size(); itemCount++) { - if (m_labelItemsRow.size() < itemCount + 1) - m_labelItemsRow.append(LabelItem()); - m_drawer->generateLabelItem(&m_labelItemsRow[itemCount], m_labelsRow.at(itemCount)); - } -} - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/qdataset.h b/src/datavis3d/engine/qdataset.h deleted file mode 100644 index e645bc16..00000000 --- a/src/datavis3d/engine/qdataset.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDATASET_H -#define QDATASET_H - -#include "QtDataVis3D/qdatavis3dglobal.h" -#include "qdataitem.h" -#include "qdatarow.h" - -#include <QScopedPointer> -#include <QVector> -#include <QString> - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -class QDataSetPrivate; - -class QTENTERPRISE_DATAVIS3D_EXPORT QDataSet : public QObject -{ - Q_OBJECT - -public: - explicit QDataSet(); - ~QDataSet(); - - Q_INVOKABLE void setLabels(const QString &xAxis = QString(), - const QString &zAxis = QString(), - const QString &yAxis = QString(), - const QVector<QString> &labelsRow = QVector<QString>(), - const QVector<QString> &labelsColumn = QVector<QString>()); - Q_INVOKABLE void addRow(QDataRow *row); - -private: - QScopedPointer<QDataSetPrivate> d_ptr; - friend class Bars3dShared; - friend class Q3DMaps; - friend class Q3DMapsPrivate; -}; - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/qdataset_p.h b/src/datavis3d/engine/qdataset_p.h deleted file mode 100644 index a259aa9a..00000000 --- a/src/datavis3d/engine/qdataset_p.h +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt 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 QDATASET_P_H -#define QDATASET_P_H - -#include "qdatavis3dglobal.h" -#include "qdataset.h" -#include "drawer_p.h" -#include "labelitem_p.h" -#include <QVector> -#include <QString> - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -class QDataSetPrivate : public QObject -{ - Q_OBJECT - -public: - explicit QDataSetPrivate(QDataSet *q); - ~QDataSetPrivate(); - - void setDrawer(Drawer *drawer); - QVector<QDataRow*> set(); - QDataRow *getRow(int rowIndex); - QVector<QString> rowLabels(); - QVector<QString> columnLabels(); - QVector<LabelItem> rowLabelItems(); - QVector<LabelItem> columnLabelItems(); - void axisLabels(QString *xAxis, QString *zAxis, QString *yAxis); - void axisLabelItems(LabelItem *xAxisItem, LabelItem *zAxisItem, LabelItem *yAxisItem); - void verifySize(int colSize, int rowSize = 0); // If rowSize is 0, don't verify rows - // first = min, second = max - QPair<GLfloat, GLfloat> limitValues(); - -public Q_SLOTS: - void updateTextures(); - -private: - QDataSet *q_ptr; - QVector<QDataRow*> m_set; - QString m_xAxis; - QString m_zAxis; - QString m_yAxis; - QVector<QString> m_labelsRow; - QVector<QString> m_labelsColumn; - LabelItem m_xAxisItem; - LabelItem m_zAxisItem; - LabelItem m_yAxisItem; - QVector<LabelItem> m_labelItemsRow; - QVector<LabelItem> m_labelItemsColumn; - Drawer *m_drawer; - friend class QDataSet; -}; - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/scatter3dcontroller.cpp b/src/datavis3d/engine/scatter3dcontroller.cpp new file mode 100644 index 00000000..0d93b06f --- /dev/null +++ b/src/datavis3d/engine/scatter3dcontroller.cpp @@ -0,0 +1,365 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "scatter3dcontroller_p.h" +#include "scatter3drenderer_p.h" +#include "camerahelper_p.h" +#include "qabstractaxis_p.h" +#include "qvalueaxis_p.h" +#include "qscatterdataproxy_p.h" + +#include <QMatrix4x4> +#include <QMouseEvent> +#include <qmath.h> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +Scatter3DController::Scatter3DController(QRect boundRect) + : Abstract3DController(boundRect), + m_mouseState(MouseNone), + m_mousePos(QPoint(0, 0)), + m_isSlicingActivated(false), + m_renderer(0), + m_data(0) +{ + // Default axes + setAxisX(new QValueAxis()); + setAxisY(new QValueAxis()); + setAxisZ(new QValueAxis()); + + setObjectType(QDataVis::Spheres, false); // default object type + + setDataProxy(new QScatterDataProxy); +} + +Scatter3DController::~Scatter3DController() +{ + delete m_data; +} + +void Scatter3DController::initializeOpenGL() +{ + // Initialization is called multiple times when Qt Quick components are used + if (isInitialized()) + return; + + m_renderer = new Scatter3DRenderer(this); + setRenderer(m_renderer); +} + +void Scatter3DController::synchDataToRenderer() +{ + Abstract3DController::synchDataToRenderer(); + + if (!isInitialized()) + return; + + // Notify changes to renderer + if (m_changeTracker.slicingActiveChanged) { + // TODO: Add notification. + m_changeTracker.slicingActiveChanged = false; + } + + if (m_isDataDirty) { + m_renderer->updateDataModel(m_data); + m_isDataDirty = false; + } +} + +QMatrix4x4 Scatter3DController::calculateViewMatrix(int zoom, int viewPortWidth, + int viewPortHeight, bool showUnder) +{ + return m_cameraHelper->calculateViewMatrix(m_mousePos, + zoom, + viewPortWidth, + viewPortHeight, + showUnder); +} + +bool Scatter3DController::isSlicingActive() +{ + return m_isSlicingActivated; +} + +void Scatter3DController::setSlicingActive(bool isSlicing) +{ + m_isSlicingActivated = isSlicing; + + m_changeTracker.slicingActiveChanged = true; + emit slicingActiveChanged(m_isSlicingActivated); +} + +Scatter3DController::MouseState Scatter3DController::mouseState() +{ + return m_mouseState; +} + +#if defined(Q_OS_ANDROID) +void Scatter3DController::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (!m_isSlicingActivated) { + m_mouseState = Scatter3DController::MouseOnScene; + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = event->pos(); + } +} + +void Scatter3DController::touchEvent(QTouchEvent *event) +{ + static int prevDistance = 0; + + QList<QTouchEvent::TouchPoint> points; + points = event->touchPoints(); + + if (points.count() == 2) { + m_mouseState = Scatter3DController::MouseOnPinch; + + QPointF distance = points.at(0).pos() - points.at(1).pos(); + int newDistance = distance.manhattanLength(); + int zoomRate = 1; + int zoomLevel = m_zoomLevel; + if (zoomLevel > 100) + zoomRate = 5; + if (newDistance > prevDistance) + zoomLevel += zoomRate; + else + zoomLevel -= zoomRate; + if (zoomLevel > 500) + zoomLevel = 500; + else if (zoomLevel < 10) + zoomLevel = 10; + setZoomLevel(zoomLevel); + prevDistance = newDistance; + //qDebug() << "distance" << distance.manhattanLength(); + } +} +#endif + +void Scatter3DController::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) +{ + QRect mainViewPort = m_renderer->mainViewPort(); + if (Qt::LeftButton == event->button()) { + if (m_isSlicingActivated) { + if (mousePos.x() <= mainViewPort.width() + && mousePos.y() <= mainViewPort.height()) { + m_mouseState = Scatter3DController::MouseOnOverview; + //qDebug() << "Mouse pressed on overview"; + } else { + m_mouseState = Scatter3DController::MouseOnZoom; + //qDebug() << "Mouse pressed on zoom"; + } + } else { +#if !defined(Q_OS_ANDROID) + m_mouseState = Scatter3DController::MouseOnScene; +#else + m_mouseState = Scatter3DController::MouseRotating; +#endif + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = mousePos; + //qDebug() << "Mouse pressed on scene"; + } + } else if (Qt::MiddleButton == event->button()) { + // reset rotations + m_mousePos = QPoint(0, 0); + } else if (Qt::RightButton == event->button()) { +#if !defined(Q_OS_ANDROID) + m_mouseState = Scatter3DController::MouseRotating; +#else + m_mouseState = Scatter3DController::MouseOnScene; +#endif + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = mousePos; + } + m_cameraHelper->updateMousePos(m_mousePos); +} + +void Scatter3DController::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event); + if (Scatter3DController::MouseRotating == m_mouseState) { + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = mousePos; + m_cameraHelper->updateMousePos(mousePos); + } + m_mouseState = Scatter3DController::MouseNone; +} + +void Scatter3DController::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event); + if (Scatter3DController::MouseRotating == m_mouseState) + m_mousePos = mousePos; +} + +void Scatter3DController::wheelEvent(QWheelEvent *event) +{ + int zoomLevel = m_zoomLevel; + if (zoomLevel > 100) + zoomLevel += event->angleDelta().y() / 12; + else if (zoomLevel > 50) + zoomLevel += event->angleDelta().y() / 60; + else + zoomLevel += event->angleDelta().y() / 120; + if (zoomLevel > 500) + zoomLevel = 500; + else if (zoomLevel < 10) + zoomLevel = 10; + + setZoomLevel(zoomLevel); +} + +void Scatter3DController::setDataProxy(QScatterDataProxy *proxy) +{ + delete m_data; + m_data = proxy; + + QObject::connect(m_data, &QScatterDataProxy::arrayReset, + this, &Scatter3DController::handleArrayReset); + QObject::connect(m_data, &QScatterDataProxy::itemsAdded, + this, &Scatter3DController::handleItemsAdded); + QObject::connect(m_data, &QScatterDataProxy::itemsChanged, + this, &Scatter3DController::handleItemsChanged); + QObject::connect(m_data, &QScatterDataProxy::itemsRemoved, + this, &Scatter3DController::handleItemsRemoved); + QObject::connect(m_data, &QScatterDataProxy::itemsInserted, + this, &Scatter3DController::handleItemsInserted); + + adjustValueAxisRange(); + m_isDataDirty = true; +} + +QScatterDataProxy *Scatter3DController::dataProxy() +{ + return m_data; +} + +void Scatter3DController::handleArrayReset() +{ + setSlicingActive(false); + adjustValueAxisRange(); + m_isDataDirty = true; +} + +void Scatter3DController::handleItemsAdded(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + adjustValueAxisRange(); + m_isDataDirty = true; +} + +void Scatter3DController::handleItemsChanged(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + adjustValueAxisRange(); + m_isDataDirty = true; +} + +void Scatter3DController::handleItemsRemoved(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + adjustValueAxisRange(); + m_isDataDirty = true; +} + +void Scatter3DController::handleItemsInserted(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + adjustValueAxisRange(); + m_isDataDirty = true; +} + +void Scatter3DController::handleAxisAutoAdjustRangeChangedInOrientation( + QAbstractAxis::AxisOrientation orientation, bool autoAdjust) +{ + Q_UNUSED(orientation) + Q_UNUSED(autoAdjust) + adjustValueAxisRange(); +} + +void Scatter3DController::setObjectType(QDataVis::MeshStyle style, bool smooth) +{ + QString objFile; + if (style == QDataVis::Spheres) { + if (smooth) + objFile = QStringLiteral(":/defaultMeshes/sphereSmooth"); + else + objFile = QStringLiteral(":/defaultMeshes/sphere"); + } else { + if (smooth) + objFile = QStringLiteral(":/defaultMeshes/dotSmooth"); + else + objFile = QStringLiteral(":/defaultMeshes/dot"); + } + Abstract3DController::setMeshFileName(objFile); +} + +void Scatter3DController::setSelectionMode(QDataVis::SelectionMode mode) +{ + if (mode > QDataVis::ModeItem) { + qWarning("Unsupported selection mode."); + return; + } + // Disable zoom if selection mode changes + setSlicingActive(false); + Abstract3DController::setSelectionMode(mode); +} + +QPoint Scatter3DController::mousePosition() +{ + return m_mousePos; +} + +void Scatter3DController::adjustValueAxisRange() +{ + if (m_data) { + QVector3D limits = m_data->dptr()->limitValues(); + QValueAxis *valueAxis = static_cast<QValueAxis *>(m_axisX); + if (valueAxis && valueAxis->isAutoAdjustRange()) { + if (limits.x() > 0) + valueAxis->dptr()->setRange(-limits.x(), limits.x()); + else + valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default. + } + + valueAxis = static_cast<QValueAxis *>(m_axisY); + if (valueAxis && valueAxis->isAutoAdjustRange()) { + if (limits.y() > 0) + valueAxis->dptr()->setRange(-limits.y(), limits.y()); + else + valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default. + } + + valueAxis = static_cast<QValueAxis *>(m_axisZ); + if (valueAxis && valueAxis->isAutoAdjustRange()) { + if (limits.z() > 0) + valueAxis->dptr()->setRange(-limits.z(), limits.z()); + else + valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default. + } + } +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/scatter3dcontroller_p.h b/src/datavis3d/engine/scatter3dcontroller_p.h new file mode 100644 index 00000000..437664b7 --- /dev/null +++ b/src/datavis3d/engine/scatter3dcontroller_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 Q3DSCATTERCONTROLLER_p_H +#define Q3DSCATTERCONTROLLER_p_H + +#include "datavis3dglobal_p.h" +#include "abstract3dcontroller_p.h" + +//#define DISPLAY_RENDER_SPEED + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class Scatter3DRenderer; +class QScatterDataProxy; + +struct Scatter3DChangeBitField { + bool slicingActiveChanged : 1; + + Scatter3DChangeBitField() : + slicingActiveChanged(true) + { + } +}; + +class QT_DATAVIS3D_EXPORT Scatter3DController : public Abstract3DController +{ + Q_OBJECT + +private: + Scatter3DChangeBitField m_changeTracker; + + // Interaction + MouseState m_mouseState; + QPoint m_mousePos; + bool m_isSlicingActivated; + + // Rendering + Scatter3DRenderer *m_renderer; + QScatterDataProxy *m_data; + +public: + explicit Scatter3DController(QRect rect); + ~Scatter3DController(); + + void initializeOpenGL(); + + MouseState mouseState(); + QPoint mousePosition(); + + bool isSlicingActive(); + void setSlicingActive(bool isSlicing); + + QMatrix4x4 calculateViewMatrix(int zoom, int viewPortWidth, int viewPortHeight, + bool showUnder = false); + + // Object type + void setObjectType(QDataVis::MeshStyle style, bool smooth = false); + + // Change selection mode + void setSelectionMode(QDataVis::SelectionMode mode); + +#if defined(Q_OS_ANDROID) + void mouseDoubleClickEvent(QMouseEvent *event); + void touchEvent(QTouchEvent *event); +#endif + void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); + void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); + void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); + void wheelEvent(QWheelEvent *event); + + // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. + void setDataProxy(QScatterDataProxy *proxy); + QScatterDataProxy *dataProxy(); + + void synchDataToRenderer(); + + virtual void handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust); + +public slots: + void handleArrayReset(); + void handleItemsAdded(int startIndex, int count); + void handleItemsChanged(int startIndex, int count); + void handleItemsRemoved(int startIndex, int count); + void handleItemsInserted(int startIndex, int count); + +signals: + void slicingActiveChanged(bool isSlicing); + +private: + void adjustValueAxisRange(); + + Q_DISABLE_COPY(Scatter3DController) +}; + + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/scatter3drenderer.cpp b/src/datavis3d/engine/scatter3drenderer.cpp new file mode 100644 index 00000000..d8d5da9a --- /dev/null +++ b/src/datavis3d/engine/scatter3drenderer.cpp @@ -0,0 +1,1648 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "scatter3drenderer_p.h" +#include "scatter3dcontroller_p.h" +#include "camerahelper_p.h" +#include "shaderhelper_p.h" +#include "objecthelper_p.h" +#include "texturehelper_p.h" +#include "utils_p.h" + +#include <QMatrix4x4> +#include <QMouseEvent> +#include <QThread> +#include <qmath.h> +#include <QDebug> + +// Commenting this draws the shadow map with perspective projection. Otherwise it's drawn in +// orthographic projection. +//#define USE_WIDER_SHADOWS + +// You can verify that depth buffer drawing works correctly by uncommenting this. +// You should see the scene from where the light is +//#define SHOW_DEPTH_TEXTURE_SCENE + +#ifdef DISPLAY_RENDER_SPEED +#include <QTime> +#endif + +QT_DATAVIS3D_BEGIN_NAMESPACE + +//#define USE_UNIFORM_SCALING // Scale x and z uniformly, or based on autoscaled values + +#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels + +const GLfloat aspectRatio = 2.0f; // Forced ratio of x and z to y. Dynamic will make it look odd. +// TODO: Make margin modifiable? +const GLfloat backgroundMargin = 1.1f; // Margin for background (1.1f = make it 10% larger to avoid items being drawn inside background) +const GLfloat gridLineWidth = 0.005f; +static QVector3D selectionSkipColor = QVector3D(255, 255, 255); // Selection texture's background color + +Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) + : Abstract3DRenderer(controller), + m_controller(controller), + m_selectedItem(0), + m_previouslySelectedItem(0), + m_xFlipped(false), + m_zFlipped(false), + m_yFlipped(false), + m_updateLabels(false), + m_dotShader(0), + m_depthShader(0), + m_selectionShader(0), + m_backgroundShader(0), + m_labelShader(0), + m_dotObj(0), + m_backgroundObj(0), + m_gridLineObj(0), + m_labelObj(0), + m_bgrTexture(0), + m_depthTexture(0), + m_selectionTexture(0), + m_depthFrameBuffer(0), + m_selectionFrameBuffer(0), + m_selectionDepthBuffer(0), + m_shadowQualityToShader(33.3f), + m_heightNormalizer(1.0f), + m_scaleFactor(0), + m_selection(selectionSkipColor), + m_areaSize(QSizeF(0.0f, 0.0f)), + m_hasHeightAdjustmentChanged(true), + m_dotSizeScale(1.0f) + #ifdef DISPLAY_RENDER_SPEED + , m_isFirstFrame(true), + m_numFrames(0) + #endif +{ + //qDebug() << __FUNCTION__; + m_dummyRenderItem.setRenderer(this); + initializeOpenGLFunctions(); + initializeOpenGL(); +} + +Scatter3DRenderer::~Scatter3DRenderer() +{ + //qDebug() << __FUNCTION__; + m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); + m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); + m_textureHelper->deleteTexture(&m_selectionTexture); + m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); + m_textureHelper->deleteTexture(&m_bgrTexture); + delete m_dotShader; + delete m_depthShader; + delete m_selectionShader; + delete m_backgroundShader; + delete m_dotObj; + delete m_backgroundObj; + delete m_gridLineObj; + delete m_textureHelper; +} + +void Scatter3DRenderer::initializeOpenGL() +{ + //qDebug() << __FUNCTION__; + m_textureHelper = new TextureHelper(); + m_drawer->initializeOpenGL(); + + // Initialize shaders + handleShadowQualityChange(); + + initLabelShaders(QStringLiteral(":/shaders/vertexLabel"), + QStringLiteral(":/shaders/fragmentLabel")); + +#if !defined(QT_OPENGL_ES_2) + // Init depth shader (for shadows). Init in any case, easier to handle shadow activation if done via api. + initDepthShader(); +#endif + + // Init selection shader + initSelectionShader(); + + // Load grid line mesh + loadGridLineMesh(); + + // Load label mesh + loadLabelMesh(); + + // Set OpenGL features + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + +#if !defined(QT_OPENGL_ES_2) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); +#endif + + // Set view port + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width(), m_mainViewPort.height()); + + // Resize in case we've missed resize events + // Resize calls initSelectionBuffer and initDepthBuffer, so they don't need to be called here + handleResize(); + + // Load background mesh (we need to be initialized first) + loadBackgroundMesh(); + + Abstract3DRenderer::initializeOpenGL(); +} + +void Scatter3DRenderer::updateDataModel(QScatterDataProxy *dataProxy) +{ + const QScatterDataArray &dataArray = *dataProxy->array(); + calculateSceneScalingFactors(); + int dataSize = dataArray.size(); + m_renderItemArray.resize(dataSize); + for (int i = 0; i < dataSize ; i++) { + qreal value = dataArray.at(i).position().y(); + m_renderItemArray[i].setValue(value); + m_renderItemArray[i].setPosition(dataArray.at(i).position()); + //m_renderItemArray[i].setHeight(value / m_heightNormalizer); + //m_renderItemArray[i].setItemLabel(dataArray.at(i).label()); + calculateTranslation(m_renderItemArray[i]); + m_renderItemArray[i].setRenderer(this); + } + m_dotSizeScale = (GLfloat)qBound(0.01, (qreal)(2.0f / qSqrt((qreal)dataSize)), 0.1); + + Abstract3DRenderer::updateDataModel(dataProxy); +} + +void Scatter3DRenderer::render(CameraHelper *camera, const GLuint defaultFboHandle) +{ + //qDebug() << __FUNCTION__; + +#ifdef DISPLAY_RENDER_SPEED + // For speed computation + if (m_isFirstFrame) { + m_lastFrameTime.start(); + m_isFirstFrame = false; + } + + // Measure speed (as milliseconds per frame) + m_numFrames++; + if (m_lastFrameTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago + qDebug() << qreal(m_lastFrameTime.elapsed()) / qreal(m_numFrames) << "ms/frame (=" << qreal(m_numFrames) << "fps)"; + m_numFrames = 0; + m_lastFrameTime.restart(); + } +#endif + + if (defaultFboHandle) { + glDepthMask(true); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + } + + QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme.m_windowColor); + glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (m_hasHeightAdjustmentChanged) { + // Set initial camera position. Also update if height adjustment has changed. + camera->setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + m_hasHeightAdjustmentChanged = false; + } + + // Draw bars scene + drawScene(camera, defaultFboHandle); +} + +void Scatter3DRenderer::drawScene(CameraHelper *camera, + const GLuint defaultFboHandle) +{ + //qDebug() << __FUNCTION__; + GLfloat backgroundRotation = 0; + + // Specify viewport + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width(), m_mainViewPort.height()); + + // Set up projection matrix + QMatrix4x4 projectionMatrix; + projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width() + / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f); + + // Calculate view matrix + QMatrix4x4 viewMatrix = m_controller->calculateViewMatrix( + m_cachedZoomLevel * m_autoScaleAdjustment, + m_mainViewPort.width(), + m_mainViewPort.height(), + true); + + // Calculate label flipping + if (viewMatrix.row(0).x() > 0) + m_zFlipped = false; + else + m_zFlipped = true; + if (viewMatrix.row(0).z() <= 0) + m_xFlipped = false; + else + m_xFlipped = true; + + // Check if we're viewing the scene from below + if (viewMatrix.row(2).y() < 0) + m_yFlipped = true; + else + m_yFlipped = false; + + // Calculate background rotation + if (!m_zFlipped && !m_xFlipped) + backgroundRotation = 270.0f; + else if (!m_zFlipped && m_xFlipped) + backgroundRotation = 180.0f; + else if (m_zFlipped && m_xFlipped) + backgroundRotation = 90.0f; + else if (m_zFlipped && !m_xFlipped) + backgroundRotation = 0.0f; + + // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) + QVector3D lightPos = camera->calculateLightPosition(defaultLightPos); + + // Map adjustment direction to model matrix scaling + // TODO: Let's use these for testing the autoscaling of dots based on their number + GLfloat heightMultiplier = m_dotSizeScale; //1.0f; + GLfloat widthMultiplier = m_dotSizeScale; //1.0f; + GLfloat depthMultiplier = m_dotSizeScale; //1.0f; + GLfloat heightScaler = 0.0f; + GLfloat widthScaler = 0.0f; + GLfloat depthScaler = 0.0f; + // switch (m_adjustDirection) { + // case Q3DMaps::AdjustHeight: + // widthMultiplier = 0.0f; + // heightMultiplier = 1.0f; + // depthMultiplier = 0.0f; + // widthScaler = m_barThickness.x() / m_scaleFactor; + // heightScaler = 0.0f; + // depthScaler = m_barThickness.z() / m_scaleFactor; + // break; + // case Q3DMaps::AdjustWidth: + // widthMultiplier = 1.0f; + // heightMultiplier = 0.0f; + // depthMultiplier = 0.0f; + // widthScaler = 0.0f; + // heightScaler = m_barThickness.y() / m_scaleFactor; + // depthScaler = m_barThickness.z() / m_scaleFactor; + // break; + // case Q3DMaps::AdjustDepth: + // widthMultiplier = 0.0f; + // heightMultiplier = 0.0f; + // depthMultiplier = 1.0f; + // widthScaler = m_barThickness.x() / m_scaleFactor; + // heightScaler = m_barThickness.y() / m_scaleFactor; + // depthScaler = 0.0f; + // break; + // case Q3DMaps::AdjustRadius: + // widthMultiplier = 1.0f; + // heightMultiplier = 0.0f; + // depthMultiplier = 1.0f; + // widthScaler = 0.0f; + // heightScaler = m_barThickness.y() / m_scaleFactor; + // depthScaler = 0.0f; + // break; + // case Q3DMaps::AdjustAll: + // widthMultiplier = 1.0f; + // heightMultiplier = 1.0f; + // depthMultiplier = 1.0f; + // widthScaler = 0.0f; + // heightScaler = 0.0f; + // depthScaler = 0.0f; + // break; + // } + + // Introduce regardless of shadow quality to simplify logic + QMatrix4x4 depthViewMatrix; + QMatrix4x4 depthProjectionMatrix; + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Render scene into a depth texture for using with shadow mapping + // Bind depth shader + m_depthShader->bind(); + + // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width() * m_cachedShadowQuality, + m_mainViewPort.height() * m_cachedShadowQuality); + + // Enable drawing to framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); + glClear(GL_DEPTH_BUFFER_BIT); + + // Set front face culling to reduce self-shadowing issues + glCullFace(GL_FRONT); + + // Get the depth view matrix + // It may be possible to hack lightPos here if we want to make some tweaks to shadow + QVector3D depthLightPos = camera->calculateLightPosition( + defaultLightPos, 0.0f, 1.0f / m_autoScaleAdjustment); + depthViewMatrix.lookAt(depthLightPos, QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed + //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); + // Set the depth projection matrix +#ifndef USE_WIDER_SHADOWS + // Use this for perspective shadows + depthProjectionMatrix.perspective(15.0f, (GLfloat)m_mainViewPort.width() + / (GLfloat)m_mainViewPort.height(), 3.0f, 100.0f); +#else + // Use these for orthographic shadows + //depthProjectionMatrix.ortho(-aspectRatio * 2.0f, aspectRatio * 2.0f, + // -m_heightNormalizer * 2.0f, m_heightNormalizer * 2.0f, + // 0.0f, 100.0f); + GLfloat testAspectRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height(); + depthProjectionMatrix.ortho(-testAspectRatio * 2.0f, testAspectRatio * 2.0f, + -m_heightNormalizer * 2.0f, m_heightNormalizer * 2.0f, + 0.0f, 100.0f); +#endif + // Draw bars to depth buffer + for (int bar = 0; bar < m_renderItemArray.size(); bar++) { + const ScatterRenderItem &item = m_renderItemArray.at(bar); + if (!item.value()) + continue; + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(item.translation().x(), + item.translation().y(), + item.translation().z()); + modelMatrix.scale(QVector3D(widthMultiplier + widthScaler, + heightMultiplier + heightScaler, + depthMultiplier + depthScaler)); + //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler, + // heightMultiplier * item.size() + heightScaler, + // depthMultiplier * item.size() + depthScaler)); + + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_dotObj->vertexBuf()); + glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_dotObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, m_dotObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(m_depthShader->posAtt()); + } + + // Disable drawing to framebuffer (= enable drawing to screen) + glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); + + // Reset culling to normal + glCullFace(GL_BACK); + + // Release depth shader + m_depthShader->release(); + + // Revert to original viewport + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width(), m_mainViewPort.height()); + +#if 0 // Use this if you want to see what is being drawn to the framebuffer + // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it) + m_labelShader->bind(); + glEnable(GL_TEXTURE_2D); + QMatrix4x4 modelMatrix; + QMatrix4x4 viewmatrix; + viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.5f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + modelMatrix.translate(0.0, 0.0, zComp); + QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; + m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); + m_drawer->drawObject(m_labelShader, m_labelObj, + m_depthTexture); + glDisable(GL_TEXTURE_2D); + m_labelShader->release(); +#endif + } +#endif + + // Skip selection mode drawing if we have no selection mode + if (m_cachedSelectionMode > QDataVis::ModeNone) { + // Bind selection shader + m_selectionShader->bind(); + + // Draw bars to selection buffer + glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); + glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used + glClearColor(selectionSkipColor.x() / 255, selectionSkipColor.y() / 255, + selectionSkipColor.z() / 255, 1.0f); // Set clear color to white (= skipColor) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer + glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled + GLint barIdxRed = 0; + GLint barIdxGreen = 0; + GLint barIdxBlue = 0; + for (int bar = 0; bar < m_renderItemArray.size(); bar++, barIdxRed++) { + const ScatterRenderItem &item = m_renderItemArray.at(bar); + if (!item.value()) + continue; + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(item.translation().x(), + item.translation().y(), + item.translation().z()); + modelMatrix.scale(QVector3D(widthMultiplier + widthScaler, + heightMultiplier + heightScaler, + depthMultiplier + depthScaler)); + //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler, + // heightMultiplier * item.size() + heightScaler, + // depthMultiplier * item.size() + depthScaler)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + + if (barIdxRed > 0 && barIdxRed % 256 == 0) { + barIdxRed = 0; + barIdxGreen++; + } + if (barIdxGreen > 0 && barIdxGreen % 256 == 0) { + barIdxGreen = 0; + barIdxBlue++; + } + if (barIdxBlue > 255) + qFatal("Too many objects"); + + QVector3D barColor = QVector3D((GLfloat)barIdxRed / 255.0f, + (GLfloat)barIdxGreen / 255.0f, + (GLfloat)barIdxBlue / 255.0f); + + m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); + m_selectionShader->setUniformValue(m_selectionShader->color(), barColor); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_selectionShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_dotObj->vertexBuf()); + glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_dotObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, m_dotObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(m_selectionShader->posAtt()); + } + glEnable(GL_DITHER); + + // Read color under cursor + if (Scatter3DController::MouseOnScene == m_controller->mouseState()) + m_selection = Utils::getSelection(m_controller->mousePosition(), + m_cachedBoundingRect.height()); + + QMutexLocker locker(&m_mutex); + if (m_isSelectionPointRequestActive) { + m_isSelectionPointRequestActive = false; + m_selection = Utils::getSelection(m_selectionPointRequest, + m_cachedBoundingRect.height()); + emit selectionUpdated(m_selection); + } + locker.unlock(); + + glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); + + // Release selection shader + m_selectionShader->release(); + +#if 0 // Use this if you want to see what is being drawn to the framebuffer + m_labelShader->bind(); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + QMatrix4x4 modelMatrix; + QMatrix4x4 viewmatrix; + viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + modelMatrix.translate(0.0, 0.0, zComp); + QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; + m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); + m_drawer->drawObject(m_labelShader, m_labelObj, + m_selectionTexture); + glDisable(GL_TEXTURE_2D); + m_labelShader->release(); +#endif + } + + // Bind bar shader + m_dotShader->bind(); + + // Enable texture + glEnable(GL_TEXTURE_2D); + + // Draw bars + bool barSelectionFound = false; + for (int bar = 0; bar < m_renderItemArray.size(); bar++) { + ScatterRenderItem &item = m_renderItemArray[bar]; + if (!item.value()) + continue; + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(item.translation().x(), + item.translation().y(), + item.translation().z()); + modelMatrix.scale(QVector3D(widthMultiplier + widthScaler, + heightMultiplier + heightScaler, + depthMultiplier + depthScaler)); + //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler, + // heightMultiplier * item.size() + heightScaler, + // depthMultiplier * item.size() + depthScaler)); + itModelMatrix.scale(QVector3D(widthMultiplier + widthScaler, + heightMultiplier + heightScaler, + depthMultiplier + depthScaler)); + //itModelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler, + // heightMultiplier * item.size() + heightScaler, + // depthMultiplier * item.size() + depthScaler)); + +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + QVector3D baseColor = Utils::vectorFromColor(m_cachedTheme.m_baseColor); + QVector3D heightColor = + Utils::vectorFromColor(m_cachedTheme.m_heightColor) * item.translation().y(); + + QVector3D barColor = baseColor + heightColor; + + GLfloat lightStrength = m_cachedTheme.m_lightStrength; + if (m_cachedSelectionMode > QDataVis::ModeNone) { + Scatter3DController::SelectionType selectionType = isSelected(bar, m_selection); + switch (selectionType) { + case Scatter3DController::SelectionItem: { + barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor); + lightStrength = m_cachedTheme.m_highlightLightStrength; + // Insert data to ScatterRenderItem. We have no ownership, don't delete the previous one + m_selectedItem = &item; + barSelectionFound = true; + break; + } + case Scatter3DController::SelectionNone: { + // Current bar is not selected, nor on a row or column + // do nothing + break; + } + default: { + // Unsupported selection mode + // do nothing + break; + } + } + } + + // Set shader bindings + m_dotShader->setUniformValue(m_dotShader->lightP(), lightPos); + m_dotShader->setUniformValue(m_dotShader->view(), viewMatrix); + m_dotShader->setUniformValue(m_dotShader->model(), modelMatrix); + m_dotShader->setUniformValue(m_dotShader->nModel(), + itModelMatrix.inverted().transposed()); + m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix); + m_dotShader->setUniformValue(m_dotShader->color(), barColor); + m_dotShader->setUniformValue(m_dotShader->ambientS(), m_cachedTheme.m_ambientStrength); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader); + m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix); + m_dotShader->setUniformValue(m_dotShader->lightS(), lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_dotShader, m_dotObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_dotShader->setUniformValue(m_dotShader->lightS(), lightStrength); + + // Draw the object + m_drawer->drawObject(m_dotShader, m_dotObj); + } + } + + // Release bar shader + m_dotShader->release(); + + // Bind background shader + m_backgroundShader->bind(); + + glCullFace(GL_BACK); + + // Draw background + if (m_cachedIsBackgroundEnabled && m_backgroundObj) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(0.0f, 0.0f, zComp); +#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z + modelMatrix.scale( + QVector3D( + (aspectRatio * backgroundMargin * m_areaSize.width()) / m_scaleFactor, + backgroundMargin, + (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor)); +#else // ..and this if we want uniform scaling based on largest dimension + modelMatrix.scale(QVector3D((aspectRatio * backgroundMargin), + backgroundMargin, + (aspectRatio * backgroundMargin))); +#endif + // We can copy modelMatrix to itModelMatrix as it has not been translated + itModelMatrix = modelMatrix; + // If we're viewing from below, background object must be flipped + if (m_yFlipped) { + modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0); + modelMatrix.rotate(270.0f - backgroundRotation, 0.0f, 1.0f, 0.0f); + } else { + modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); + } + +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme.m_backgroundColor); + + // Set shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos); + m_backgroundShader->setUniformValue(m_backgroundShader->view(), viewMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->model(), modelMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->nModel(), + itModelMatrix.inverted().transposed()); + m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->color(), backgroundColor); + m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(), + m_cachedTheme.m_ambientStrength * 2.0f); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), + m_shadowQualityToShader); + m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_backgroundShader, m_backgroundObj); + } + } + + // Release background shader + m_backgroundShader->release(); + + // Disable textures + glDisable(GL_TEXTURE_2D); + + // Draw grid lines +#ifdef USE_UNIFORM_SCALING + AxisRenderCache *axisCacheMax; + if (m_axisCacheZ.max() > m_axisCacheX.max()) + axisCacheMax = &m_axisCacheZ; + else + axisCacheMax = &m_axisCacheX; +#endif + + if (m_cachedIsGridEnabled && m_heightNormalizer) { + // Bind bar shader + m_dotShader->bind(); + + // Set unchanging shader bindings + QVector3D barColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine); + m_dotShader->setUniformValue(m_dotShader->lightP(), lightPos); + m_dotShader->setUniformValue(m_dotShader->view(), viewMatrix); + m_dotShader->setUniformValue(m_dotShader->color(), barColor); + m_dotShader->setUniformValue(m_dotShader->ambientS(), m_cachedTheme.m_ambientStrength); + + // Floor lines: rows (= Z) + if (m_axisCacheZ.segmentCount() > 0) { +#ifndef USE_UNIFORM_SCALING + GLfloat lineStep = aspectRatio * m_axisCacheZ.subSegmentStep(); + GLfloat linePos = aspectRatio * m_axisCacheZ.min(); // Start line + int lastSegment = m_axisCacheZ.subSegmentCount() * m_axisCacheZ.segmentCount(); +#else + GLfloat lineStep = aspectRatio * axisCacheMax->subSegmentStep(); + GLfloat linePos = -aspectRatio * m_scaleFactor; // Start line + int lastSegment = axisCacheMax->subSegmentCount() * axisCacheMax->segmentCount(); +#endif + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + if (m_yFlipped) { + modelMatrix.translate(0.0f, + backgroundMargin, + linePos / m_scaleFactor + zComp); + } else { + modelMatrix.translate(0.0f, + -backgroundMargin, + linePos / m_scaleFactor + zComp); + } +#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z + modelMatrix.scale( + QVector3D( + (aspectRatio * backgroundMargin * m_areaSize.width()) / m_scaleFactor, + gridLineWidth, gridLineWidth)); + itModelMatrix.scale( + QVector3D( + (aspectRatio * backgroundMargin * m_areaSize.width()) / m_scaleFactor, + gridLineWidth, gridLineWidth)); +#else // ..and this if we want uniform scaling based on largest dimension + modelMatrix.scale(QVector3D((aspectRatio * backgroundMargin), + gridLineWidth, gridLineWidth)); + itModelMatrix.scale(QVector3D(aspectRatio * backgroundMargin, + gridLineWidth, gridLineWidth)); +#endif + + // If we're viewing from below, grid line object must be flipped + if (m_yFlipped) + modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + m_dotShader->setUniformValue(m_dotShader->model(), modelMatrix); + m_dotShader->setUniformValue(m_dotShader->nModel(), + itModelMatrix.inverted().transposed()); + m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader); + m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix); + m_dotShader->setUniformValue(m_dotShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_dotShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_dotShader->setUniformValue(m_dotShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_dotShader, m_gridLineObj); + } + linePos += lineStep; + } + } + + // Floor lines: columns (= X) + if (m_axisCacheX.segmentCount() > 0) { +#ifndef USE_UNIFORM_SCALING + GLfloat lineStep = aspectRatio * m_axisCacheX.subSegmentStep(); + GLfloat linePos = aspectRatio * m_axisCacheX.min(); + int lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount(); +#else + GLfloat lineStep = aspectRatio * axisCacheMax->subSegmentStep(); + GLfloat linePos = -aspectRatio * m_scaleFactor; + int lastSegment = axisCacheMax->subSegmentCount() * axisCacheMax->segmentCount(); +#endif + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + if (m_yFlipped) { + modelMatrix.translate(linePos / m_scaleFactor, + backgroundMargin, + zComp); + } else { + modelMatrix.translate(linePos / m_scaleFactor, + -backgroundMargin, + zComp); + } +#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z + modelMatrix.scale( + QVector3D( + gridLineWidth, gridLineWidth, + (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor)); + itModelMatrix.scale( + QVector3D( + gridLineWidth, gridLineWidth, + (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor)); +#else // ..and this if we want uniform scaling based on largest dimension + modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + aspectRatio * backgroundMargin)); + itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + aspectRatio * backgroundMargin)); +#endif + + // If we're viewing from below, grid line object must be flipped + if (m_yFlipped) + modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + m_dotShader->setUniformValue(m_dotShader->model(), modelMatrix); + m_dotShader->setUniformValue(m_dotShader->nModel(), + itModelMatrix.inverted().transposed()); + m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader); + m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix); + m_dotShader->setUniformValue(m_dotShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_dotShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_dotShader->setUniformValue(m_dotShader->lightS(), m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_dotShader, m_gridLineObj); + } + linePos += lineStep; + } + } + + // Wall lines: back wall + if (m_axisCacheY.segmentCount() > 0) { + GLfloat lineStep = m_axisCacheY.subSegmentStep(); + GLfloat linePos = m_axisCacheY.min(); + int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount(); + + for (int segment = 0; segment <= lastSegment; segment++) { +#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z + GLfloat lineZTrans = (aspectRatio * backgroundMargin * m_areaSize.height()) + / m_scaleFactor; +#else // ..and this if we want uniform scaling based on largest dimension + GLfloat lineZTrans = aspectRatio * backgroundMargin; +#endif + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + if (!m_zFlipped) + lineZTrans = -lineZTrans; + + modelMatrix.translate(0.0f, + linePos / m_heightNormalizer, + lineZTrans + zComp); +#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z + modelMatrix.scale( + QVector3D( + (aspectRatio * backgroundMargin * m_areaSize.width() / m_scaleFactor), + gridLineWidth, gridLineWidth)); + itModelMatrix.scale( + QVector3D( + (aspectRatio * backgroundMargin * m_areaSize.width() / m_scaleFactor), + gridLineWidth, gridLineWidth)); +#else // ..and this if we want uniform scaling based on largest dimension + modelMatrix.scale(QVector3D((aspectRatio * backgroundMargin), + gridLineWidth, gridLineWidth)); + itModelMatrix.scale(QVector3D(aspectRatio * backgroundMargin, + gridLineWidth, gridLineWidth)); +#endif + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + m_dotShader->setUniformValue(m_dotShader->model(), modelMatrix); + m_dotShader->setUniformValue(m_dotShader->nModel(), + itModelMatrix.inverted().transposed()); + m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader); + m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix); + m_dotShader->setUniformValue(m_dotShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_dotShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_dotShader->setUniformValue(m_dotShader->lightS(), m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_dotShader, m_gridLineObj); + } + linePos += lineStep; + } + + // Wall lines: side wall + linePos = m_axisCacheY.min(); + lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount(); + + for (int segment = 0; segment <= lastSegment; segment++) { +#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z + GLfloat lineXTrans = (aspectRatio * backgroundMargin * m_areaSize.width()) + / m_scaleFactor; +#else // ..and this if we want uniform scaling based on largest dimension + GLfloat lineXTrans = aspectRatio * backgroundMargin; +#endif + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + if (!m_xFlipped) + lineXTrans = -lineXTrans; + + modelMatrix.translate(lineXTrans, + linePos / m_heightNormalizer, + zComp); +#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z + modelMatrix.scale( + QVector3D( + gridLineWidth, gridLineWidth, + (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor)); + itModelMatrix.scale( + QVector3D( + gridLineWidth, gridLineWidth, + (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor)); + +#else // ..and this if we want uniform scaling based on largest dimension + modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + (aspectRatio * backgroundMargin))); + itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + aspectRatio * backgroundMargin)); + +#endif + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + m_dotShader->setUniformValue(m_dotShader->model(), modelMatrix); + m_dotShader->setUniformValue(m_dotShader->nModel(), + itModelMatrix.inverted().transposed()); + m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader); + m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix); + m_dotShader->setUniformValue(m_dotShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_dotShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_dotShader->setUniformValue(m_dotShader->lightS(), m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_dotShader, m_gridLineObj); + } + linePos += lineStep; + } + } + + // Release bar shader + m_dotShader->release(); + } + + // Handle selection clearing and selection label drawing + if (!barSelectionFound) { + // We have no ownership, don't delete. Just NULL the pointer. + m_selectedItem = NULL; + } else { + // Print value of selected bar + m_labelShader->bind(); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + if (m_cachedLabelTransparency > QDataVis::TransparencyNone) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } +#ifndef DISPLAY_FULL_DATA_ON_SELECTION + // Draw just the value string of the selected bar + if (m_previouslySelectedBar != m_selectedBar || m_updateLabels) { + m_drawer->generateLabelTexture(m_selectedBar); + m_previouslySelectedBar = m_selectedBar; + } + + m_drawer->drawLabel(*m_selectedBar, m_selectedBar->labelItem(), + viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), + m_cachedSelectionMode, m_labelShader, + m_labelObj, m_camera, true); +#else + // Draw the value string followed by row label and column label + LabelItem &labelItem = m_selectedItem->selectionLabel(); + if (m_previouslySelectedItem != m_selectedItem || m_updateLabels + || !labelItem.textureId()) { + QString labelText = m_selectedItem->label(); + // TODO More elaborate label? + m_drawer->generateLabelItem(labelItem, labelText); + m_previouslySelectedItem = m_selectedItem; + } + + m_drawer->drawLabel(*m_selectedItem, labelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 0.0f, 0.0f), m_selectedItem->height(), + m_cachedSelectionMode, m_labelShader, + m_labelObj, camera, true, false, Drawer::LabelMid); +#endif + glDisable(GL_TEXTURE_2D); + if (m_cachedLabelTransparency > QDataVis::TransparencyNone) + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + + // Release label shader + m_labelShader->release(); + + // Reset label update flag; they should have been updated when we get here + m_updateLabels = false; + } + + // Draw axis labels + // TODO: Calculations done temporarily here. Should be done when calculating lines to avoid + // extra for -loops? + // Bind label shader + m_labelShader->bind(); + + glEnable(GL_TEXTURE_2D); + if (m_cachedLabelTransparency > QDataVis::TransparencyNone) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + // Z Labels + if (m_axisCacheZ.segmentCount() > 0) { +#ifndef USE_UNIFORM_SCALING + GLfloat posStep = aspectRatio * m_axisCacheZ.segmentStep(); + GLfloat labelPos = aspectRatio * m_axisCacheZ.min(); + int lastSegment = m_axisCacheZ.segmentCount(); +#else + GLfloat posStep = aspectRatio * axisCacheMax->segmentStep(); + GLfloat labelPos = -aspectRatio * m_scaleFactor; + int lastSegment = axisCacheMax->segmentCount(); +#endif + int labelNbr = 0; + for (int segment = 0; segment <= lastSegment; segment++) { +#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z + if (m_axisCacheZ.labelItems().size() > labelNbr) { + GLfloat labelXTrans = (aspectRatio * backgroundMargin * m_areaSize.width()) + / m_scaleFactor; +#else // ..and this if we want uniform scaling based on largest dimension + if (axisCacheMax->labelItems().size() > labelNbr) { + GLfloat labelXTrans = aspectRatio * backgroundMargin; +#endif + GLfloat labelYTrans = -backgroundMargin; + GLfloat rotLabelX = -90.0f; + GLfloat rotLabelY = 0.0f; + GLfloat rotLabelZ = 0.0f; + Qt::AlignmentFlag alignment = Qt::AlignRight; + if (m_zFlipped) + rotLabelY = 180.0f; + if (m_xFlipped) { + labelXTrans = -labelXTrans; + alignment = Qt::AlignLeft; + } + if (m_yFlipped) { + rotLabelZ += 180.0f; + rotLabelY += 180.0f; + labelYTrans = -labelYTrans; + } + QVector3D labelTrans = QVector3D(labelXTrans, + labelYTrans, + labelPos / m_scaleFactor + zComp); + + + // Draw the label here + m_dummyRenderItem.setTranslation(labelTrans); +#ifndef USE_UNIFORM_SCALING + const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(labelNbr); +#else + const LabelItem &axisLabelItem = *axisCacheMax->labelItems().at(labelNbr); +#endif + + m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, 0.0f, zComp), + QVector3D(rotLabelX, rotLabelY, rotLabelZ), + 0, m_cachedSelectionMode, + m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + alignment); + } + labelNbr++; + labelPos += posStep; + } + } + // X Labels + if (m_axisCacheX.segmentCount() > 0) { +#ifndef USE_UNIFORM_SCALING + GLfloat posStep = aspectRatio * m_axisCacheX.segmentStep(); + GLfloat labelPos = aspectRatio * m_axisCacheX.min(); + int lastSegment = m_axisCacheX.segmentCount(); +#else + GLfloat posStep = aspectRatio * axisCacheMax->segmentStep(); + GLfloat labelPos = -aspectRatio * m_scaleFactor; + int lastSegment = axisCacheMax->segmentCount(); +#endif + int labelNbr = 0; + for (int segment = 0; segment <= lastSegment; segment++) { +#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z + if (m_axisCacheX.labelItems().size() > labelNbr) { + GLfloat labelZTrans = (aspectRatio * backgroundMargin * m_areaSize.height()) + / m_scaleFactor; +#else // ..and this if we want uniform scaling based on largest dimension + if (axisCacheMax->labelItems().size() > labelNbr) { + GLfloat labelZTrans = aspectRatio * backgroundMargin; +#endif + GLfloat labelYTrans = -backgroundMargin; + GLfloat rotLabelX = -90.0f; + GLfloat rotLabelY = 90.0f; + GLfloat rotLabelZ = 0.0f; + Qt::AlignmentFlag alignment = Qt::AlignLeft; + if (m_xFlipped) + rotLabelY = -90.0f; + if (m_zFlipped) { + labelZTrans = -labelZTrans; + alignment = Qt::AlignRight; + } + if (m_yFlipped) { + rotLabelZ += 180.0f; + rotLabelY += 180.0f; + labelYTrans = -labelYTrans; + } + QVector3D labelTrans = QVector3D(labelPos / m_scaleFactor, + labelYTrans, + labelZTrans + zComp); + + // Draw the label here + m_dummyRenderItem.setTranslation(labelTrans); +#ifndef USE_UNIFORM_SCALING + const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(labelNbr); +#else + const LabelItem &axisLabelItem = *axisCacheMax->labelItems().at(labelNbr); +#endif + + m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, 0.0f, zComp), + QVector3D(rotLabelX, rotLabelY, rotLabelZ), + 0, m_cachedSelectionMode, + m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + alignment); + } + labelNbr++; + labelPos += posStep; + } + } + // Y Labels + if (m_axisCacheY.segmentCount() > 0) { + GLfloat posStep = m_axisCacheY.segmentStep(); + GLfloat labelPos = m_axisCacheY.min(); + int labelNbr = 0; + for (int segment = 0; segment <= m_axisCacheY.segmentCount(); segment++) { + if (m_axisCacheY.labelItems().size() > labelNbr) { +#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z + GLfloat labelXTrans = (aspectRatio * backgroundMargin * m_areaSize.width()) + / m_scaleFactor; + GLfloat labelZTrans = (aspectRatio * backgroundMargin * m_areaSize.height()) + / m_scaleFactor; +#else // ..and this if we want uniform scaling based on largest dimension + GLfloat labelXTrans = aspectRatio * backgroundMargin; + GLfloat labelZTrans = labelXTrans; +#endif + GLfloat labelYTrans = labelPos / m_heightNormalizer; + GLfloat rotLabelX = 0.0f; + GLfloat rotLabelY = -90.0f; + GLfloat rotLabelZ = 0.0f; + Qt::AlignmentFlag alignment = Qt::AlignLeft; + if (!m_xFlipped) { + labelXTrans = -labelXTrans; + rotLabelY = 90.0f; + } + if (m_zFlipped) { + labelZTrans = -labelZTrans; + alignment = Qt::AlignRight; + } + + const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr); + + // Back wall + QVector3D labelTrans = QVector3D(labelXTrans, labelYTrans, labelZTrans + zComp); + + // Draw the label here + m_dummyRenderItem.setTranslation(labelTrans); + m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, 0.0f, zComp), + QVector3D(rotLabelX, rotLabelY, rotLabelZ), + 0, m_cachedSelectionMode, + m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + alignment); + + // Side wall + if (m_xFlipped) + alignment = Qt::AlignLeft; + else + alignment = Qt::AlignRight; + if (m_zFlipped) + rotLabelY = 180.0f; + else + rotLabelY = 0.0f; + + labelTrans = QVector3D(-labelXTrans, labelYTrans, -labelZTrans + zComp); + + // Draw the label here + m_dummyRenderItem.setTranslation(labelTrans); + m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, 0.0f, zComp), + QVector3D(rotLabelX, rotLabelY, rotLabelZ), + 0, m_cachedSelectionMode, + m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + alignment); + } + labelNbr++; + labelPos += posStep; + } + } + glDisable(GL_TEXTURE_2D); + if (m_cachedLabelTransparency > QDataVis::TransparencyNone) + glDisable(GL_BLEND); + + // Release label shader + m_labelShader->release(); +} + +void Scatter3DRenderer::requestSelectionAtPoint(const QPoint &point) +{ + //qDebug() << __FUNCTION__; + QMutexLocker locker(&m_mutex); + m_selectionPointRequest.setX(point.x()); + m_selectionPointRequest.setY(point.y()); + m_isSelectionPointRequestActive = true; +} + +void Scatter3DRenderer::handleResize() +{ + //qDebug() << __FUNCTION__; + if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) + return; + + // Set view port + m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); + + Abstract3DRenderer::handleResize(); +} + +void Scatter3DRenderer::updateMeshFileName(const QString &objFileName) +{ + Abstract3DRenderer::updateMeshFileName(objFileName); + loadBarMesh(); +} + +void Scatter3DRenderer::updateBackgroundEnabled(bool enable) +{ + if (enable != m_cachedIsBackgroundEnabled) { + Abstract3DRenderer::updateBackgroundEnabled(enable); + loadBarMesh(); // Load changed bar type + } +} + +void Scatter3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) +{ + qDebug() << "Scatter3DRenderer::setShadowQuality" << quality; + m_cachedShadowQuality = quality; + switch (quality) { + case QDataVis::ShadowLow: + m_shadowQualityToShader = 33.3f; + break; + case QDataVis::ShadowMedium: + m_shadowQualityToShader = 100.0f; + break; + case QDataVis::ShadowHigh: + m_shadowQualityToShader = 200.0f; + break; + default: + m_shadowQualityToShader = 0.0f; + break; + } +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + // Re-init shaders + if (!m_cachedTheme.m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } else { + // Re-init shaders + if (!m_cachedTheme.m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + // Re-init depth buffer + updateDepthBuffer(); +#else + if (!m_cachedTheme.m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentColorOnYES2")); + } else { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); +#endif +} + +void Scatter3DRenderer::loadBarMesh() +{ + //qDebug() << __FUNCTION__; + QString objectFileName = m_cachedObjFile; + if (m_dotObj) + delete m_dotObj; + m_dotObj = new ObjectHelper(objectFileName); + m_dotObj->load(); +} + +void Scatter3DRenderer::loadBackgroundMesh() +{ + //qDebug() << __FUNCTION__; + if (m_backgroundObj) + delete m_backgroundObj; + m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background")); + m_backgroundObj->load(); +} + +void Scatter3DRenderer::loadGridLineMesh() +{ + //qDebug() << __FUNCTION__; + if (m_gridLineObj) + delete m_gridLineObj; + m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar")); + m_gridLineObj->load(); +} + +void Scatter3DRenderer::loadLabelMesh() +{ + //qDebug() << __FUNCTION__; + if (m_labelObj) + delete m_labelObj; + m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); + m_labelObj->load(); +} + +void Scatter3DRenderer::updateTextures() +{ + //qDebug() << __FUNCTION__; + // Drawer has changed; this flag needs to be checked when checking if we need to update labels + m_updateLabels = true; +} + +void Scatter3DRenderer::updateAxisRange(QAbstractAxis::AxisOrientation orientation, + qreal min, qreal max) +{ + Abstract3DRenderer::updateAxisRange(orientation, min, max); +} + +void Scatter3DRenderer::calculateTranslation(ScatterRenderItem &item) +{ + //qDebug() << __FUNCTION__; + + // Origin should be in the center of scene, ie. both positive and negative values are drawn + // above background + + // We need to normalize translations + GLfloat xTrans = (aspectRatio * item.position().x()) / m_scaleFactor; + GLfloat zTrans = (aspectRatio * item.position().z()) / m_scaleFactor; + GLfloat yTrans = item.position().y() / m_heightNormalizer; + item.setTranslation(QVector3D(xTrans, yTrans, zTrans + zComp)); + //qDebug() << item.translation(); +} + +void Scatter3DRenderer::calculateSceneScalingFactors() +{ + m_heightNormalizer = (GLfloat)m_axisCacheY.max(); + // TODO: Get rid of m_areaSize and use m_axisCaches directly? + m_areaSize.setHeight(m_axisCacheZ.max()); + m_areaSize.setWidth(m_axisCacheX.max()); + m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()); + //qDebug() << m_heightNormalizer << m_areaSize << m_scaleFactor << m_axisCacheY.max() << m_axisCacheX.max() << m_axisCacheZ.max(); +} + +Scatter3DController::SelectionType Scatter3DRenderer::isSelected(GLint bar, + const QVector3D &selection) +{ + //qDebug() << __FUNCTION__; + GLubyte barIdxRed = 0; + GLubyte barIdxGreen = 0; + GLubyte barIdxBlue = 0; + //static QVector3D prevSel = selection; // TODO: For debugging + Scatter3DController::SelectionType isSelectedType = Scatter3DController::SelectionNone; + + if (selection == selectionSkipColor) + return isSelectedType; // skip window + + if (bar <= 255) { + barIdxRed = bar; + } else if (bar <= 65535) { + barIdxGreen = bar / 256; + barIdxRed = bar % 256; + } else { + barIdxBlue = bar / 65535; + barIdxGreen = bar % 65535; + barIdxRed = bar % 256; + } + + QVector3D current = QVector3D(barIdxRed, barIdxGreen, barIdxBlue); + + // TODO: For debugging + //if (selection != prevSel) { + // qDebug() << selection.x() << selection .y() << selection.z(); + // prevSel = selection; + //} + + if (current == selection) + isSelectedType = Scatter3DController::SelectionItem; + + return isSelectedType; +} + +QRect Scatter3DRenderer::mainViewPort() +{ + //qDebug() << __FUNCTION__; + return m_mainViewPort; +} + +void Scatter3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader) +{ + //qDebug() << __FUNCTION__; + if (m_dotShader) + delete m_dotShader; + m_dotShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_dotShader->initialize(); +} + +void Scatter3DRenderer::initSelectionShader() +{ + //qDebug() << __FUNCTION__; + if (m_selectionShader) + delete m_selectionShader; + m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSelection"), + QStringLiteral(":/shaders/fragmentSelection")); + m_selectionShader->initialize(); +} + +void Scatter3DRenderer::initSelectionBuffer() +{ + //qDebug() << __FUNCTION__; + if (m_selectionTexture) + m_textureHelper->deleteTexture(&m_selectionTexture); + + m_selectionTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(), + m_selectionFrameBuffer, + m_selectionDepthBuffer); +} + +#if !defined(QT_OPENGL_ES_2) +void Scatter3DRenderer::initDepthShader() +{ + //qDebug() << __FUNCTION__; + if (m_depthShader) + delete m_depthShader; + m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"), + QStringLiteral(":/shaders/fragmentDepth")); + m_depthShader->initialize(); +} + +void Scatter3DRenderer::updateDepthBuffer() +{ + //qDebug() << __FUNCTION__; + if (m_depthTexture) { + m_textureHelper->deleteTexture(&m_depthTexture); + m_depthTexture = 0; + } + + if (m_cachedShadowQuality > QDataVis::ShadowNone) { + m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(), + m_depthFrameBuffer, + m_cachedShadowQuality); + if (!m_depthTexture) { + switch (m_cachedShadowQuality) { + case QDataVis::ShadowHigh: + qWarning("Creating high quality shadows failed. Changing to medium quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowMedium); + break; + case QDataVis::ShadowMedium: + qWarning("Creating medium quality shadows failed. Changing to low quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowLow); + break; + case QDataVis::ShadowLow: + qWarning("Creating low quality shadows failed. Switching shadows off."); + (void)m_controller->setShadowQuality(QDataVis::ShadowNone); + break; + default: + // You'll never get here + break; + } + } + } +} +#endif + +void Scatter3DRenderer::initBackgroundShaders(const QString &vertexShader, + const QString &fragmentShader) +{ + //qDebug() << __FUNCTION__; + if (m_backgroundShader) + delete m_backgroundShader; + m_backgroundShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_backgroundShader->initialize(); +} + +void Scatter3DRenderer::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) +{ + //qDebug() << __FUNCTION__; + if (m_labelShader) + delete m_labelShader; + m_labelShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_labelShader->initialize(); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/scatter3drenderer_p.h b/src/datavis3d/engine/scatter3drenderer_p.h new file mode 100644 index 00000000..45054db4 --- /dev/null +++ b/src/datavis3d/engine/scatter3drenderer_p.h @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 Q3DSCATTERRENDERER_P_H +#define Q3DSCATTERRENDERER_P_H + +#include <QtCore/QSize> +#include <QtCore/QObject> +#include <QtGui/QOpenGLFunctions> +#include <QtGui/QFont> +#include <QTime> +#include <QWindow> +#include <QMutex> + +#include "datavis3dglobal_p.h" +#include "scatter3dcontroller_p.h" +#include "abstract3drenderer_p.h" +#include "qscatterdataproxy.h" +#include "scatterrenderitem_p.h" + +//#define DISPLAY_RENDER_SPEED + +class QPoint; +class QSizeF; +class QOpenGLShaderProgram; + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class ShaderHelper; +class ObjectHelper; +class TextureHelper; +class LabelItem; +class CameraHelper; +class QAbstractAxisPrivate; + +class QT_DATAVIS3D_EXPORT Scatter3DRenderer : public Abstract3DRenderer +{ + Q_OBJECT + +private: + // TODO: Filter to the set of attributes to be moved to the model object. + // * All GL rendering only related attribs should be moved out of this public set. + // * All attribs that are modifiable from QML need to e in this set. + + Scatter3DController *m_controller; + + // Mutex for sharing resources between render and main threads. + // TODO: this mutex needs to go, too + QMutex m_mutex; + + // Internal state + ScatterRenderItem *m_selectedItem; // points to renderitem array + ScatterRenderItem *m_previouslySelectedItem; // points to renderitem array + bool m_xFlipped; + bool m_zFlipped; + bool m_yFlipped; + QRect m_mainViewPort; + bool m_updateLabels; + ShaderHelper *m_dotShader; + ShaderHelper *m_depthShader; + ShaderHelper *m_selectionShader; + ShaderHelper *m_backgroundShader; + ShaderHelper *m_labelShader; + ObjectHelper *m_dotObj; + ObjectHelper *m_backgroundObj; + ObjectHelper *m_gridLineObj; + ObjectHelper *m_labelObj; + TextureHelper *m_textureHelper; + GLuint m_bgrTexture; + GLuint m_depthTexture; + GLuint m_selectionTexture; + GLuint m_depthFrameBuffer; + GLuint m_selectionFrameBuffer; + GLuint m_selectionDepthBuffer; + GLfloat m_shadowQualityToShader; + GLfloat m_heightNormalizer; + GLfloat m_scaleFactor; + QVector3D m_selection; + QSizeF m_areaSize; + GLfloat m_dotSizeScale; + + QPoint m_selectionPointRequest; + bool m_isSelectionPointRequestActive; + + bool m_hasHeightAdjustmentChanged; + ScatterRenderItem m_dummyRenderItem; + + ScatterRenderItemArray m_renderItemArray; + +#ifdef DISPLAY_RENDER_SPEED + bool m_isFirstFrame; + QTime m_lastFrameTime; + GLint m_numFrames; +#endif + +public: + explicit Scatter3DRenderer(Scatter3DController *controller); + ~Scatter3DRenderer(); + + void updateDataModel(QScatterDataProxy *dataProxy); + void render(CameraHelper *camera, const GLuint defaultFboHandle); + + QRect mainViewPort(); + +public slots: + void updateBackgroundEnabled(bool enable); + void updateMeshFileName(const QString &objFileName); + + // Overloaded from abstract renderer + virtual void updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); + + // Requests that upon next render pass the column and row under the given point is inspected for selection. + // Only one request can be queued per render pass at this point. New request will override any pending requests. + // After inspection the selectionUpdated signal is emitted. + virtual void requestSelectionAtPoint(const QPoint &point); + +signals: + void selectionUpdated(QVector3D selection); + +private: + virtual void initializeOpenGL(); + virtual void initShaders(const QString &vertexShader, const QString &fragmentShader); + virtual void updateShadowQuality(QDataVis::ShadowQuality quality); + virtual void updateTextures(); + + void drawScene(CameraHelper *camera, const GLuint defaultFboHandle); + void handleResize(); + + void loadBarMesh(); + void loadBackgroundMesh(); + void loadGridLineMesh(); + void loadLabelMesh(); + void initSelectionShader(); + void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); + void initLabelShaders(const QString &vertexShader, const QString &fragmentShader); + void initSelectionBuffer(); +#if !defined(QT_OPENGL_ES_2) + void initDepthShader(); + void updateDepthBuffer(); +#endif + void calculateTranslation(ScatterRenderItem &item); + void calculateSceneScalingFactors(); + Scatter3DController::SelectionType isSelected(GLint bar, const QVector3D &selection); + + Q_DISABLE_COPY(Scatter3DRenderer) + + friend class ScatterRenderItem; +}; + + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/shaders/colorOnY_ES2.frag b/src/datavis3d/engine/shaders/colorOnY_ES2.frag index dd7c0cf3..68c8ac39 100644 --- a/src/datavis3d/engine/shaders/colorOnY_ES2.frag +++ b/src/datavis3d/engine/shaders/colorOnY_ES2.frag @@ -31,5 +31,6 @@ void main() { materialAmbientColor + materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / (distance * distance) + materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / (distance * distance); + gl_FragColor.a = 1.0; } diff --git a/src/datavis3d/engine/shaders/selection.frag b/src/datavis3d/engine/shaders/selection.frag index 1658b316..099c87a1 100644 --- a/src/datavis3d/engine/shaders/selection.frag +++ b/src/datavis3d/engine/shaders/selection.frag @@ -2,5 +2,6 @@ uniform highp vec3 color_mdl; void main() { gl_FragColor.rgb = color_mdl; + gl_FragColor.a = 1.0; } diff --git a/src/datavis3d/engine/shaders/surface.frag b/src/datavis3d/engine/shaders/surface.frag new file mode 100644 index 00000000..9fe7f45b --- /dev/null +++ b/src/datavis3d/engine/shaders/surface.frag @@ -0,0 +1,39 @@ +#version 120 + +varying highp vec2 UV; +varying highp vec3 coords_mdl; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; + +uniform sampler2D textureSampler; +uniform highp vec3 lightPosition_wrld; +uniform highp float lightStrength; +uniform highp float ambientStrength; + +void main() { + highp vec2 gradientUV = vec2(0.5, (coords_mdl.y + 1.0) / 2.0); + highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz; + highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; + highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); + + highp float distance = length(lightPosition_wrld - position_wrld); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + +// gl_FragColor.rgb = materialDiffuseColor; + gl_FragColor.rgb = + materialAmbientColor + + materialDiffuseColor * lightStrength * pow(cosTheta, 2) / distance + + materialSpecularColor * lightStrength * pow(cosAlpha, 10) / distance; + gl_FragColor.a = 1.0; +// gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); +} + diff --git a/src/datavis3d/engine/shaders/surface.vert b/src/datavis3d/engine/shaders/surface.vert new file mode 100644 index 00000000..cbfb7569 --- /dev/null +++ b/src/datavis3d/engine/shaders/surface.vert @@ -0,0 +1,30 @@ +#version 120 + +attribute highp vec3 vertexPosition_mdl; +attribute highp vec2 vertexUV; +attribute highp vec3 vertexNormal_mdl; + +uniform highp mat4 MVP; +uniform highp mat4 V; +uniform highp mat4 M; +uniform highp mat4 itM; +uniform highp vec3 lightPosition_wrld; + +varying highp vec2 UV; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; +varying highp vec3 coords_mdl; + +void main() { + gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); + coords_mdl = vertexPosition_mdl; + position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz; + vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz; + eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr; + vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz; + lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr; + normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; + UV = vertexUV; +} diff --git a/src/datavis3d/engine/shaders/surfaceFlat.frag b/src/datavis3d/engine/shaders/surfaceFlat.frag new file mode 100644 index 00000000..eb398582 --- /dev/null +++ b/src/datavis3d/engine/shaders/surfaceFlat.frag @@ -0,0 +1,38 @@ +#version 150 + +varying highp vec2 UV; +varying highp vec3 coords_mdl; +varying highp vec3 position_wrld; +flat in highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; + +uniform sampler2D textureSampler; +uniform highp vec3 lightPosition_wrld; +uniform highp float lightStrength; +uniform highp float ambientStrength; + +void main() { + highp vec2 gradientUV = vec2(0.5, (coords_mdl.y + 1.0) / 2.0); + highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz; + highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; + highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); + + highp float distance = length(lightPosition_wrld - position_wrld); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + +// gl_FragColor.rgb = materialDiffuseColor; + gl_FragColor.rgb = + materialAmbientColor + + materialDiffuseColor * lightStrength * pow(cosTheta, 2) / distance + + materialSpecularColor * lightStrength * pow(cosAlpha, 10) / distance; + gl_FragColor.a = 1.0; +} + diff --git a/src/datavis3d/engine/shaders/surfaceFlat.vert b/src/datavis3d/engine/shaders/surfaceFlat.vert new file mode 100644 index 00000000..24c9b9a3 --- /dev/null +++ b/src/datavis3d/engine/shaders/surfaceFlat.vert @@ -0,0 +1,30 @@ +#version 150 + +attribute highp vec3 vertexPosition_mdl; +attribute highp vec2 vertexUV; +attribute highp vec3 vertexNormal_mdl; + +uniform highp mat4 MVP; +uniform highp mat4 V; +uniform highp mat4 M; +uniform highp mat4 itM; +uniform highp vec3 lightPosition_wrld; + +varying highp vec2 UV; +varying highp vec3 position_wrld; +flat out highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; +varying highp vec3 coords_mdl; + +void main() { + gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); + coords_mdl = vertexPosition_mdl; + position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz; + vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz; + eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr; + vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz; + lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr; + normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; + UV = vertexUV; +} diff --git a/src/datavis3d/engine/shaders/surfaceGrid.frag b/src/datavis3d/engine/shaders/surfaceGrid.frag new file mode 100644 index 00000000..20b923fb --- /dev/null +++ b/src/datavis3d/engine/shaders/surfaceGrid.frag @@ -0,0 +1,16 @@ +varying highp vec2 UV; +varying highp vec2 coords_mdl; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; + +uniform highp vec3 lightPosition_wrld; +uniform highp vec3 color_mdl; +uniform highp float lightStrength; +uniform highp float ambientStrength; + +void main() { + gl_FragColor.rgb = color_mdl; +} + diff --git a/src/datavis3d/engine/shaders/surfaceGrid.vert b/src/datavis3d/engine/shaders/surfaceGrid.vert new file mode 100644 index 00000000..efb40862 --- /dev/null +++ b/src/datavis3d/engine/shaders/surfaceGrid.vert @@ -0,0 +1,26 @@ +attribute highp vec3 vertexPosition_mdl; +attribute highp vec2 vertexUV; +attribute highp vec3 vertexNormal_mdl; + +uniform highp mat4 MVP; +uniform highp mat4 V; +uniform highp mat4 M; +uniform highp mat4 itM; +uniform highp vec3 lightPosition_wrld; + +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; +varying highp vec2 coords_mdl; + +void main() { + gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); + coords_mdl = vertexPosition_mdl.xy; + position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz; + vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz; + eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr; + vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz; + lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr; + normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; +} diff --git a/src/datavis3d/engine/surface3dcontroller.cpp b/src/datavis3d/engine/surface3dcontroller.cpp new file mode 100644 index 00000000..2915c993 --- /dev/null +++ b/src/datavis3d/engine/surface3dcontroller.cpp @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "surface3dcontroller_p.h" +#include "surface3drenderer_p.h" +#include "camerahelper_p.h" + +#include <QMatrix4x4> +#include <QMouseEvent> + +#include <QDebug> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +Surface3dController::Surface3dController(QRect rect) + : Abstract3DController(rect), + m_mouseState(MouseNone), + m_mousePos(QPoint(0, 0)), + m_renderer(0), + m_isInitialized(false), + m_smoothSurface(false), + m_surfaceGrid(true) +{ +} + +Surface3dController::~Surface3dController() +{ +} + +void Surface3dController::initializeOpenGL() +{ + // Initialization is called multiple times when Qt Quick components are used + if (m_isInitialized) + return; + + m_renderer = new Surface3dRenderer(this); + m_isInitialized = true; +} + +void Surface3dController::synchDataToRenderer() +{ + // TODO: Implement +} + +void Surface3dController::render(const GLuint defaultFboHandle) +{ + if (!m_isInitialized) + return; + + m_renderer->render(m_cameraHelper, defaultFboHandle); +} + +void Surface3dController::handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust) +{ + Q_UNUSED(orientation) + Q_UNUSED(autoAdjust) + + // TODO: Implement! +} + +QMatrix4x4 Surface3dController::calculateViewMatrix(int zoom, int viewPortWidth, int viewPortHeight, bool showUnder) +{ + return m_cameraHelper->calculateViewMatrix(m_mousePos, + zoom, + viewPortWidth, + viewPortHeight, + showUnder); +} + +void Surface3dController::setWidth(const int width) +{ + qDebug() << "Surface3dController::setWidth"; + m_renderer->setWidth(width); +} + +void Surface3dController::setHeight(const int height) +{ + qDebug() << "Surface3dController::setHeight"; + m_renderer->setHeight(height); +} + +void Surface3dController::setSmoothSurface(bool enable) +{ + m_smoothSurface = enable; + emit smoothStatusChanged(m_smoothSurface); +} + +bool Surface3dController::smoothSurface() +{ + return m_smoothSurface; +} + +void Surface3dController::setSurfaceGrid(bool enable) +{ + m_surfaceGrid = enable; + emit surfaceGridChanged(m_surfaceGrid); +} + +bool Surface3dController::surfaceGrid() +{ + return m_surfaceGrid; +} + + +#if defined(Q_OS_ANDROID) +void Surface3dController::mouseDoubleClickEvent(QMouseEvent *event) +{ +} +void touchEvent(QTouchEvent *event) +{ +} +#endif + +void Surface3dController::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) +{ + if (Qt::LeftButton == event->button()) { + m_mousePos = mousePos; + emit leftMousePressed(); + } else if (Qt::RightButton == event->button()) { + #if !defined(Q_OS_ANDROID) + m_mouseState = Abstract3DController::MouseRotating; + #else + m_mouseState = Abstract3DController::MouseOnScene; + #endif + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = mousePos; //event->pos(); + } + m_cameraHelper->updateMousePos(m_mousePos); +} + +void Surface3dController::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event) + if (Abstract3DController::MouseRotating == m_mouseState) { + // update mouse positions to prevent jumping when releasing or repressing a button + m_mousePos = mousePos; //event->pos(); + m_cameraHelper->updateMousePos(mousePos); //event->pos()); + } + m_mouseState = Abstract3DController::MouseNone; +} + +void Surface3dController::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event) + if (Abstract3DController::MouseRotating == m_mouseState) + m_mousePos = mousePos; //event->pos(); +} + +void Surface3dController::wheelEvent(QWheelEvent *event) +{ + Q_UNUSED(event) +} + +QPoint Surface3dController::mousePosition() +{ + return m_mousePos; +} + + +// TODO: abstract renderer should have accessor for Drawer instead +Drawer *Surface3dController::drawer() +{ + if (m_renderer) + return m_renderer->drawer(); + else + return 0; +} + +void Surface3dController::setSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum) +{ + m_segmentCount = segmentCount; + m_segmentStep = step; + m_segmentMinimum = minimum; + + emit segmentCountChanged(m_segmentCount, m_segmentStep, m_segmentMinimum); +} + +void Surface3dController::setGradientColorAt(qreal pos, const QColor &color) +{ + Theme t = theme(); + t.m_surfaceGradient.setColorAt(pos, color); + emit themeChanged(t); +} + +// TODO: Temp +void Surface3dController::setData(QList<qreal> series, int width, int depth) +{ + m_series = series; + m_dataWidth = width; + m_dataDepth = depth; + + m_renderer->setXZStuff(width, depth); + m_renderer->setSeries(series); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/surface3dcontroller_p.h b/src/datavis3d/engine/surface3dcontroller_p.h new file mode 100644 index 00000000..d8c36d08 --- /dev/null +++ b/src/datavis3d/engine/surface3dcontroller_p.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 SURFACE3DCONTROLLER_P_H +#define SURFACE3DCONTROLLER_P_H + +#include "abstract3dcontroller_p.h" +#include "datavis3dglobal_p.h" + +#include <QLinearGradient> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class Surface3dRenderer; + +class QT_DATAVIS3D_EXPORT Surface3dController : public Abstract3DController +{ + Q_OBJECT + +private: + Surface3dRenderer *m_renderer; + bool m_isInitialized; + QList<qreal> m_series; // TODO: TEMP + int m_dataWidth; + int m_dataDepth; + bool m_smoothSurface; + bool m_surfaceGrid; + + GLint m_segmentCount; + GLfloat m_segmentStep; + GLfloat m_segmentMinimum; + + // Interaction + MouseState m_mouseState; + QPoint m_mousePos; + QDataVis::SelectionMode m_selectionMode; + +public: + explicit Surface3dController(QRect rect); + ~Surface3dController(); + + void initializeOpenGL(); + void synchDataToRenderer(); + void render(const GLuint defaultFboHandle = 0); + + QPoint mousePosition(); + + QMatrix4x4 calculateViewMatrix(int zoom, int viewPortWidth, int viewPortHeight, bool showUnder = false); + + void setWidth(const int width); + void setHeight(const int height); + + // Enable or disable the smoothes of the surface + void setSmoothSurface(bool enable); + bool smoothSurface(); + + // Enable or disable the grid on the surface + void setSurfaceGrid(bool enable); + bool surfaceGrid(); + + void setGradientColorAt(qreal pos, const QColor &color); + + // Set segment count and step. Note; segmentCount * step should be the maximum possible value of data + // set. Minimum is the absolute minimum possible value a bar can have. This is especially + // important to set if values can be negative. + void setSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum = 0.0f); + + //TODO: Temp solution + void setData(QList<qreal> series, int width, int depth); + +#if defined(Q_OS_ANDROID) + void mouseDoubleClickEvent(QMouseEvent *event); + void touchEvent(QTouchEvent *event); +#endif + void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); + void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); + void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); + void wheelEvent(QWheelEvent *event); + + // TODO: abstract renderer should have accessor for Drawer instead + virtual Drawer *drawer(); + virtual void handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust); + +signals: + void smoothStatusChanged(bool enable); + void surfaceGridChanged(bool enable); + void segmentCountChanged(GLint segmentCount, GLfloat step, GLfloat minimum); + void leftMousePressed(); + +private: + Q_DISABLE_COPY(Surface3dController) +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // SURFACE3DCONTROLLER_P_H diff --git a/src/datavis3d/engine/surface3drenderer.cpp b/src/datavis3d/engine/surface3drenderer.cpp new file mode 100644 index 00000000..c66bd291 --- /dev/null +++ b/src/datavis3d/engine/surface3drenderer.cpp @@ -0,0 +1,894 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "surface3dcontroller_p.h" +#include "surface3drenderer_p.h" +#include "camerahelper_p.h" +#include "shaderhelper_p.h" +#include "objecthelper_p.h" +#include "surfaceobject_p.h" +#include "texturehelper_p.h" +#include "theme_p.h" +#include "utils_p.h" +#include "drawer_p.h" + +#include <QMatrix4x4> +#include <QMouseEvent> +#include <qmath.h> + +#include <QLinearGradient> +#include <QPainter> + +#include <QDebug> + +static const int ID_TO_RGBA_MASK = 0xff; + +QT_DATAVIS3D_BEGIN_NAMESPACE + +Surface3dRenderer::Surface3dRenderer(Surface3dController *controller) + : QObject(controller), + m_controller(controller), + m_mousePressed(MouseNone), + m_mousePos(QPoint(0, 0)), + m_isGridEnabled(true), + m_isBackgroundEnabled(true), + m_shadowQuality(QDataVis::ShadowLow), + m_labelTransparency(QDataVis::TransparencyFromTheme), + m_font(QFont(QStringLiteral("Arial"))), + m_hasNegativeValues(false), + m_segmentYCount(0), + m_segmentYStep(0.0f), + m_segmentXCount(0), + m_segmentZCount(0), + m_backgroundShader(0), + m_surfaceShader(0), + m_surfaceGridShader(0), + m_selectionShader(0), + m_isInitialized(false), + m_yRange(0.0f), // m_heightNormalizer + m_yAdjustment(0.0f), + m_xLength(0.0f), + m_zLength(0.0f), + m_maxDimension(0.0f), + m_scaleFactor(0.0f), + m_scaleX(0.0f), + m_scaleZ(0.0f), + m_maxSceneSize(40.0), + m_backgroundObj(0), + m_gridLineObj(0), + m_surfaceObj(0), + m_depthTexture(0), + m_depthFrameBuffer(0), + m_selectionFrameBuffer(0), + m_selectionDepthBuffer(0), + m_gradientTexture(0), + m_selectionTexture(0), + m_selectionResultTexture(0), + m_shadowQualityToShader(33.3f), + m_querySelection(false), + m_drawer(new Drawer(m_cachedTheme, m_font, m_labelTransparency)) +{ + // Listen to changes in the controller + QObject::connect(m_controller, &Surface3dController::smoothStatusChanged, this, + &Surface3dRenderer::updateSmoothStatus); + QObject::connect(m_controller, &Surface3dController::surfaceGridChanged, this, + &Surface3dRenderer::updateSurfaceGridStatus); + QObject::connect(m_controller, &Surface3dController::segmentCountChanged, this, + &Surface3dRenderer::updateSegmentCount); + QObject::connect(m_controller, &Surface3dController::themeChanged, this, + &Surface3dRenderer::updateTheme); + QObject::connect(m_controller, &Surface3dController::leftMousePressed, this, + &Surface3dRenderer::getSelection); + + m_cachedSmoothSurface = m_controller->smoothSurface(); + updateSurfaceGridStatus(m_controller->surfaceGrid()); + updateTheme(m_controller->theme()); + + initializeOpenGL(); +} + +Surface3dRenderer::~Surface3dRenderer() +{ + qDebug() << "Surface3dRenderer::~Surface3dRenderer()"; + m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); + m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); + m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); + + m_textureHelper->deleteTexture(&m_depthTexture); + m_textureHelper->deleteTexture(&m_gradientTexture); + m_textureHelper->deleteTexture(&m_selectionTexture); + m_textureHelper->deleteTexture(&m_selectionResultTexture); + + delete m_backgroundShader; + delete m_selectionShader; + delete m_surfaceShader; + delete m_surfaceGridShader; + + delete m_backgroundObj; + delete m_surfaceObj; + delete m_textureHelper; + delete m_drawer; +} + +void Surface3dRenderer::initializeOpenGL() +{ + // Initialization is called multiple times when Qt Quick components are used + if (m_isInitialized) + return; + + initializeOpenGLFunctions(); + + m_textureHelper = new TextureHelper(); + m_drawer->initializeOpenGL(); + + // Initialize shaders +#if !defined(QT_OPENGL_ES_2) + if (m_shadowQuality > QDataVis::ShadowNone) { + initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } else { + initBackgroundShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } +#else + initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); +#endif + + initSurfaceShaders(); + + // Init selection shader + initSelectionShaders(); + + // Load grid line mesh + loadGridLineMesh(); + + // Load label mesh + //loadLabelMesh(); + + // Set OpenGL features + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + +#if !defined(QT_OPENGL_ES_2) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); +#endif + + // Set view port + glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(), + m_sliceViewPort.width(), m_sliceViewPort.height()); + + // Set initialized -flag + m_isInitialized = true; + + // Resize in case we've missed resize events + // Resize calls initSelectionBuffer and initDepthBuffer, so they don't need to be called here + handleResize(); + + // Load background mesh (we need to be initialized first) + loadBackgroundMesh(); + + //loadSurfaceObj(); +} + +void Surface3dRenderer::render(CameraHelper *camera, const GLuint defaultFboHandle) +{ + if (!m_isInitialized) + return; + + if (defaultFboHandle) { + glDepthMask(true); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + } + + QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme.m_windowColor); + glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // TODO: bars have m_hasHeightAdjustmentChanged, which is always true! + // Set initial camera position + // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later + camera->setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + + drawScene(camera, defaultFboHandle); +} + +void Surface3dRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboHandle) +{ + //qDebug() << "Surface3dRenderer::drawScene"; + + GLfloat backgroundRotation = 0; + + // Specify viewport + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width(), m_mainViewPort.height()); + + // Set up projection matrix + QMatrix4x4 projectionMatrix; + projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width() + / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f); + + // Calculate view matrix + QMatrix4x4 viewMatrix = m_controller->calculateViewMatrix( + 100.0f, //TODO: m_zoomLevel * m_autoScaleAdjustment + m_mainViewPort.width(), + m_mainViewPort.height(), + m_hasNegativeValues); + + // calculate background rotation based on view matrix rotation + if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() <= 0) + backgroundRotation = 270.0f; + else if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() > 0) + backgroundRotation = 180.0f; + else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() > 0) + backgroundRotation = 90.0f; + else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() <= 0) + backgroundRotation = 0.0f; + + QVector3D lightPos = camera->calculateLightPosition(defaultLightPos); + + QMatrix4x4 depthViewMatrix; + QMatrix4x4 depthProjectionMatrix; + depthProjectionMatrix = projectionMatrix; // TODO + depthViewMatrix.lookAt(lightPos, QVector3D(0.0f, -m_yAdjustment, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); // TODO: Move + + // Enable texturing + glEnable(GL_TEXTURE_2D); + + // + // Do the surface drawing + // + + if (m_querySelection && m_surfaceObj) { + m_selectionShader->bind(); + glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); + glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer + glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled + + glDisable(GL_CULL_FACE); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); + modelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, + 1.0f, + m_zLength / m_scaleFactor)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + + m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); + + // Activate texture + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_selectionTexture); + m_selectionShader->setUniformValue(m_selectionShader->texture(), 0); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_selectionShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_surfaceObj->vertexBuf()); + glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // 3rd attribute buffer : UVs + glEnableVertexAttribArray(m_selectionShader->uvAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_surfaceObj->uvBuf()); + glVertexAttribPointer(m_selectionShader->uvAtt(), 2, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_surfaceObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(), (void *)0); + //m_drawer->drawObject(m_selectionShader, m_surfaceObj, m_selectionTexture, 0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(m_selectionShader->uvAtt()); + glDisableVertexAttribArray(m_selectionShader->posAtt()); + + glEnable(GL_DITHER); + + m_querySelection = false; + + QPoint point = m_controller->mousePosition(); + GLubyte pixel[4] = {0}; + glReadPixels(point.x(), height() - point.y(), 1, 1, + GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixel); + //uint id = pixel[0] + pixel[1] * 256 + pixel[2] * 65536 + pixel[3] * 16777216; + + qDebug() << "pixel = " << pixel[0] << ", " << pixel[1] << ", " << pixel[2] << ", " << pixel[3]; + + glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); + + // Release selection shader + m_selectionShader->release(); + } + + if (m_surfaceObj) { + m_surfaceShader->bind(); + // m_selectionShader->bind(); // IFDEF print selection + + // For surface we can see climpses from underneath + glDisable(GL_CULL_FACE); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); + modelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, + 1.0f, + m_zLength / m_scaleFactor)); + itModelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, + 1.0f, + m_zLength / m_scaleFactor)); + +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif + // TODO Check the usage? + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set shader bindings + m_surfaceShader->setUniformValue(m_surfaceShader->lightP(), lightPos); + m_surfaceShader->setUniformValue(m_surfaceShader->view(), viewMatrix); + m_surfaceShader->setUniformValue(m_surfaceShader->model(), modelMatrix); + m_surfaceShader->setUniformValue(m_surfaceShader->nModel(), itModelMatrix.inverted().transposed()); + m_surfaceShader->setUniformValue(m_surfaceShader->MVP(), MVPMatrix); + //m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); // IFDEF print selection + m_surfaceShader->setUniformValue(m_surfaceShader->ambientS(), m_cachedTheme.m_ambientStrength); + + //IF QT_OPENGL_ES_2 TODO + // Shadow quality etc. + //m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), m_shadowQualityToShader); + //m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix); + m_surfaceShader->setUniformValue(m_surfaceShader->lightS(), + m_cachedTheme.m_lightStrength * 2.0f); + + m_drawer->drawObject(m_surfaceShader, m_surfaceObj, m_gradientTexture, m_depthTexture); + //m_drawer->drawObject(m_selectionShader, m_surfaceObj, m_selectionTexture, 0); // IFDEF print selection + + m_surfaceShader->release(); + //m_selectionShader->release(); // IFDEF print selection + + if (m_cachedSurfaceGridOn) { + // Draw the grid over the surface + glPolygonOffset(1.0f, 1.0f); + glEnable(GL_POLYGON_OFFSET_FILL); + + m_surfaceGridShader->bind(); + + QVector3D gridColor = Utils::vectorFromColor(QColor(Qt::white)); + // Set shader bindings + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->view(), viewMatrix); + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->model(), modelMatrix); + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->nModel(), itModelMatrix.inverted().transposed()); + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix); + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(), gridColor); + //m_surfaceGridShader->setUniformValue(m_surfaceGridShader->ambientS(), m_theme->m_ambientStrength); + m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_surfaceObj); + + m_surfaceGridShader->release(); + + glPolygonOffset(0.0f, 0.0f); + glDisable(GL_POLYGON_OFFSET_FILL); + } + } + + // Bind background shader + m_backgroundShader->bind(); + + if (m_hasNegativeValues) + glDisable(GL_CULL_FACE); + else + glCullFace(GL_BACK); + + // Draw background + if (m_isBackgroundEnabled && m_backgroundObj) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); + modelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, + 1.0f, + m_zLength / m_scaleFactor)); + modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); + itModelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, + 1.0f, + m_zLength / m_scaleFactor)); + +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme.m_backgroundColor); + + // Set shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos); + m_backgroundShader->setUniformValue(m_backgroundShader->view(), viewMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->model(), modelMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->nModel(), + itModelMatrix.inverted().transposed()); + m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->color(), backgroundColor); + m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(), + m_cachedTheme.m_ambientStrength * 2.0f); + +#if !defined(QT_OPENGL_ES_2) + if (m_shadowQuality > QDataVis::ShadowNone) { + // Set shadow shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), + m_shadowQualityToShader); + m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_backgroundShader, m_backgroundObj); + } + } + + // Release background shader + m_backgroundShader->release(); + + // Disable textures + glDisable(GL_TEXTURE_2D); + + // Reset culling + if (m_hasNegativeValues) { + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + } +} + +void Surface3dRenderer::updateSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum) +{ + m_segmentYCount = segmentCount; + m_segmentYStep = step; + if (segmentCount > 0 && step > 0.0) { + m_yRange = m_segmentYCount * m_segmentYStep; + m_yAdjustment = 2.0f - ((m_yRange - minimum) / m_yRange); // TODO: to function + } + + qDebug() << "m_yAdjustment = " << m_yAdjustment; +} + +void Surface3dRenderer::setXZStuff(GLint segmentXCount, GLint segmentZCount) +{ + m_segmentXCount = segmentXCount; + m_segmentZCount = segmentZCount; + + // TODO: Invent "idiotproof" max scene size formula.. + // This seems to work ok if spacing is not negative (and row/column or column/row ratio is not too high) + m_maxSceneSize = 2 * qSqrt(segmentXCount * segmentZCount); + + calculateSceneScalingFactors(); +} + +void Surface3dRenderer::updateTheme(Theme theme) +{ + m_cachedTheme.setFromTheme(theme); + + // Update things depending from the theme + updateSurfaceGradient(); +} + +void Surface3dRenderer::updateSurfaceGradient() +{ + QImage image(QSize(4, 100), QImage::Format_RGB32); + QPainter pmp(&image); + pmp.setBrush(QBrush(m_cachedTheme.m_surfaceGradient)); + pmp.setPen(Qt::NoPen); + pmp.drawRect(0, 0, 4, 100); + + // QImage image(QStringLiteral("C:\\Users\\misalmel\\Work\\gerrit\\qtdatavis3d_2\\grid.png")); + + if (m_gradientTexture) { + m_textureHelper->deleteTexture(&m_gradientTexture); + m_gradientTexture = 0; + } + + m_gradientTexture = m_textureHelper->create2DTexture(image, false, true); +} + +void Surface3dRenderer::updateSelectionTexture() +{ + // Create the selection ID image. Each grid corner gets 2x2 pixel area of + // ID color so that each vertex (data point) has 4x4 pixel area of ID color + // TODO: power of two thing for ES + int idImageWidth = (m_segmentXCount - 1) * 4; + int idImageHeight = (m_segmentZCount - 1) * 4; + int stride = idImageWidth * 4 * sizeof(uchar); // 4 = number of color components (rgba) + + uchar *bits = new uchar[idImageWidth * idImageHeight * 4 * sizeof(uchar)]; + uint id = 1; + for (int i = 0; i < idImageHeight; i += 4) { + for (int j = 0; j < idImageWidth; j += 4) { + int p = (i * idImageWidth + j) * 4; + uchar r, g, b, a; + idToRGBA(id, &r, &g, &b, &a); + fillIdCorner(&bits[p], r, g, b, a, stride); + + idToRGBA(id + 1, &r, &g, &b, &a); + fillIdCorner(&bits[p + 8], r, g, b, a, stride); + + idToRGBA(id + m_segmentXCount, &r, &g, &b, &a); + fillIdCorner(&bits[p + 2 * stride], r, g, b, a, stride); + + idToRGBA(id + m_segmentXCount + 1, &r, &g, &b, &a); + fillIdCorner(&bits[p + 2 * stride + 8], r, g, b, a, stride); + + id++; + } + id++; + } + + // Use this to save the ID image to file + //QImage image(bits, idImageWidth, idImageHeight, QImage::Format_ARGB32); + //image.save("C:\\Users\\misalmel\\Work\\gerrit\\qtdatavis3d_2\\selection.png"); + + // If old texture exists, delete it + if (m_selectionTexture) { + m_textureHelper->deleteTexture(&m_selectionTexture); + m_selectionTexture = 0; + } + + // Move the ID image (bits) to the texture + m_selectionTexture = m_textureHelper->create2DTexture(bits, idImageWidth, idImageHeight); + + // Release the temp bits allocation + delete bits; + + // Create the result selection texture and buffers + if (m_selectionResultTexture) { + m_textureHelper->deleteTexture(&m_selectionResultTexture); + m_selectionResultTexture = 0; + } + + m_selectionResultTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(), + m_selectionFrameBuffer, + m_selectionDepthBuffer); +} + +void Surface3dRenderer::fillIdCorner(uchar *p, uchar r, uchar g, uchar b, uchar a, int stride) +{ + p[0] = r; + p[1] = g; + p[2] = b; + p[3] = a; + p[4] = r; + p[5] = g; + p[6] = b; + p[7] = a; + p[stride + 0] = r; + p[stride + 1] = g; + p[stride + 2] = b; + p[stride + 3] = a; + p[stride + 4] = r; + p[stride + 5] = g; + p[stride + 6] = b; + p[stride + 7] = a; +} + +void Surface3dRenderer::idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a) +{ + *r = id & ID_TO_RGBA_MASK; + *g = (id >> 8) & ID_TO_RGBA_MASK; + *b = (id >> 16) & ID_TO_RGBA_MASK; + *a = (id >> 24) & ID_TO_RGBA_MASK; +} + +void Surface3dRenderer::getSelection() +{ + qDebug() << "Surface3dRenderer::getSelection"; + m_querySelection = true; +} + +void Surface3dRenderer::setSeries(QList<qreal> series) +{ + m_series = series; + + // TODO temp solution + if (!m_surfaceObj) + loadSurfaceObj(); + + if (m_cachedSmoothSurface) + m_surfaceObj->setUpSmoothData(series, m_segmentXCount, m_segmentZCount, m_yRange, true); + else + m_surfaceObj->setUpData(series, m_segmentXCount, m_segmentZCount, m_yRange, true); + + updateSelectionTexture(); +} + +void Surface3dRenderer::calculateSceneScalingFactors() +{ + // Calculate scene scaling and translation factors + // m_rowWidth = ((m_columnCount + 1) * m_barSpacing.width()) / 2.0f; + // m_columnDepth = ((m_rowCount + 1) * m_barSpacing.height()) / 2.0f; + // m_maxDimension = qMax(m_rowWidth, m_columnDepth); + // m_scaleFactor = qMin((m_columnCount * (m_maxDimension / m_maxSceneSize)), + // (m_rowCount * (m_maxDimension / m_maxSceneSize))); + // m_scaleX = m_barThickness.width() / m_scaleFactor; + // m_scaleZ = m_barThickness.height() / m_scaleFactor; + + m_xLength = m_segmentXCount; + m_zLength = m_segmentZCount; + m_maxDimension = qMax(m_xLength, m_zLength); + m_scaleFactor = qMin((m_segmentXCount * (m_maxDimension / m_maxSceneSize)), + (m_segmentZCount * (m_maxDimension / m_maxSceneSize))); + m_scaleX = 1.0f / m_scaleFactor; // TODO: correspondance to m_barThickness + m_scaleZ = 1.0f / m_scaleFactor; // TODO: correspondance to m_barThickness + + //qDebug() << "m_scaleX" << m_scaleX << "m_scaleFactor" << m_scaleFactor; + //qDebug() << "m_scaleZ" << m_scaleZ << "m_scaleFactor" << m_scaleFactor; + //qDebug() << "m_rowWidth:" << m_rowWidth << "m_columnDepth:" << m_columnDepth << "m_maxDimension:" << m_maxDimension; +} + +void Surface3dRenderer::updateSmoothStatus(bool enable) +{ + m_cachedSmoothSurface = enable; + + if (!m_surfaceObj) + return; + + if (m_cachedSmoothSurface) + m_surfaceObj->setUpSmoothData(m_series, m_segmentXCount, m_segmentZCount, m_yRange, true); + else + m_surfaceObj->setUpData(m_series, m_segmentXCount, m_segmentZCount, m_yRange, true); + + initSurfaceShaders(); +} + +void Surface3dRenderer::updateSurfaceGridStatus(bool enable) +{ + m_cachedSurfaceGridOn = enable; +} + +void Surface3dRenderer::loadBackgroundMesh() +{ + if (!m_isInitialized) + return; + + if (m_backgroundObj) + delete m_backgroundObj; + if (m_hasNegativeValues) + m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/negativeBackground")); + else + m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background")); + m_backgroundObj->load(); +} + +void Surface3dRenderer::loadSurfaceObj() +{ + if (!m_isInitialized) + return; + + if (m_surfaceObj) + delete m_surfaceObj; + m_surfaceObj = new SurfaceObject(); + //m_surfaceObj->setUpData(); +} + +void Surface3dRenderer::loadGridLineMesh() +{ + if (m_gridLineObj) + delete m_gridLineObj; + m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar")); + m_gridLineObj->load(); +} + +const QSize Surface3dRenderer::size() +{ + return m_boundingRect.size(); +} + +const QRect Surface3dRenderer::boundingRect() +{ + return m_boundingRect; +} + +void Surface3dRenderer::setBoundingRect(const QRect boundingRect) +{ + m_boundingRect = boundingRect; + handleResize(); +} + +void Surface3dRenderer::setWidth(const int width) +{ + m_boundingRect.setWidth(width); + handleResize(); +} + +int Surface3dRenderer::width() +{ + return m_boundingRect.width(); +} + +void Surface3dRenderer::setHeight(const int height) +{ + m_boundingRect.setHeight(height); + handleResize(); +} + +int Surface3dRenderer::height() +{ + return m_boundingRect.height(); +} + +void Surface3dRenderer::setX(const int x) +{ + m_boundingRect.setX(x); +} + +int Surface3dRenderer::x() +{ + return m_boundingRect.x(); +} + +void Surface3dRenderer::setY(const int y) +{ + m_boundingRect.setY(y); +} + +int Surface3dRenderer::y() +{ + return m_boundingRect.y(); +} + +void Surface3dRenderer::handleResize() +{ + if (!m_isInitialized) + return; + + qDebug() << "Surface3dRenderer::handleResize " << width() << "x" << height(); + + m_mainViewPort = QRect(0, 0, width(), height()); + m_sliceViewPort = QRect(0, 0, width(), height()); + +#if !defined(QT_OPENGL_ES_2) + // Re-init depth buffer + updateDepthBuffer(); +#endif +} + +#if !defined(QT_OPENGL_ES_2) +void Surface3dRenderer::updateDepthBuffer() +{ + if (m_depthTexture) { + m_textureHelper->deleteTexture(&m_depthTexture); + m_depthTexture = 0; + } + + // TODO: bars uses some m_cachedShadowQuality + if (m_shadowQuality > QDataVis::ShadowNone && !m_mainViewPort.size().isEmpty()) { + m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(), + m_depthFrameBuffer, + m_shadowQuality); + if (!m_depthTexture) { + qDebug() << "Failed to create m_depthTexture"; + // switch (m_shadowQuality) { + // case ShadowHigh: + // qWarning("Creating high quality shadows failed. Changing to medium quality."); + // (void)setShadowQuality(ShadowMedium); + // break; + // case ShadowMedium: + // qWarning("Creating medium quality shadows failed. Changing to low quality."); + // (void)setShadowQuality(ShadowLow); + // break; + // case ShadowLow: + // qWarning("Creating low quality shadows failed. Switching shadows off."); + // (void)setShadowQuality(ShadowNone); + // break; + // default: + // // You'll never get here + // break; + // } + } + } +} +#endif + +void Surface3dRenderer::initBackgroundShaders(const QString &vertexShader, + const QString &fragmentShader) +{ + if (m_backgroundShader) + delete m_backgroundShader; + m_backgroundShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_backgroundShader->initialize(); +} + +void Surface3dRenderer::initSelectionShaders() +{ + if (m_selectionShader) + delete m_selectionShader; + m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexLabel"), + QStringLiteral(":/shaders/fragmentLabel")); + m_selectionShader->initialize(); +} + +void Surface3dRenderer::initSurfaceShaders() +{ + if (m_surfaceShader) + delete m_surfaceShader; + if (m_cachedSmoothSurface) { + m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurface"), + QStringLiteral(":/shaders/fragmentSurface")); + } else { + m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"), + QStringLiteral(":/shaders/fragmentSurfaceFlat")); + } + m_surfaceShader->initialize(); + + if (m_surfaceGridShader) + delete m_surfaceGridShader; + m_surfaceGridShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceGrid"), + QStringLiteral(":/shaders/fragmentSurfaceGrid")); + m_surfaceGridShader->initialize(); +} + +QT_DATAVIS3D_END_NAMESPACE + + +//p = 90; +//qDebug() << "rgba = " << bits[p + 0] << ", " << bits[p + 1] << ", " << +// bits[p + 2] << ", " << bits[p + 3]; +//p += 4; +//qDebug() << "rgba = " << bits[p + 0] << ", " << bits[p + 1] << ", " << +// bits[p + 2] << ", " << bits[p + 3]; +//p += 4; +//qDebug() << "rgba = " << bits[p + 0] << ", " << bits[p + 1] << ", " << +// bits[p + 2] << ", " << bits[p + 3]; +//p += 4; +//qDebug() << "rgba = " << bits[p + 0] << ", " << bits[p + 1] << ", " << +// bits[p + 2] << ", " << bits[p + 3]; +//p += 4; +//qDebug() << "rgba = " << bits[p + 0] << ", " << bits[p + 1] << ", " << +// bits[p + 2] << ", " << bits[p + 3]; +//p += 4; + diff --git a/src/datavis3d/engine/surface3drenderer_p.h b/src/datavis3d/engine/surface3drenderer_p.h new file mode 100644 index 00000000..f2fb120a --- /dev/null +++ b/src/datavis3d/engine/surface3drenderer_p.h @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 SURFACE3DRENDERER_P_H +#define SURFACE3DRENDERER_P_H + +#include <QtCore/QSize> +#include <QtCore/QObject> +#include <QtGui/QOpenGLFunctions> +#include <QtGui/QFont> +#include <QLinearGradient> +#include <QWindow> + +#include "datavis3dglobal_p.h" +#include "surface3dcontroller_p.h" + +class QOpenGLShaderProgram; + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class ShaderHelper; +class ObjectHelper; +class SurfaceObject; +class TextureHelper; +class Theme; +class Drawer; +class CameraHelper; + +class QT_DATAVIS3D_EXPORT Surface3dRenderer : public QObject, protected QOpenGLFunctions +{ + Q_OBJECT + +public: + enum MousePressType { + MouseNone = 0, + MouseOnScene, + MouseOnOverview, + MouseOnZoom, + MouseRotating, + MouseOnPinch + }; + + Surface3dController *m_controller; + + // Interaction related parameters // TODO: Moved to controller + MousePressType m_mousePressed; + QPoint m_mousePos; + QDataVis::SelectionMode m_selectionMode; + + // Visual parameters + QRect m_boundingRect; + Theme m_cachedTheme; + QDataVis::LabelTransparency m_labelTransparency; + QFont m_font; + bool m_isGridEnabled; + bool m_isBackgroundEnabled; + QDataVis::ShadowQuality m_shadowQuality; + bool m_hasNegativeValues; + +private: + // Data parameters + QList<qreal> m_series; // TODO: TEMP + GLint m_segmentYCount; + GLfloat m_segmentYStep; + GLint m_segmentXCount; + GLint m_segmentZCount; + + // Internal attributes purely related to how the scene is drawn with GL. + QRect m_mainViewPort; + QRect m_sliceViewPort; + ShaderHelper *m_backgroundShader; + ShaderHelper *m_surfaceShader; + ShaderHelper *m_surfaceGridShader; + ShaderHelper *m_selectionShader; + TextureHelper *m_textureHelper; + bool m_isInitialized; + GLfloat m_yRange; // m_heightNormalizer + GLfloat m_yAdjustment; + GLfloat m_xLength; + GLfloat m_zLength; + GLfloat m_maxDimension; + GLfloat m_scaleFactor; + GLfloat m_scaleX; + GLfloat m_scaleZ; + GLfloat m_maxSceneSize; + ObjectHelper *m_backgroundObj; + ObjectHelper *m_gridLineObj; + SurfaceObject *m_surfaceObj; + GLuint m_depthTexture; + GLuint m_depthFrameBuffer; + GLuint m_selectionFrameBuffer; + GLuint m_selectionDepthBuffer; + GLuint m_gradientTexture; + GLuint m_selectionTexture; + GLuint m_selectionResultTexture; + GLfloat m_shadowQualityToShader; + bool m_querySelection; + bool m_cachedSmoothSurface; + bool m_cachedSurfaceGridOn; + + Drawer *m_drawer; + +public: + explicit Surface3dRenderer(Surface3dController *controller); + ~Surface3dRenderer(); + + void initializeOpenGL(); + void render(CameraHelper *camera, const GLuint defaultFboHandle = 0); + + // TODO: Not thread-safe, needs rethinking how axes create labels + Drawer *drawer() { return m_drawer; } + +public slots: + void updateTheme(Theme theme); + void updateSmoothStatus(bool enable); + void updateSurfaceGridStatus(bool enable); + void updateSurfaceGradient(); + void updateSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum = 0.0f); + + void getSelection(); + +public: + // Size + const QSize size(); + const QRect boundingRect(); + void setBoundingRect(const QRect boundingRect); + void setWidth(const int width); + int width(); + void setHeight(const int height); + int height(); + void setX(const int x); + int x(); + void setY(const int y); + int y(); + + void handleResize(); + +#if !defined(QT_OPENGL_ES_2) + void updateDepthBuffer(); +#endif + void loadBackgroundMesh(); + void loadGridLineMesh(); + void loadSurfaceObj(); + + // TODO: temp + void setXZStuff(GLint segmentXCount, GLint segmentZCount); + void setSeries(QList<qreal> series); + +private: + void drawScene(CameraHelper *camera, const GLuint defaultFboHandle); + void calculateSceneScalingFactors(); + void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); + void initSelectionShaders(); + void initSurfaceShaders(); + void updateSelectionTexture(); + void idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a); + void fillIdCorner(uchar *p, uchar r, uchar g, uchar b, uchar a, int stride); + + Q_DISABLE_COPY(Surface3dRenderer) +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // SURFACE3DRENDERER_P_H diff --git a/src/datavis3d/engine/theme.cpp b/src/datavis3d/engine/theme.cpp index 4a258b67..7b2cb210 100644 --- a/src/datavis3d/engine/theme.cpp +++ b/src/datavis3d/engine/theme.cpp @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -46,7 +23,7 @@ #include <stdio.h> #endif -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE Theme::Theme() : m_baseColor(QColor(Qt::gray)), @@ -60,21 +37,32 @@ Theme::Theme() m_highlightBarColor(QColor(Qt::red)), m_highlightRowColor(QColor(Qt::darkRed)), m_highlightColumnColor(QColor(Qt::darkMagenta)), + m_surfaceGradient(QLinearGradient(1, 100, 0, 0)), m_lightStrength(4.0f), m_ambientStrength(0.3f), m_highlightLightStrength(8.0f), m_uniformColor(true) { + // Default values for surface gradient + m_surfaceGradient.setColorAt(0.0, Qt::green); + m_surfaceGradient.setColorAt(0.5, Qt::yellow); + m_surfaceGradient.setColorAt(1.0, Qt::red); } Theme::~Theme() { } -void Theme::useTheme(ColorTheme theme) +QDataVis::ColorTheme Theme::colorTheme() +{ + return m_colorTheme; +} + +void Theme::useColorTheme(QDataVis::ColorTheme colorTheme) { - switch (theme) { - case ThemeSystem: { + m_colorTheme = colorTheme; + switch (colorTheme) { + case QDataVis::ThemeSystem: { #ifdef Q_OS_WIN DWORD colorHighlight; colorHighlight = GetSysColor(COLOR_HIGHLIGHT); @@ -157,7 +145,7 @@ void Theme::useTheme(ColorTheme theme) qDebug("ThemeSystem"); break; } - case ThemeBlueCerulean: { + case QDataVis::ThemeBlueCerulean: { m_baseColor = QColor(QRgb(0xc7e85b)); m_heightColor = QColor(QRgb(0xee7392)); m_depthColor = QColor(QRgb(0x1cb54f)); @@ -176,7 +164,7 @@ void Theme::useTheme(ColorTheme theme) qDebug("ThemeBlueCerulean"); break; } - case ThemeBlueIcy: { + case QDataVis::ThemeBlueIcy: { m_baseColor = QRgb(0x3daeda); m_heightColor = QRgb(0x2fa3b4); m_depthColor = QColor(QRgb(0x2685bf)); @@ -195,7 +183,7 @@ void Theme::useTheme(ColorTheme theme) qDebug("ThemeBlueIcy"); break; } - case ThemeBlueNcs: { + case QDataVis::ThemeBlueNcs: { m_baseColor = QColor(QRgb(0x1db0da)); m_heightColor = QColor(QRgb(0x398ca3)); m_depthColor = QColor(QRgb(0x1341a6)); @@ -214,7 +202,7 @@ void Theme::useTheme(ColorTheme theme) qDebug("ThemeBlueNcs"); break; } - case ThemeBrownSand: { + case QDataVis::ThemeBrownSand: { m_baseColor = QColor(QRgb(0xb39b72)); m_heightColor = QColor(QRgb(0x494345)); m_depthColor = QColor(QRgb(0xb3b376)); @@ -233,7 +221,7 @@ void Theme::useTheme(ColorTheme theme) qDebug("ThemeBrownSand"); break; } - case ThemeDark: { + case QDataVis::ThemeDark: { m_baseColor = QColor(QRgb(0x38ad6b)); // charts: series color 1 m_heightColor = QColor(QRgb(0xbf593e)); // charts: series color 5 m_depthColor = QColor(QRgb(0x3c84a7)); // charts: series color 2 @@ -252,7 +240,7 @@ void Theme::useTheme(ColorTheme theme) qDebug("ThemeDark"); break; } - case ThemeHighContrast: { + case QDataVis::ThemeHighContrast: { m_baseColor = QColor(QRgb(0x202020)); m_heightColor = QColor(QRgb(0xff4a41)); m_depthColor = QColor(QRgb(0x596a74)); @@ -271,7 +259,7 @@ void Theme::useTheme(ColorTheme theme) qDebug("ThemeHighContrast"); break; } - case ThemeLight: { + case QDataVis::ThemeLight: { m_baseColor = QColor(QRgb(0x209fdf)); m_heightColor = QColor(QRgb(0xbf593e)); m_depthColor = QColor(QRgb(0x99ca53)); @@ -295,4 +283,25 @@ void Theme::useTheme(ColorTheme theme) } } -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +void Theme::setFromTheme(Theme &theme) +{ + m_colorTheme = theme.m_colorTheme; + m_baseColor = theme.m_baseColor; + m_heightColor = theme.m_heightColor; + m_depthColor = theme.m_depthColor; + m_backgroundColor = theme.m_backgroundColor; + m_windowColor = theme.m_windowColor; + m_textColor = theme.m_textColor; + m_textBackgroundColor = theme.m_textBackgroundColor; + m_gridLine = theme.m_gridLine; + m_highlightBarColor = theme.m_highlightBarColor; + m_highlightRowColor = theme.m_highlightRowColor; + m_highlightColumnColor = theme.m_highlightColumnColor; + m_surfaceGradient = theme.m_surfaceGradient; + m_lightStrength = theme.m_lightStrength; + m_ambientStrength = theme.m_ambientStrength; + m_highlightLightStrength = theme.m_highlightLightStrength; + m_uniformColor = theme.m_uniformColor; +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/theme_p.h b/src/datavis3d/engine/theme_p.h index 234d4709..31c47941 100644 --- a/src/datavis3d/engine/theme_p.h +++ b/src/datavis3d/engine/theme_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,13 +29,13 @@ #ifndef THEME_P_H #define THEME_P_H -#include "QtDataVis3D/qdatavis3dglobal.h" -#include "QtDataVis3D/qdatavis3namespace.h" +#include "datavis3dglobal_p.h" #include "q3dbars.h" +#include <QLinearGradient> class QColor; -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE class Theme { @@ -66,14 +43,21 @@ public: explicit Theme(); ~Theme(); - void useTheme(ColorTheme theme); + void useColorTheme(QDataVis::ColorTheme theme); + QDataVis::ColorTheme colorTheme(); + void setFromTheme(Theme &theme); private: - friend class Bars3dShared; - friend class Q3DMaps; - friend class Q3DMapsPrivate; + friend class Abstract3DController; + friend class Abstract3DRenderer; + friend class Bars3dRenderer; + friend class Maps3DController; + friend class Surface3dRenderer; + friend class Surface3dController; + friend class Scatter3DRenderer; friend class Drawer; + QDataVis::ColorTheme m_colorTheme; QColor m_baseColor; QColor m_heightColor; QColor m_depthColor; @@ -85,12 +69,13 @@ private: QColor m_highlightBarColor; QColor m_highlightRowColor; QColor m_highlightColumnColor; + QLinearGradient m_surfaceGradient; float m_lightStrength; float m_ambientStrength; float m_highlightLightStrength; bool m_uniformColor; }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/global/datavis3dglobal_p.h b/src/datavis3d/global/datavis3dglobal_p.h new file mode 100644 index 00000000..d556c5e1 --- /dev/null +++ b/src/datavis3d/global/datavis3dglobal_p.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 DATAVIS3DGLOBAL_P_H +#define DATAVIS3DGLOBAL_P_H + +#include "qdatavis3dglobal.h" +#include "qdatavis3denums.h" +#include <QOpenGLFunctions> +#include <QVector3D> +#include <QDebug> + +//#define ROTATE_ZOOM_SELECTION + +QT_DATAVIS3D_BEGIN_NAMESPACE + +// Constants used in several files +// Compensation for z position; move all objects to positive z, as shader can't handle negative values correctly +const GLfloat zComp = 10.0f; +// Default light position. To have shadows working correctly, light should be as far as camera, or a bit further +// y position is added to the minimum height (or can be thought to be that much above or below the camera) +const QVector3D defaultLightPos = QVector3D(0.0f, 0.5f, zComp); +const GLfloat defaultRatio = 1.0f / 1.6f; // default aspect ratio 16:10 + +QT_DATAVIS3D_END_NAMESPACE + +#endif // DATAVIS3DGLOBAL_P_H diff --git a/src/datavis3d/global/global.pri b/src/datavis3d/global/global.pri index 56cb9f8f..7292bbd6 100644 --- a/src/datavis3d/global/global.pri +++ b/src/datavis3d/global/global.pri @@ -1,5 +1,4 @@ -INCLUDEPATH += $$PWD -VPATH += $$PWD HEADERS += \ - global/qdatavis3dglobal.h \ - global/qdatavis3namespace.h + $$PWD/qdatavis3dglobal.h \ + $$PWD/qdatavis3denums.h \ + $$PWD/datavis3dglobal_p.h diff --git a/src/datavis3d/global/qdatavis3denums.h b/src/datavis3d/global/qdatavis3denums.h new file mode 100644 index 00000000..a6384508 --- /dev/null +++ b/src/datavis3d/global/qdatavis3denums.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QDATAVIS3DENUMS_H +#define QDATAVIS3DENUMS_H + +#include <QtDataVis3D/qdatavis3dglobal.h> +#include <QObject> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class QT_DATAVIS3D_EXPORT QDataVis : public QObject +{ + Q_OBJECT + Q_ENUMS(MeshStyle) + Q_ENUMS(CameraPreset) + Q_ENUMS(ColorTheme) + Q_ENUMS(SelectionMode) + Q_ENUMS(ShadowQuality) + Q_ENUMS(LabelTransparency) + +public: + + enum MeshStyle { + Bars = 0, + Pyramids, + Cones, + Cylinders, + BevelBars, + Spheres, + Dots + }; + + enum CameraPreset { + NoPreset = -1, + PresetFrontLow = 0, + PresetFront, + PresetFrontHigh, + PresetLeftLow, + PresetLeft, + PresetLeftHigh, + PresetRightLow, + PresetRight, + PresetRightHigh, + PresetBehindLow, + PresetBehind, + PresetBehindHigh, + PresetIsometricLeft, + PresetIsometricLeftHigh, + PresetIsometricRight, + PresetIsometricRightHigh, + PresetDirectlyAbove, + PresetDirectlyAboveCW45, + PresetDirectlyAboveCCW45, + PresetFrontBelow, // These work only for graphs including negative values. + PresetLeftBelow, // They act as Preset...Low for positive-only values. + PresetRightBelow, + PresetBehindBelow, + PresetDirectlyBelow + }; + + enum ColorTheme { + ThemeDefault = -1, + ThemeSystem = 0, + ThemeBlueCerulean, + ThemeBlueIcy, + ThemeBlueNcs, + ThemeBrownSand, + ThemeDark, + ThemeHighContrast, + ThemeLight + }; + + enum SelectionMode { + ModeNone = 0, + ModeItem, + ModeItemAndRow, // From here onwards used for Q3DBars only + ModeItemAndColumn, + ModeItemRowAndColumn, + ModeZoomRow, + ModeZoomColumn + }; + + enum ShadowQuality { + ShadowNone = 0, + ShadowLow = 1, + ShadowMedium = 3, + ShadowHigh = 5 + }; + + enum LabelTransparency { + TransparencyNone = 0, // Full solid, using colors from theme + TransparencyFromTheme, // Use colors and transparencies from theme + TransparencyNoBackground // Draw just text on transparent background + }; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/global/qdatavis3dglobal.h b/src/datavis3d/global/qdatavis3dglobal.h index 7dad9374..5e2e88b1 100644 --- a/src/datavis3d/global/qdatavis3dglobal.h +++ b/src/datavis3d/global/qdatavis3dglobal.h @@ -4,17 +4,15 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of QtDataVis3D. +** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. ** ** If you have questions regarding the use of this file, please use ** contact form at http://qt.digia.com -** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -23,68 +21,47 @@ #include <qglobal.h> -//#define ROTATE_ZOOM_SELECTION - -#define QTENTERPRISE_DATAVIS3D_VERSION_STR "0.0.1" +#define QT_DATAVIS3D_VERSION_STR "0.0.1" /* - QTENTERPRISE_DATAVIS3D_VERSION is (major << 16) + (minor << 8) + patch. + QT_DATAVIS3D_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QTENTERPRISE_DATAVIS3D_VERSION 0x000001 +#define QT_DATAVIS3D_VERSION 0x000001 /* - can be used like #if (QTENTERPRISE_DATAVIS3D_VERSION >= QTENTERPRISE_DATAVIS3D_VERSION_CHECK(1, 1, 0)) + can be used like #if (QT_DATAVIS3D_VERSION >= QT_DATAVIS3D_VERSION_CHECK(1, 1, 0)) */ -#define QTENTERPRISE_DATAVIS3D_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) +#define QT_DATAVIS3D_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) -#if defined(QTENTERPRISE_DATAVIS3D_LIBRARY) -# define QTENTERPRISE_DATAVIS3D_EXPORT Q_DECL_EXPORT +#if defined(QT_DATAVIS3D_LIBRARY) +# define QT_DATAVIS3D_EXPORT Q_DECL_EXPORT #else -# define QTENTERPRISE_DATAVIS3D_EXPORT Q_DECL_IMPORT +# define QT_DATAVIS3D_EXPORT Q_DECL_IMPORT #endif -#if defined(BUILD_PRIVATE_UNIT_TESTS) && defined(QTENTERPRISE_DATAVIS3D_LIBRARY) -# define QTENTERPRISE_DATAVIS3D_AUTOTEST_EXPORT Q_DECL_EXPORT -#elif defined(BUILD_PRIVATE_UNIT_TESTS) && !defined(QTENTERPRISE_DATAVIS3D_LIBRARY) -# define QTENTERPRISE_DATAVIS3D_AUTOTEST_EXPORT Q_DECL_IMPORT +#if defined(BUILD_PRIVATE_UNIT_TESTS) && defined(QT_DATAVIS3D_LIBRARY) +# define QT_DATAVIS3D_AUTOTEST_EXPORT Q_DECL_EXPORT +#elif defined(BUILD_PRIVATE_UNIT_TESTS) && !defined(QT_DATAVIS3D_LIBRARY) +# define QT_DATAVIS3D_AUTOTEST_EXPORT Q_DECL_IMPORT #else -# define QTENTERPRISE_DATAVIS3D_AUTOTEST_EXPORT +# define QT_DATAVIS3D_AUTOTEST_EXPORT #endif -#ifdef QTENTERPRISE_DATAVIS3D_STATICLIB -# undef QTENTERPRISE_DATAVIS3D_EXPORT -# undef QTENTERPRISE_DATAVIS3D_AUTOTEST_EXPORT -# define QTENTERPRISE_DATAVIS3D_EXPORT -# define QTENTERPRISE_DATAVIS3D_AUTOTEST_EXPORT +#ifdef QT_DATAVIS3D_STATICLIB +# undef QT_DATAVIS3D_EXPORT +# undef QT_DATAVIS3D_AUTOTEST_EXPORT +# define QT_DATAVIS3D_EXPORT +# define QT_DATAVIS3D_AUTOTEST_EXPORT #endif -#define QTENTERPRISE_DATAVIS3D_NAMESPACE QtDataVis3D +#define QT_DATAVIS3D_NAMESPACE QtDataVis3D -#ifdef QTENTERPRISE_DATAVIS3D_NAMESPACE -# define QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE namespace QTENTERPRISE_DATAVIS3D_NAMESPACE { -# define QTENTERPRISE_DATAVIS3D_END_NAMESPACE } -# define QTENTERPRISE_DATAVIS3D_USE_NAMESPACE using namespace QTENTERPRISE_DATAVIS3D_NAMESPACE; +#ifdef QT_DATAVIS3D_NAMESPACE +# define QT_DATAVIS3D_BEGIN_NAMESPACE namespace QT_DATAVIS3D_NAMESPACE { +# define QT_DATAVIS3D_END_NAMESPACE } +# define QT_DATAVIS3D_USE_NAMESPACE using namespace QT_DATAVIS3D_NAMESPACE; #else -# define QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE -# define QTENTERPRISE_DATAVIS3D_END_NAMESPACE -# define QTENTERPRISE_DATAVIS3D_USE_NAMESPACE -#endif - -#if defined(DEVELOPMENT_BUILD) && !defined(QT_NO_DEBUG) -#include <stdarg.h> -#include <QDebug> - -#define CHART_DEBUG chartDebug(3,__LINE__,__FILE__,__FUNCTION__) - -static inline QDebug chartDebug(int numargs,...) -{ - va_list valist; - va_start(valist, numargs); - //for( int i = 0 ; i < numargs; i++ ) - int line = va_arg(valist, int); - char *file = va_arg(valist, char *); - char *function = va_arg(valist, char *); - va_end(valist); - return qDebug() << QString().append(function).append("(").append(file).append(":%1)").arg(line); -} +# define QT_DATAVIS3D_BEGIN_NAMESPACE +# define QT_DATAVIS3D_END_NAMESPACE +# define QT_DATAVIS3D_USE_NAMESPACE #endif #endif // QVIS3DGLOBAL_H diff --git a/src/datavis3d/global/qdatavis3namespace.h b/src/datavis3d/global/qdatavis3namespace.h deleted file mode 100644 index e36cc02a..00000000 --- a/src/datavis3d/global/qdatavis3namespace.h +++ /dev/null @@ -1,147 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QVIS3DNAMESPACE_H -#define QVIS3DNAMESPACE_H - -#include "qdatavis3dglobal.h" -#include <QOpenGLFunctions> -#include <QVector3D> - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -// Constants used in several files -const GLfloat m_pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679f; -// Compensation for z position; move all objects to positive z, as shader can't handle negative values correctly -const GLfloat zComp = 10.0f; -// Default light position. To have shadows working correctly, light should be as far as camera, or a bit further -// y position is added to the minimum height (or can be thought to be that much above or below the camera) -const QVector3D defaultLightPos = QVector3D(0.0f, 0.5f, zComp); -const GLfloat defaultRatio = 1.0f / 1.6f; // default aspect ratio 16:10 - -// Enums used in several files -enum BarStyle { - Bars = 0, - Pyramids, - Cones, - Cylinders, - BevelBars, - Spheres -}; - -enum CameraPreset { - PresetFrontLow = 0, - PresetFront, - PresetFrontHigh, - PresetLeftLow, - PresetLeft, - PresetLeftHigh, - PresetRightLow, - PresetRight, - PresetRightHigh, - PresetBehindLow, - PresetBehind, - PresetBehindHigh, - PresetIsometricLeft, - PresetIsometricLeftHigh, - PresetIsometricRight, - PresetIsometricRightHigh, - PresetDirectlyAbove, - PresetDirectlyAboveCW45, - PresetDirectlyAboveCCW45, - PresetFrontBelow, // These work only for graphs including negative values. - PresetLeftBelow, // They act as Preset...Low for positive-only values. - PresetRightBelow, - PresetBehindBelow, - PresetDirectlyBelow -}; - -enum ColorTheme { - ThemeSystem = 0, - ThemeBlueCerulean, - ThemeBlueIcy, - ThemeBlueNcs, - ThemeBrownSand, - ThemeDark, - ThemeHighContrast, - ThemeLight -}; - -// TODO: Should this be moved to Q3DBarsPrivate? Not for use via API directly? -enum LabelPosition { - LabelBelow = 0, - LabelLow, - LabelMid, - LabelHigh, - LabelOver, - LabelBottom, // Absolute positions from here onward, used for axes (QDataItem is ignored) - LabelTop, - LabelLeft, - LabelRight -}; - -// TODO: Will these be used from other vis types than Q3DBars? -enum SelectionMode { - ModeNone = 0, - ModeBar, - ModeBarAndRow, - ModeBarAndColumn, - ModeBarRowAndColumn, - ModeZoomRow, - ModeZoomColumn -}; - -enum ShadowQuality { - ShadowNone = 0, - ShadowLow = 1, - ShadowMedium = 3, - ShadowHigh = 5 -}; - -enum LabelTransparency { - TransparencyNone = 0, // Full solid, using colors from theme - TransparencyFromTheme, // Use colors and transparencies from theme - TransparencyNoBackground // Draw just text on transparent background -}; - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/global/qtdatavis3dnamespace.qdoc b/src/datavis3d/global/qtdatavis3dnamespace.qdoc new file mode 100644 index 00000000..2a1f6fae --- /dev/null +++ b/src/datavis3d/global/qtdatavis3dnamespace.qdoc @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +/*! + \namespace QtDataVis3D + \inmodule QtDataVis3D + \target QtDataVis3D Namespace + + \brief The QtDataVis3D namespace contains miscellaneous identifiers + used throughout the QtDataVis3D library. +*/ + +/*! + \enum QtDataVis3D::BarStyle + + Predefined bar types. + + \value Bars + Basic cubic bar. + \value Pyramids + Four -sided pyramid. + \value Cones + Basic cone. + \value Cylinders + Basic cylinder. + \value BevelBars + Slilghtly beveled (rounded) cubic bar. + \value Spheres + Sphere. Not usable in Q3DBars. +*/ + +/*! + \enum QtDataVis3D::CameraPreset + + Predefined positions for camera. + + \value PresetFrontLow + \value PresetFront + \value PresetFrontHigh + \value PresetLeftLow + \value PresetLeft + \value PresetLeftHigh + \value PresetRightLow + \value PresetRight + \value PresetRightHigh + \value PresetBehindLow + \value PresetBehind + \value PresetBehindHigh + \value PresetIsometricLeft + \value PresetIsometricLeftHigh + \value PresetIsometricRight + \value PresetIsometricRightHigh + \value PresetDirectlyAbove + \value PresetDirectlyAboveCW45 + \value PresetDirectlyAboveCCW45 + \value PresetFrontBelow + From PresetFrontBelow onward these only work for graphs including negative values. + They act as Preset...Low for positive-only values. + \value PresetLeftBelow + \value PresetRightBelow + \value PresetBehindBelow + \value PresetDirectlyBelow + Acts as PresetFrontLow for positive -only bars. +*/ + +/*! + \enum QtDataVis3D::ColorTheme + + Predefined color themes. + + \value ThemeSystem + \value ThemeBlueCerulean + \value ThemeBlueIcy + \value ThemeBlueNcs + \value ThemeBrownSand + \value ThemeDark + \value ThemeHighContrast + \value ThemeLight +*/ + +/*! + \enum QtDataVis3D::LabelPosition + + Predefined positions for labels. + + \value LabelBelow + \value LabelLow + \value LabelMid + \value LabelHigh + \value LabelOver + \value LabelBottom + \value LabelTop + \value LabelLeft + \value LabelRight +*/ + +/*! + \enum QtDataVis3D::SelectionMode + + Bar selection modes. + + \value ModeNone + Selection mode disabled. + \value ModeBar + Selection selects a single bar. + \value ModeBarAndRow + Selection selects a single bar and highlights the row it is on. + \value ModeBarAndColumn + Selection selects a single bar and highlights the column it is on. + \value ModeBarRowAndColumn + Selection selects a single bar and highlights the row and the column it is on. + \value ModeZoomRow + Selection selects a single bar and displays the row it is on in a separate view. The + original view is shrunk into upper left corner. Original view is restored by clicking + on it. + \value ModeZoomColumn + Selection selects a single bar and displays the column it is on in a separate view. The + original view is shrunk into upper left corner. Original view is restored by clicking + on it. +*/ + +/*! + \enum QtDataVis3D::ShadowQuality + + Quality of shadows. + + \value ShadowNone + Shadows are disabled. + \value ShadowLow + Shadows are rendered in low quality. + \value ShadowMedium + Shadows are rendered in medium quality. + \value ShadowHigh + Shadows are rendered in high quality. +*/ + +/*! + \enum QtDataVis3D::LabelTransparency + + Label transparencies. + + \value TransparencyNone + Full solid, using colors from theme. + \value TransparencyFromTheme + Use colors and transparencies from theme. + \value TransparencyNoBackground + Draw just text on transparent background. +*/ diff --git a/src/datavis3d/utils/abstractobjecthelper.cpp b/src/datavis3d/utils/abstractobjecthelper.cpp new file mode 100644 index 00000000..d54a50c7 --- /dev/null +++ b/src/datavis3d/utils/abstractobjecthelper.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "abstractobjecthelper_p.h" + +#include <QDebug> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +AbstractObjectHelper::AbstractObjectHelper() + : m_vertexbuffer(0), + m_normalbuffer(0), + m_uvbuffer(0), + m_elementbuffer(0), + m_indexCount(0), + m_meshDataLoaded(false) +{ +} + +AbstractObjectHelper::~AbstractObjectHelper() +{ + glDeleteBuffers(1, &m_vertexbuffer); + glDeleteBuffers(1, &m_uvbuffer); + glDeleteBuffers(1, &m_normalbuffer); + glDeleteBuffers(1, &m_elementbuffer); +} + +GLuint AbstractObjectHelper::vertexBuf() +{ + if (!m_meshDataLoaded) + qFatal("No loaded object"); + return m_vertexbuffer; +} + +GLuint AbstractObjectHelper::normalBuf() +{ + if (!m_meshDataLoaded) + qFatal("No loaded object"); + return m_normalbuffer; +} + +GLuint AbstractObjectHelper::uvBuf() +{ + if (!m_meshDataLoaded) + qFatal("No loaded object"); + return m_uvbuffer; +} + +GLuint AbstractObjectHelper::elementBuf() +{ + if (!m_meshDataLoaded) + qFatal("No loaded object"); + return m_elementbuffer; +} + +GLuint AbstractObjectHelper::indexCount() +{ + return m_indexCount; +} + +GLuint AbstractObjectHelper::indicesType() +{ + return m_indicesType; +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/utils/abstractobjecthelper_p.h b/src/datavis3d/utils/abstractobjecthelper_p.h new file mode 100644 index 00000000..a4d701fa --- /dev/null +++ b/src/datavis3d/utils/abstractobjecthelper_p.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 ABSTRACTOBJECTHELPER_H +#define ABSTRACTOBJECTHELPER_H + +#include "datavis3dglobal_p.h" +#include <QOpenGLFunctions> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class AbstractObjectHelper: protected QOpenGLFunctions +{ +protected: + AbstractObjectHelper(); +public: + ~AbstractObjectHelper(); + + GLuint vertexBuf(); + GLuint normalBuf(); + GLuint uvBuf(); + GLuint elementBuf(); + GLuint indexCount(); + GLuint indicesType(); + +public: + GLuint m_vertexbuffer; + GLuint m_normalbuffer; + GLuint m_uvbuffer; + GLuint m_elementbuffer; + + GLuint m_indexCount; + GLboolean m_meshDataLoaded; + + GLuint m_indicesType; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif // ABSTRACTOBJECTHELPER_H diff --git a/src/datavis3d/utils/camerahelper.cpp b/src/datavis3d/utils/camerahelper.cpp index 4d59132f..5ae91adb 100644 --- a/src/datavis3d/utils/camerahelper.cpp +++ b/src/datavis3d/utils/camerahelper.cpp @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -45,21 +22,26 @@ #include <QMatrix4x4> #include <QVector3D> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -// Initial camera position -QVector3D m_position = QVector3D(0, 0.25, 3); -QVector3D m_target = QVector3D(0, 0, 0); -QVector3D m_up = QVector3D(0, 1, 0); +QT_DATAVIS3D_BEGIN_NAMESPACE -QPoint m_previousMousePos(0, 0); +CameraHelper::CameraHelper(QObject *parent) : + QObject(parent), + m_position(0, 0.25, 3), + m_target(0, 0, 0), + m_up(0, 1, 0), + m_previousMousePos(0,0), + m_xRotation(0), + m_yRotation(0), + m_defaultXRotation(0), + m_defaultYRotation(0), + m_rotationSpeed(100) +{ +} -GLfloat m_xRotation = 0; -GLfloat m_yRotation = 0; -GLfloat m_defaultXRotation = 0; -GLfloat m_defaultYRotation = 0; +CameraHelper::~CameraHelper() +{ +} -GLfloat m_rotationSpeed = 100; // FUNCTIONS void CameraHelper::setRotationSpeed(int speed) @@ -89,10 +71,10 @@ QMatrix4x4 CameraHelper::calculateViewMatrix(const QPoint &mousePos, int zoom, int screenWidth, int screenHeight, bool showUnder) { QMatrix4x4 viewMatrix; - GLint lowerLimit = 0; + GLfloat lowerLimit = 0.0f; if (showUnder) - lowerLimit = -90; + lowerLimit = -90.0f; // Calculate mouse movement since last frame GLfloat mouseMoveX = GLfloat(m_previousMousePos.x() - mousePos.x()) @@ -103,10 +85,10 @@ QMatrix4x4 CameraHelper::calculateViewMatrix(const QPoint &mousePos, int zoom, m_xRotation -= mouseMoveX; m_yRotation -= mouseMoveY; // Reset at 360 in x and limit to 0...90 in y - if (qFabs(m_xRotation) >= 360) - m_xRotation = 0; - if (m_yRotation >= 90) - m_yRotation = 90; + if (qAbs(m_xRotation) >= 360.0f) + m_xRotation = 0.0f; + if (m_yRotation >= 90.0f) + m_yRotation = 90.0f; else if (m_yRotation <= lowerLimit) m_yRotation = lowerLimit; @@ -116,8 +98,8 @@ QMatrix4x4 CameraHelper::calculateViewMatrix(const QPoint &mousePos, int zoom, viewMatrix.translate(m_target.x(), m_target.y(), m_target.z()); // Apply rotations // Handle x and z rotation when y -angle is other than 0 - viewMatrix.rotate(m_xRotation, 0, cos(m_yRotation * m_pi / 180.0f), - sin(m_yRotation * m_pi / 180.0f)); + viewMatrix.rotate(m_xRotation, 0, qCos(qDegreesToRadians(m_yRotation)), + qSin(qDegreesToRadians(m_yRotation))); // y rotation is always "clean" viewMatrix.rotate(m_yRotation, 1.0f, 0.0f, 0.0f); // handle zoom by scaling @@ -126,11 +108,6 @@ QMatrix4x4 CameraHelper::calculateViewMatrix(const QPoint &mousePos, int zoom, viewMatrix.translate(-m_target.x(), -m_target.y(), -m_target.z()); //qDebug() << m_xRotation << m_yRotation; - //qDebug() << "sin(m_yRotation)" << sin(m_yRotation*m_pi/180); - //qDebug() << "asin(m_yRotation)" << asin(m_yRotation*m_pi/180); - //qDebug() << "cos(m_yRotation)" << cos(m_yRotation*m_pi/180); - //qDebug() << "tan(m_yRotation)" << tan(m_yRotation*m_pi/180); - m_previousMousePos = mousePos; return viewMatrix; } @@ -144,18 +121,17 @@ QVector3D CameraHelper::calculateLightPosition(const QVector3D &lightPosition, GLfloat xAngle; GLfloat yAngle; if (!fixedRotation) { - xAngle = m_xRotation * m_pi / 180.0f; - yAngle = m_yRotation * m_pi / 180.0f; + xAngle = qDegreesToRadians(m_xRotation); + yAngle = qDegreesToRadians(m_yRotation); } else { - xAngle = fixedRotation * m_pi / 180.0f; + xAngle = qDegreesToRadians(fixedRotation); yAngle = 0; } GLfloat radius = (radiusFactor + lightPosition.y()); // set radius to match the highest height of the light - GLfloat zPos = radius * cos(xAngle) * cos(yAngle); - GLfloat xPos = radius * sin(xAngle) * cos(yAngle); - GLfloat yPos = (radiusFactor + lightPosition.y()) * sin(yAngle); + GLfloat zPos = radius * qCos(xAngle) * qCos(yAngle); + GLfloat xPos = radius * qSin(xAngle) * qCos(yAngle); + GLfloat yPos = (radiusFactor + lightPosition.y()) * qSin(yAngle); // Keep light in the set position in relation to camera - // TODO: Does not work perfectly yet; Light seems wrong when viewing scene from sides (or isometrically) newLightPosition = QVector3D(-xPos + lightPosition.x(), yPos + lightPosition.y(), zPos + lightPosition.z()); @@ -179,125 +155,125 @@ QPointF CameraHelper::getCameraRotations() return rotations; } -void CameraHelper::setCameraPreset(CameraPreset preset) +void CameraHelper::setCameraPreset(QDataVis::CameraPreset preset) { switch (preset) { - case PresetFrontLow: { + case QDataVis::PresetFrontLow: { qDebug("PresetFrontLow"); CameraHelper::setCameraRotation(QPointF(0.0f, 0.0f)); break; } - case PresetFront: { + case QDataVis::PresetFront: { qDebug("PresetFront"); CameraHelper::setCameraRotation(QPointF(0.0f, 22.5f)); break; } - case PresetFrontHigh: { + case QDataVis::PresetFrontHigh: { qDebug("PresetFrontHigh"); CameraHelper::setCameraRotation(QPointF(0.0f, 45.0f)); break; } - case PresetLeftLow: { + case QDataVis::PresetLeftLow: { qDebug("PresetLeftLow"); CameraHelper::setCameraRotation(QPointF(90.0f, 0.0f)); break; } - case PresetLeft: { + case QDataVis::PresetLeft: { qDebug("PresetLeft"); CameraHelper::setCameraRotation(QPointF(90.0f, 22.5f)); break; } - case PresetLeftHigh: { + case QDataVis::PresetLeftHigh: { qDebug("PresetLeftHigh"); CameraHelper::setCameraRotation(QPointF(90.0f, 45.0f)); break; } - case PresetRightLow: { + case QDataVis::PresetRightLow: { qDebug("PresetRightLow"); CameraHelper::setCameraRotation(QPointF(-90.0f, 0.0f)); break; } - case PresetRight: { + case QDataVis::PresetRight: { qDebug("PresetRight"); CameraHelper::setCameraRotation(QPointF(-90.0f, 22.5f)); break; } - case PresetRightHigh: { + case QDataVis::PresetRightHigh: { qDebug("PresetRightHigh"); CameraHelper::setCameraRotation(QPointF(-90.0f, 45.0f)); break; } - case PresetBehindLow: { + case QDataVis::PresetBehindLow: { qDebug("PresetBehindLow"); CameraHelper::setCameraRotation(QPointF(180.0f, 0.0f)); break; } - case PresetBehind: { + case QDataVis::PresetBehind: { qDebug("PresetBehind"); CameraHelper::setCameraRotation(QPointF(180.0f, 22.5f)); break; } - case PresetBehindHigh: { + case QDataVis::PresetBehindHigh: { qDebug("PresetBehindHigh"); CameraHelper::setCameraRotation(QPointF(180.0f, 45.0f)); break; } - case PresetIsometricLeft: { + case QDataVis::PresetIsometricLeft: { qDebug("PresetIsometricLeft"); CameraHelper::setCameraRotation(QPointF(45.0f, 22.5f)); break; } - case PresetIsometricLeftHigh: { + case QDataVis::PresetIsometricLeftHigh: { qDebug("PresetIsometricLeftHigh"); CameraHelper::setCameraRotation(QPointF(45.0f, 45.0f)); break; } - case PresetIsometricRight: { + case QDataVis::PresetIsometricRight: { qDebug("PresetIsometricRight"); CameraHelper::setCameraRotation(QPointF(-45.0f, 22.5f)); break; } - case PresetIsometricRightHigh: { + case QDataVis::PresetIsometricRightHigh: { qDebug("PresetIsometricRightHigh"); CameraHelper::setCameraRotation(QPointF(-45.0f, 45.0f)); break; } - case PresetDirectlyAbove: { + case QDataVis::PresetDirectlyAbove: { qDebug("PresetDirectlyAbove"); CameraHelper::setCameraRotation(QPointF(0.0f, 90.0f)); break; } - case PresetDirectlyAboveCW45: { + case QDataVis::PresetDirectlyAboveCW45: { qDebug("PresetDirectlyAboveCW45"); CameraHelper::setCameraRotation(QPointF(-45.0f, 90.0f)); break; } - case PresetDirectlyAboveCCW45: { + case QDataVis::PresetDirectlyAboveCCW45: { qDebug("PresetDirectlyAboveCCW45"); CameraHelper::setCameraRotation(QPointF(45.0f, 90.0f)); break; } - case PresetFrontBelow: { + case QDataVis::PresetFrontBelow: { qDebug("PresetFrontBelow"); CameraHelper::setCameraRotation(QPointF(0.0f, -45.0f)); break; } - case PresetLeftBelow: { + case QDataVis::PresetLeftBelow: { qDebug("PresetLeftBelow"); CameraHelper::setCameraRotation(QPointF(90.0f, -45.0f)); break; } - case PresetRightBelow: { + case QDataVis::PresetRightBelow: { qDebug("PresetRightBelow"); CameraHelper::setCameraRotation(QPointF(-90.0f, -45.0f)); break; } - case PresetBehindBelow: { + case QDataVis::PresetBehindBelow: { qDebug("PresetBehindBelow"); CameraHelper::setCameraRotation(QPointF(180.0f, -45.0f)); break; } - case PresetDirectlyBelow: { + case QDataVis::PresetDirectlyBelow: { qDebug("PresetDirectlyBelow"); CameraHelper::setCameraRotation(QPointF(0.0f, -90.0f)); break; @@ -307,4 +283,4 @@ void CameraHelper::setCameraPreset(CameraPreset preset) } } -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/utils/camerahelper_p.h b/src/datavis3d/utils/camerahelper_p.h index 21b6ccac..3b8c0c9c 100644 --- a/src/datavis3d/utils/camerahelper_p.h +++ b/src/datavis3d/utils/camerahelper_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,43 +29,62 @@ #ifndef CAMERAPOSITIONER_P_H #define CAMERAPOSITIONER_P_H -#include "qdatavis3dglobal.h" -#include "qdatavis3namespace.h" +#include "datavis3dglobal_p.h" #include "q3dbars.h" +#include <QObject> class QMatrix4x4; class QVector3D; class QPoint; class QPointF; -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE -class CameraHelper +class CameraHelper : public QObject { - public: + Q_OBJECT + +private: + QVector3D m_position; + QVector3D m_target; + QVector3D m_up; + + QPoint m_previousMousePos; + + GLfloat m_xRotation; + GLfloat m_yRotation; + GLfloat m_defaultXRotation; + GLfloat m_defaultYRotation; + + GLfloat m_rotationSpeed; + +public: + explicit CameraHelper(QObject *parent = 0); + ~CameraHelper(); + // How fast camera rotates when mouse is dragged. Default is 100. - static void setRotationSpeed(int speed); + void setRotationSpeed(int speed); // Set camera rotation in degrees - static void setCameraRotation(const QPointF &rotation); + void setCameraRotation(const QPointF &rotation); // Get camera rotations - static QPointF getCameraRotations(); + QPointF getCameraRotations(); // Set default camera orientation. Position's x and y should be 0. - static void setDefaultCameraOrientation(const QVector3D &defaultPosition, + void setDefaultCameraOrientation(const QVector3D &defaultPosition, const QVector3D &defaultTarget, const QVector3D &defaultUp); // Calculate view matrix based on rotation and zoom - static QMatrix4x4 calculateViewMatrix(const QPoint &mousePos, int zoom, + QMatrix4x4 calculateViewMatrix(const QPoint &mousePos, int zoom, int screenWidth, int screenHeight, bool showUnder = false); // Calcluate light position based on rotation. Call after calling calculateViewMatrix to get // up-to-date position - static QVector3D calculateLightPosition(const QVector3D &lightPosition, + QVector3D calculateLightPosition(const QVector3D &lightPosition, GLfloat fixedRotation = 0.0f, GLfloat distanceModifier = 0.0f); - static void updateMousePos(const QPoint &mousePos); - static void setCameraPreset(CameraPreset preset); + void updateMousePos(const QPoint &mousePos); + void setCameraPreset(QDataVis::CameraPreset preset); }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/utils/meshloader.cpp b/src/datavis3d/utils/meshloader.cpp index 0bb780ce..ee2f12a6 100644 --- a/src/datavis3d/utils/meshloader.cpp +++ b/src/datavis3d/utils/meshloader.cpp @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -49,7 +26,7 @@ #include <QDebug> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE QString slashTag = QStringLiteral("/"); @@ -145,4 +122,4 @@ bool MeshLoader::loadOBJ(const QString &path, return true; } -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/utils/meshloader_p.h b/src/datavis3d/utils/meshloader_p.h index 88ab89b3..acbfb037 100644 --- a/src/datavis3d/utils/meshloader_p.h +++ b/src/datavis3d/utils/meshloader_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,12 +29,12 @@ #ifndef MESHLOADER_P_H #define MESHLOADER_P_H -#include "qdatavis3dglobal.h" +#include "datavis3dglobal_p.h" class QVector2D; class QVector3D; -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE class MeshLoader { @@ -69,6 +46,6 @@ class MeshLoader // TODO: add loaders for other formats? }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/utils/objecthelper.cpp b/src/datavis3d/utils/objecthelper.cpp index d280abf8..cbd1e960 100644 --- a/src/datavis3d/utils/objecthelper.cpp +++ b/src/datavis3d/utils/objecthelper.cpp @@ -1,69 +1,38 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #include "meshloader_p.h" #include "vertexindexer_p.h" #include "objecthelper_p.h" +#include "abstractobjecthelper_p.h" #include <QDebug> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE ObjectHelper::ObjectHelper(const QString &objectFile) - : m_objectFile(objectFile), - m_vertexbuffer(0), - m_normalbuffer(0), - m_uvbuffer(0), - m_elementbuffer(0), - m_indexCount(0), - m_meshDataLoaded(false) + : m_objectFile(objectFile) { + m_indicesType = GL_UNSIGNED_SHORT; } ObjectHelper::~ObjectHelper() { - glDeleteBuffers(1, &m_vertexbuffer); - glDeleteBuffers(1, &m_uvbuffer); - glDeleteBuffers(1, &m_normalbuffer); - glDeleteBuffers(1, &m_elementbuffer); } void ObjectHelper::setObjectFile(const QString &objectFile) @@ -129,37 +98,4 @@ void ObjectHelper::load() m_meshDataLoaded = true; } -GLuint ObjectHelper::vertexBuf() -{ - if (!m_meshDataLoaded) - qFatal("No loaded object"); - return m_vertexbuffer; -} - -GLuint ObjectHelper::normalBuf() -{ - if (!m_meshDataLoaded) - qFatal("No loaded object"); - return m_normalbuffer; -} - -GLuint ObjectHelper::uvBuf() -{ - if (!m_meshDataLoaded) - qFatal("No loaded object"); - return m_uvbuffer; -} - -GLuint ObjectHelper::elementBuf() -{ - if (!m_meshDataLoaded) - qFatal("No loaded object"); - return m_elementbuffer; -} - -GLuint ObjectHelper::indexCount() -{ - return m_indexCount; -} - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/utils/objecthelper_p.h b/src/datavis3d/utils/objecthelper_p.h index 6cac8770..ba9fc2f3 100644 --- a/src/datavis3d/utils/objecthelper_p.h +++ b/src/datavis3d/utils/objecthelper_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,14 +29,15 @@ #ifndef OBJECTHELPER_P_H #define OBJECTHELPER_P_H -#include "qdatavis3dglobal.h" +#include "datavis3dglobal_p.h" +#include "abstractobjecthelper_p.h" #include <QOpenGLFunctions> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE -class ObjectHelper: protected QOpenGLFunctions +class ObjectHelper : public AbstractObjectHelper { - public: +public: ObjectHelper(const QString &objectFile = QString()); ~ObjectHelper(); @@ -67,25 +45,10 @@ class ObjectHelper: protected QOpenGLFunctions void load(); - GLuint vertexBuf(); - GLuint normalBuf(); - GLuint uvBuf(); - GLuint elementBuf(); - GLuint indexCount(); - - private: +private: QString m_objectFile; - - GLuint m_vertexbuffer; - GLuint m_normalbuffer; - GLuint m_uvbuffer; - GLuint m_elementbuffer; - - GLuint m_indexCount; - - GLboolean m_meshDataLoaded; }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/utils/shaderhelper.cpp b/src/datavis3d/utils/shaderhelper.cpp index c8a92dae..c8716910 100644 --- a/src/datavis3d/utils/shaderhelper.cpp +++ b/src/datavis3d/utils/shaderhelper.cpp @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ #include <QOpenGLShader> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE ShaderHelper::ShaderHelper(QObject *parent, const QString &vertexShader, @@ -249,4 +226,4 @@ GLuint ShaderHelper::normalAtt() return m_normalAttr; } -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/utils/shaderhelper_p.h b/src/datavis3d/utils/shaderhelper_p.h index 55d075de..97fcf8a0 100644 --- a/src/datavis3d/utils/shaderhelper_p.h +++ b/src/datavis3d/utils/shaderhelper_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,12 +29,12 @@ #ifndef SHADERHELPER_P_H #define SHADERHELPER_P_H -#include "qdatavis3dglobal.h" +#include "datavis3dglobal_p.h" #include <QOpenGLFunctions> class QOpenGLShaderProgram; -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE class ShaderHelper { @@ -128,6 +105,6 @@ class ShaderHelper GLboolean m_initialized; }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/utils/surfaceobject.cpp b/src/datavis3d/utils/surfaceobject.cpp new file mode 100644 index 00000000..4c05c442 --- /dev/null +++ b/src/datavis3d/utils/surfaceobject.cpp @@ -0,0 +1,349 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "surfaceobject_p.h" +#include "abstractobjecthelper_p.h" + +#include <QVector3D> +#include <QVector2D> + +#include <QDebug> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +SurfaceObject::SurfaceObject() +{ + m_indicesType = GL_UNSIGNED_INT; +} + +SurfaceObject::~SurfaceObject() +{ +} + +void SurfaceObject::setUpSmoothData(QList<qreal> series, int columns, int rows, GLfloat yRange, bool changeGeometry) +{ + GLfloat width = (GLfloat(columns) - 1.0f) / 2.0f; + GLfloat depth = (GLfloat(rows) - 1.0f) / -2.0f; + GLfloat height = yRange / 2.0f; + + // Create vertice table + QVector<QVector3D> vertices; + QVector<QVector2D> uvs; + float uvX = 1.0 / float(columns - 1); + float uvY = 1.0 / float(rows - 1); + int row = 0; + for (float i = 0.0f; i < float(rows); i += 1.0, row += columns) { + for (float j = 0; j < columns; j++) { + vertices.append(QVector3D(j / width - 1.0f, + series.at(row + int(j)) / height - 1.0f, + i / depth + 1.0f)); + uvs.append(QVector2D(j * uvX, i * uvY)); + } + } + + // Create normals + QVector<QVector3D> normals; + for (int row = 0; row < (rows - 1) * columns; row += columns) { + for (int j = 0; j < columns - 1; j++) { + normals.append(normal(vertices.at(row + j), + vertices.at(row + j + 1), + vertices.at(row + columns + j))); + } + int p = row + columns - 1; + normals.append(normal(vertices.at(p), + vertices.at(p + columns), + vertices.at(p - 1))); + } + for (int j = (rows - 1) * columns ; j < rows * columns - 1; j++) { + normals.append(normal(vertices.at(j), + vertices.at(j - columns), + vertices.at(j + 1))); + } + int p = rows * columns - 1; + normals.append(normal(vertices.at(p), + vertices.at(p - 1), + vertices.at(p - columns - 1))); + + // Create indices table + GLint *indices = 0; + if (changeGeometry) { + m_indexCount = 6 * (columns - 1) * (rows - 1); + indices = new GLint[m_indexCount]; + p = 0; + for (int row = 0; row < (rows - 1) * columns; row += columns) { + for (int j = 0; j < columns - 1; j++) { + // Left triangle + indices[p++] = row + j + 1; + indices[p++] = row + columns + j; + indices[p++] = row + j; + + // Right triangle + indices[p++] = row + columns + j + 1; + indices[p++] = row + columns + j; + indices[p++] = row + j + 1; + } + } + } + + // Create line element indices + GLint *gridIndices = 0; + if (changeGeometry) { + m_gridIndexCount = 2 * columns * (rows - 1) + 2 * rows * (columns - 1); + gridIndices = new GLint[m_gridIndexCount]; + p = 0; + for (int i = 0, row = 0; i < rows; i++, row += columns) { + for (int j = 0; j < columns - 1; j++) { + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + 1; + } + } + for (int i = 0, row = 0; i < rows - 1; i++, row += columns) { + for (int j = 0; j < columns; j++) { + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + columns; + } + } + } + + createBuffers(vertices, uvs, normals, indices, gridIndices, changeGeometry); + + if (indices) + delete indices; + if (gridIndices) + delete gridIndices; +} + + +void SurfaceObject::setUpData(QList<qreal> series, int columns, int rows, GLfloat yRange, bool changeGeometry) +{ + GLfloat width = (GLfloat(columns) - 1.0f) / 2.0f; + GLfloat depth = (GLfloat(rows) - 1.0f) / -2.0f; + GLfloat height = yRange / 2.0f; + float uvX = 1.0 / float(columns - 1); + float uvY = 1.0 / float(rows - 1); + + // Create vertice table + QVector<QVector3D> vertices; + QVector<QVector2D> uvs; + int row = 0; + for (float i = 0.0f; i < float(rows); i += 1.0f, row += columns) { + for (float j = 0.0f; j < float(columns); j += 1.0f) { + vertices.append(QVector3D(j / width - 1.0f, + series.at(row + int(j)) / height - 1.0f, + i / depth + 1.0f)); + uvs.append(QVector2D(j * uvX, i * uvY)); + if (j > 0 && j < columns - 1) { + vertices.append(vertices.last()); + uvs.append(uvs.last()); + } + } + } + + // Create normals & indices table + QVector<QVector3D> normals; + int doubleColumns = columns * 2 - 2; + + GLint *indices = 0; + int p = 0; + if (changeGeometry) { + m_indexCount = 6 * (columns - 1) * (rows - 1); + indices = new GLint[m_indexCount]; + } + + for (int row = 0, upperRow = doubleColumns; + row < (rows - 1) * doubleColumns; + row += doubleColumns, upperRow += doubleColumns) { + for (int j = 0; j < doubleColumns; j += 2) { + // Normal for the left triangle + normals.append(normal(vertices.at(row + j), + vertices.at(row + j + 1), + vertices.at(upperRow + j))); + + // Normal for the right triangle + normals.append(normal(vertices.at(row + j + 1), + vertices.at(upperRow + j + 1), + vertices.at(upperRow + j))); + + if (changeGeometry) { + // Left triangle + indices[p++] = row + j + 1; + indices[p++] = upperRow + j; + indices[p++] = row + j; + + // Right triangle + indices[p++] = upperRow + j + 1; + indices[p++] = upperRow + j; + indices[p++] = row + j + 1; + } + } + } + + // Create grid line element indices + m_gridIndexCount = 2 * columns * (rows - 1) + 2 * rows * (columns - 1); + GLint *gridIndices = new GLint[m_gridIndexCount]; + p = 0; + int rowLimit = (rows - 1) * doubleColumns; + for (int row = 0; row < rows * doubleColumns; row += doubleColumns) { + for (int j = 0; j < doubleColumns; j += 2) { + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + 1; + + if (row < rowLimit) { + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + doubleColumns; + } + } + } + for (int i = doubleColumns - 1; i < rowLimit; i += doubleColumns) { + gridIndices[p++] = i; + gridIndices[p++] = i + doubleColumns; + } + + createBuffers(vertices, uvs, normals, indices, gridIndices, changeGeometry); + + if (indices) + delete indices; + if (gridIndices) + delete gridIndices; +} + + +void SurfaceObject::createBuffers(const QVector<QVector3D> &vertices, const QVector<QVector2D> &uvs, + const QVector<QVector3D> &normals, const GLint *indices, + const GLint *gridIndices, bool changeGeometry) +{ + initializeOpenGLFunctions(); + if (m_meshDataLoaded) { + // Delete old data + glDeleteBuffers(1, &m_vertexbuffer); + glDeleteBuffers(1, &m_normalbuffer); + if (changeGeometry) { + glDeleteBuffers(1, &m_uvbuffer); + glDeleteBuffers(1, &m_elementbuffer); + glDeleteBuffers(1, &m_gridElementbuffer); + } + } + + // Move to buffers + glGenBuffers(1, &m_vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(QVector3D), + &vertices.at(0), GL_STATIC_DRAW); + + glGenBuffers(1, &m_normalbuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_normalbuffer); + glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(QVector3D), + &normals.at(0), GL_STATIC_DRAW); + + if (changeGeometry) { + glGenBuffers(1, &m_uvbuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer); + glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(QVector2D), + &uvs.at(0), GL_STATIC_DRAW); + + glGenBuffers(1, &m_elementbuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(GLint), + indices, GL_STATIC_DRAW); + + glGenBuffers(1, &m_gridElementbuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_gridElementbuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_gridIndexCount * sizeof(GLint), + gridIndices, GL_STATIC_DRAW); + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + // We're done. Set the flag ON + m_meshDataLoaded = true; +} + +GLuint SurfaceObject::gridElementBuf() +{ + if (!m_meshDataLoaded) + qFatal("No loaded object"); + return m_gridElementbuffer; +} + +GLuint SurfaceObject::gridIndexCount() +{ + return m_gridIndexCount; +} + +QVector3D SurfaceObject::normal(const QVector3D &a, const QVector3D &b, const QVector3D &c) +{ + QVector3D v1 = b - a; + QVector3D v2 = c - a; + return QVector3D::crossProduct(v1, v2); +} + +QT_DATAVIS3D_END_NAMESPACE + + + +// For rainy days + +// QVector3D vertices[] = { +// QVector3D(-0.5f, 0.0f, 0.1f), +// QVector3D(0.5f, 0.0f, 0.1f), +// QVector3D(0.0f, 1.0f, -0.5f) +// }; + +// QVector3D normals[] = { +// QVector3D(0.5, 0.0, 1.0), +// QVector3D(0.5, 0.0, 1.0), +// QVector3D(0.5, 0.0, 1.0) +// }; + +// vertices.append(QVector3D(-1.0f, 0.0f, 0.1f)); +// vertices.append(QVector3D(0.0f, 0.0f, 0.1f)); +// vertices.append(QVector3D(0.0f, 0.5f, -0.5f)); + +// normals.append(QVector3D(0.5, 0.0, 1.0)); +// normals.append(QVector3D(0.5, 0.0, 1.0)); +// normals.append(QVector3D(0.5, 0.0, 1.0)); + +//GLushort indices[] = {0, 1, 2, 1, 3, 2}; +//GLushort indices[] = {1, 3, 2}; + +//qDebug() << indices[p + 0] << ", " << indices[p + 1] << ", " << indices[p + 2]; +//qDebug() << indices[p + 3] << ", " << indices[p + 4] << ", " << indices[p + 5]; + +//qDebug() << "(" << float(j) / width << ", 0.0, " << float(i) / depth * -1.0f << ")"; + +//normals.append(QVector3D(1,0,0)); +//normals.append(QVector3D(0,1,0)); +//normals.append(QVector3D(0,0,1)); +//normals.append(QVector3D(1,0,1)); + +//normals.append(QVector3D(1,0,0)); +//normals.append(QVector3D(0,1,0)); +//normals.append(QVector3D(0,0,1)); +//normals.append(QVector3D(1,0,1)); + +//normals.append(QVector3D(1,0,0)); +//normals.append(QVector3D(0,1,0)); +//normals.append(QVector3D(0,0,1)); +//normals.append(QVector3D(1,0,1)); + + +//qDebug() << "Left normal from (" << row + j << ", " << row + j + 1 << ", " << row + doubleColumns + j << ")"; + +//qDebug() << "right normal from (" << row + j +1 << ", " << row + doubleColumns + j + 1 << ", " << row + doubleColumns + j << ")"; + diff --git a/src/datavis3d/utils/surfaceobject_p.h b/src/datavis3d/utils/surfaceobject_p.h new file mode 100644 index 00000000..729757c4 --- /dev/null +++ b/src/datavis3d/utils/surfaceobject_p.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 SURFACEOBJECT_P_H +#define SURFACEOBJECT_P_H + +#include "datavis3dglobal_p.h" +#include "abstractobjecthelper_p.h" +#include <QOpenGLFunctions> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class SurfaceObject : public AbstractObjectHelper +{ +public: + SurfaceObject(); + ~SurfaceObject(); + + void setUpData(QList<qreal> series, int columns, int rows, GLfloat yRange, bool changeGeometry); + void setUpSmoothData(QList<qreal> series, int columns, int rows, GLfloat yRange, bool changeGeometry); + GLuint gridElementBuf(); + GLuint gridIndexCount(); + +private: + QVector3D normal(const QVector3D &a, const QVector3D &b, const QVector3D &c); + void createBuffers(const QVector<QVector3D> &vertices, const QVector<QVector2D> &uvs, + const QVector<QVector3D> &normals, const GLint *indices, + const GLint *gridIndices, bool changeGeometry); + +private: + QList<qreal> m_series; + int m_dataWidth; + int m_dataDepth; + GLfloat m_yRange; + GLuint m_gridElementbuffer; + GLuint m_gridIndexCount; +}; + +QT_DATAVIS3D_END_NAMESPACE +#endif // SURFACEOBJECT_P_H diff --git a/src/datavis3d/utils/texturehelper.cpp b/src/datavis3d/utils/texturehelper.cpp index 3d827c50..1773c0f8 100644 --- a/src/datavis3d/utils/texturehelper.cpp +++ b/src/datavis3d/utils/texturehelper.cpp @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -46,7 +23,7 @@ #include <QDebug> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE TextureHelper::TextureHelper() { @@ -101,6 +78,22 @@ GLuint TextureHelper::create2DTexture(const QImage &image, bool useTrilinearFilt return textureId; } +GLuint TextureHelper::create2DTexture(const uchar *image, int width, int height) +{ + GLuint textureId; + glGenTextures(1, &textureId); + glBindTexture(GL_TEXTURE_2D, textureId); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, + 0, GL_RGBA, GL_UNSIGNED_BYTE, image); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glBindTexture(GL_TEXTURE_2D, 0); + return textureId; +} + GLuint TextureHelper::createCubeMapTexture(const QImage &image, bool useTrilinearFiltering) { if (image.isNull()) @@ -139,8 +132,8 @@ GLuint TextureHelper::createSelectionBuffer(const QSize &size, GLuint &texture, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //#if !defined(QT_OPENGL_ES_2) -// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB, -// GL_UNSIGNED_INT, NULL); +// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGB, +// GL_UNSIGNED_BYTE, NULL); //#else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); @@ -181,17 +174,18 @@ GLuint TextureHelper::createSelectionTexture(const QSize &size, GLuint &frameBuf glBindTexture(GL_TEXTURE_2D, textureid); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -//#if !defined(QT_OPENGL_ES_2) -// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB, -// GL_UNSIGNED_INT, NULL); -//#else +#if !defined(QT_OPENGL_ES_2) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, + GL_UNSIGNED_BYTE, NULL); +#else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); -//#endif +#endif glBindTexture(GL_TEXTURE_2D, 0); // Create render buffer - glGenRenderbuffers(1, &depthBuffer); + if (!depthBuffer) + glGenRenderbuffers(1, &depthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); #if !defined(QT_OPENGL_ES_2) glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.width(), size.height()); @@ -201,7 +195,8 @@ GLuint TextureHelper::createSelectionTexture(const QSize &size, GLuint &frameBuf glBindRenderbuffer(GL_RENDERBUFFER, 0); // Create frame buffer - glGenFramebuffers(1, &frameBuffer); + if (!frameBuffer) + glGenFramebuffers(1, &frameBuffer); glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); // Attach texture to color attachment @@ -241,7 +236,8 @@ GLuint TextureHelper::createDepthTexture(const QSize &size, GLuint &frameBuffer, glBindTexture(GL_TEXTURE_2D, 0); // Create frame buffer - glGenFramebuffers(1, &frameBuffer); + if (!frameBuffer) + glGenFramebuffers(1, &frameBuffer); glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); // Attach texture to depth attachment @@ -395,4 +391,4 @@ QRgb TextureHelper::qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture } } -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/utils/texturehelper_p.h b/src/datavis3d/utils/texturehelper_p.h index e848f063..e8f17d33 100644 --- a/src/datavis3d/utils/texturehelper_p.h +++ b/src/datavis3d/utils/texturehelper_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,11 +29,11 @@ #ifndef TEXTUREHELPER_P_H #define TEXTUREHELPER_P_H -#include "qdatavis3dglobal.h" +#include "datavis3dglobal_p.h" #include <QOpenGLFunctions> #include <QRgb> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE class TextureHelper : protected QOpenGLFunctions { @@ -67,6 +44,7 @@ class TextureHelper : protected QOpenGLFunctions // Ownership of created texture is transferred to caller GLuint create2DTexture(const QImage &image, bool useTrilinearFiltering = false, bool convert = true); + GLuint create2DTexture(const uchar *image, int width, int height); GLuint createCubeMapTexture(const QImage &image, bool useTrilinearFiltering = false); // Returns selection framebuffer and inserts generated texture id to texture parameters GLuint createSelectionBuffer(const QSize &size, GLuint &texture, GLuint &depthTexture); @@ -83,10 +61,12 @@ class TextureHelper : protected QOpenGLFunctions void convertToGLFormatHelper(QImage &dstImage, const QImage &srcImage, GLenum texture_format); QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format); - friend class Q3DBarsPrivate; - friend class Q3DMapsPrivate; + friend class Bars3dRenderer; + friend class Maps3DController; + friend class Surface3dRenderer; + friend class Scatter3DRenderer; }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/utils/utils.cpp b/src/datavis3d/utils/utils.cpp index 7acca185..cf6b91f8 100644 --- a/src/datavis3d/utils/utils.cpp +++ b/src/datavis3d/utils/utils.cpp @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -51,7 +28,7 @@ #include <QDebug> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE #define NUM_IN_POWER(y, x) for (;y<x;y<<=1) #define MIN_POWER 32 @@ -110,23 +87,23 @@ void Utils::printText(QPainter *painter, const QString &text, const QSize &posit if (absoluteCoords) { // This assumes absolute screen coordinates painter->translate(position.width() - (((float)bgrStrLen / 2.0f) - * cos(rotation * m_pi / 180.0f)) - + (((float)bgrHeight / 2.0f) * sin(rotation * m_pi / 180.0f)), + * qCos(qDegreesToRadians(rotation))) + + (((float)bgrHeight / 2.0f) * qSin(qDegreesToRadians(rotation))), position.height() - - ((((float)bgrHeight / 2.0f) * cos(rotation * m_pi / 180.0f)) - + (((float)bgrStrLen / 2.0f) * sin(rotation * m_pi / 180.0f)))); + - ((((float)bgrHeight / 2.0f) * qCos(qDegreesToRadians(rotation))) + + (((float)bgrStrLen / 2.0f) * qSin(qDegreesToRadians(rotation))))); } else { // This calculates y as a distance from screen bottom painter->translate(position.width() - (((float)bgrStrLen / 2.0f) - * cos(rotation * m_pi / 180.0f)) - + (((float)bgrHeight / 2.0f) * sin(rotation * m_pi / 180.0f)), + * qCos(qDegreesToRadians(rotation))) + + (((float)bgrHeight / 2.0f) * qSin(qDegreesToRadians(rotation))), painter->window().height() - position.height() - - ((((float)bgrHeight / 2.0f) * cos(rotation * m_pi / 180.0f)) - + (((float)bgrStrLen / 2.0f) * sin(rotation * m_pi / 180.0f)))); + - ((((float)bgrHeight / 2.0f) * qCos(qDegreesToRadians(rotation))) + + (((float)bgrStrLen / 2.0f) * qSin(qDegreesToRadians(rotation))))); } //qDebug() << painter->window().height() - position.height() - // - ((((float)bgrHeight / 2.0f) * cos(rotation * m_pi / 180.0f)) - // + (((float)bgrStrLen / 2.0f) * sin(rotation * m_pi / 180.0f))); + // - ((((float)bgrHeight / 2.0f) * qCos(qDegreesToRadians(rotation))) + // + (((float)bgrStrLen / 2.0f) * qSin(qDegreesToRadians(rotation)))); painter->rotate(rotation); painter->drawText(0, 0, bgrStrLen, bgrHeight, @@ -144,7 +121,7 @@ void Utils::printText(QPainter *painter, const QString &text, const QSize &posit } QImage Utils::printTextToImage(const QFont &font, const QString &text, const QColor &bgrColor, - const QColor &txtColor, LabelTransparency transparency) + const QColor &txtColor, QDataVis::LabelTransparency transparency) { GLuint paddingWidth = 15; GLuint paddingHeight = 15; @@ -170,7 +147,7 @@ QImage Utils::printTextToImage(const QFont &font, const QString &text, const QCo paddingHeight /= 2; //qDebug() << "label size after padding" << labelSize << paddingWidth << paddingHeight; #else - if (TransparencyNoBackground == transparency) + if (QDataVis::TransparencyNoBackground == transparency) labelSize = QSize(valueStrWidth, valueStrHeight); else labelSize = QSize(valueStrWidth + paddingWidth * 2, valueStrHeight + paddingHeight * 2); @@ -187,7 +164,7 @@ QImage Utils::printTextToImage(const QFont &font, const QString &text, const QCo painter.setCompositionMode(QPainter::CompositionMode_Source); switch (transparency) { // TODO: Texture size padding fix for Android f**ks this up for axis labels. Fix or disable for android. - case TransparencyNoBackground: { + case QDataVis::TransparencyNoBackground: { painter.setFont(valueFont); painter.setPen(txtColor); painter.drawText(0, 0, @@ -196,7 +173,7 @@ QImage Utils::printTextToImage(const QFont &font, const QString &text, const QCo text); break; } - case TransparencyFromTheme: { + case QDataVis::TransparencyFromTheme: { painter.setBrush(QBrush(bgrColor)); painter.setPen(bgrColor); painter.drawRoundedRect(0, 0, labelSize.width(), labelSize.height(), 10.0, 10.0f); @@ -208,7 +185,7 @@ QImage Utils::printTextToImage(const QFont &font, const QString &text, const QCo text); break; } - case TransparencyNone: { + case QDataVis::TransparencyNone: { painter.setBrush(QBrush(bgrColor)); painter.setPen(bgrColor); painter.drawRect(0, 0, labelSize.width(), labelSize.height()); @@ -254,4 +231,4 @@ QVector3D Utils::getSelection(QPoint mousepos, int height) return selectedColor; } -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/utils/utils.pri b/src/datavis3d/utils/utils.pri index 566af55f..cef5ebf0 100644 --- a/src/datavis3d/utils/utils.pri +++ b/src/datavis3d/utils/utils.pri @@ -4,7 +4,9 @@ HEADERS += $$PWD/meshloader_p.h \ $$PWD/shaderhelper_p.h \ $$PWD/objecthelper_p.h \ $$PWD/texturehelper_p.h \ - $$PWD/utils_p.h + $$PWD/utils_p.h \ + $$PWD/abstractobjecthelper_p.h \ + $$PWD/surfaceobject_p.h SOURCES += $$PWD/meshloader.cpp \ $$PWD/vertexindexer.cpp \ @@ -12,4 +14,6 @@ SOURCES += $$PWD/meshloader.cpp \ $$PWD/shaderhelper.cpp \ $$PWD/objecthelper.cpp \ $$PWD/texturehelper.cpp \ - $$PWD/utils.cpp + $$PWD/utils.cpp \ + $$PWD/abstractobjecthelper.cpp \ + $$PWD/surfaceobject.cpp diff --git a/src/datavis3d/utils/utils_p.h b/src/datavis3d/utils/utils_p.h index f809dad7..fe7d6081 100644 --- a/src/datavis3d/utils/utils_p.h +++ b/src/datavis3d/utils/utils_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,8 +29,7 @@ #ifndef UTILS_P_H #define UTILS_P_H -#include "qdatavis3dglobal.h" -#include "qdatavis3namespace.h" +#include "datavis3dglobal_p.h" #include "q3dbars.h" class QVector3D; @@ -63,7 +39,7 @@ class QString; class QPoint; class QImage; -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE class Utils { @@ -76,10 +52,10 @@ class Utils const QString &text, const QColor &bgrColor, const QColor &txtColor, - LabelTransparency transparency); + QDataVis::LabelTransparency transparency); static QVector3D getSelection(QPoint mousepos, int height); }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3d/utils/vertexindexer.cpp b/src/datavis3d/utils/vertexindexer.cpp index c1dfb1aa..6efba116 100644 --- a/src/datavis3d/utils/vertexindexer.cpp +++ b/src/datavis3d/utils/vertexindexer.cpp @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -46,14 +23,14 @@ #include <QDebug> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE int unique_vertices = 0; // Returns true if v1 can be considered equal to v2 bool VertexIndexer::is_near(float v1, float v2) { - return qFabs(v1 - v2) < 0.01f; + return qAbs(v1 - v2) < 0.01f; } // Searches through all already-exported vertices @@ -173,4 +150,4 @@ void VertexIndexer::indexVBO_TBN(const QVector<QVector3D> &in_vertices, //qDebug() << "unique vertices" << unique_vertices; } -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/utils/vertexindexer_p.h b/src/datavis3d/utils/vertexindexer_p.h index cced863b..3ca62236 100644 --- a/src/datavis3d/utils/vertexindexer_p.h +++ b/src/datavis3d/utils/vertexindexer_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,13 +29,13 @@ #ifndef VERTEXINDEXER_P_H #define VERTEXINDEXER_P_H -#include "qdatavis3dglobal.h" +#include "datavis3dglobal_p.h" #include <QVector> #include <QVector2D> #include <QVector3D> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE class VertexIndexer { @@ -106,6 +83,6 @@ class VertexIndexer unsigned short &result); }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif diff --git a/src/datavis3dqml2/datavis3dqml2.pro b/src/datavis3dqml2/datavis3dqml2.pro index 59abef57..c994c5be 100644 --- a/src/datavis3dqml2/datavis3dqml2.pro +++ b/src/datavis3dqml2/datavis3dqml2.pro @@ -6,27 +6,33 @@ CONFIG += qt plugin TARGET = $$qtLibraryTarget($$TARGET) uri = com.digia.QtDataVis3D -staticlib:DEFINES+=QTENTERPRISE_DATAVIS3D_STATICLIB +static { + DEFINES += QT_DATAVIS3D_STATICLIB + CONFIG -= static staticlib +} # Input -INCLUDEPATH += ../datavis3d/engine +INCLUDEPATH += ../datavis3d/engine \ + ../datavis3d/global \ + ../datavis3d/data SOURCES += \ datavis3dqml2_plugin.cpp \ declarativebars.cpp \ - declarativemaps.cpp #\ - #declarativedataitem.cpp \ - #declarativedatarow.cpp \ - #declarativedataset.cpp + declarativebarsrenderer.cpp \ + declarativescatter.cpp \ + declarativescatterrenderer.cpp \ + declarativemaps.cpp \ + declarativemapsrenderer.cpp HEADERS += \ datavis3dqml2_plugin.h \ - declarativebars.h \ - declarativemaps.h \ #\ - declarativebars_p.h - #declarativedataitem.h \ - #declarativedatarow.h \ - #declarativedataset.h + declarativebars_p.h \ + declarativebarsrenderer_p.h \ + declarativescatter_p.h \ + declarativescatterrenderer_p.h \ + declarativemaps_p.h \ + declarativemapsrenderer_p.h OTHER_FILES = qmldir diff --git a/src/datavis3dqml2/datavis3dqml2_plugin.cpp b/src/datavis3dqml2/datavis3dqml2_plugin.cpp index 86923cde..d1e534f8 100644 --- a/src/datavis3dqml2/datavis3dqml2_plugin.cpp +++ b/src/datavis3dqml2/datavis3dqml2_plugin.cpp @@ -1,63 +1,48 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #include "datavis3dqml2_plugin.h" #include <qqml.h> -#include <QDebug> -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE + +QT_DATAVIS3D_BEGIN_NAMESPACE void Datavis3dqml2Plugin::registerTypes(const char *uri) { - qDebug() << "Datavis3dqml2Plugin::registerTypes()"; - // @uri com.digia.QtDataVis3D - qmlRegisterType<QDataItem>(uri, 1, 0, "DataItem"); - qmlRegisterType<QDataRow>(uri, 1, 0, "DataRow"); - qmlRegisterType<QDataSet>(uri, 1, 0, "DataSet"); + qmlRegisterUncreatableType<QAbstractItemModel>(uri, 1, 0, "AbstractItemModel", + QLatin1String("Trying to create uncreatable: AbstractItemModel.")); + qmlRegisterUncreatableType<QDataVis>(uri, 1, 0, "DataVis", + QLatin1String("Trying to create uncreatable: DataVis.")); + qmlRegisterUncreatableType<QAbstractAxis>(uri, 1, 0, "AbstractAxis", + QLatin1String("Trying to create uncreatable: AbstractAxis.")); + + qmlRegisterType<QItemModelBarDataMapping>(uri, 1, 0, "BarDataMapping"); + qmlRegisterType<QItemModelMapDataMapping>(uri, 1, 0, "MapDataMapping"); + qmlRegisterType<QItemModelScatterDataMapping>(uri, 1, 0, "ScatterDataMapping"); qmlRegisterType<DeclarativeBars>(uri, 1, 0, "Bars3D"); -} + qmlRegisterType<DeclarativeMaps>(uri, 1, 0, "Maps3D"); + qmlRegisterType<DeclarativeScatter>(uri, 1, 0, "Scatter3D"); -//#include "moc_datavis3dqml2_plugin.cpp" + qmlRegisterType<QValueAxis>(uri, 1, 0, "ValueAxis"); + qmlRegisterType<QCategoryAxis>(uri, 1, 0, "CategoryAxis"); +} -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3dqml2/datavis3dqml2_plugin.h b/src/datavis3dqml2/datavis3dqml2_plugin.h index 9dcf00cb..ac88e1b5 100644 --- a/src/datavis3dqml2/datavis3dqml2_plugin.h +++ b/src/datavis3dqml2/datavis3dqml2_plugin.h @@ -1,75 +1,53 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ #ifndef DATAVIS3DQML2_PLUGIN_H #define DATAVIS3DQML2_PLUGIN_H -#include "QtDataVis3D/qdatavis3dglobal.h" -#include "QtDataVis3D/qdatavis3namespace.h" -#include "qdataitem.h" -#include "qdatarow.h" -#include "qdataset.h" - -#include "declarativebars.h" -#include "declarativemaps.h" -//#include "declarativedataitem.h" -//#include "declarativedatarow.h" -//#include "declarativedataset.h" +#include "datavis3dglobal_p.h" +#include "declarativebars_p.h" +#include "declarativemaps_p.h" +#include "declarativescatter_p.h" +#include "qitemmodelbardatamapping.h" +#include "qitemmodelmapdatamapping.h" +#include "qitemmodelscatterdatamapping.h" +#include "qvalueaxis.h" +#include "qcategoryaxis.h" #include <QQmlExtensionPlugin> -QTENTERPRISE_DATAVIS3D_USE_NAMESPACE - -//Q_DECLARE_METATYPE(DeclarativeDataItem *) -//Q_DECLARE_METATYPE(DeclarativeDataRow *) -//Q_DECLARE_METATYPE(DeclarativeDataSet *) +QT_DATAVIS3D_USE_NAMESPACE Q_DECLARE_METATYPE(DeclarativeBars *) Q_DECLARE_METATYPE(DeclarativeMaps *) +Q_DECLARE_METATYPE(DeclarativeScatter *) + +Q_DECLARE_METATYPE(QItemModelBarDataMapping *) +Q_DECLARE_METATYPE(QItemModelMapDataMapping *) +Q_DECLARE_METATYPE(QItemModelScatterDataMapping *) +Q_DECLARE_METATYPE(QAbstractItemModel *) +Q_DECLARE_METATYPE(QDataVis *) -Q_DECLARE_METATYPE(QDataItem *) -Q_DECLARE_METATYPE(QDataRow *) -Q_DECLARE_METATYPE(QDataSet *) +Q_DECLARE_METATYPE(QAbstractAxis *) +Q_DECLARE_METATYPE(QCategoryAxis *) +Q_DECLARE_METATYPE(QValueAxis *) -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE class Datavis3dqml2Plugin : public QQmlExtensionPlugin { @@ -80,7 +58,7 @@ public: void registerTypes(const char *uri); }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE #endif // DATAVIS3DQML2_PLUGIN_H diff --git a/src/datavis3dqml2/declarativebars.cpp b/src/datavis3dqml2/declarativebars.cpp index 3194baa5..e7af7f8c 100644 --- a/src/datavis3dqml2/declarativebars.cpp +++ b/src/datavis3dqml2/declarativebars.cpp @@ -1,63 +1,50 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ -#include "declarativebars.h" -#include "bars3dshared_p.h" +#include "declarativebars_p.h" +#include "declarativebarsrenderer_p.h" +#include "qitemmodelbardataproxy.h" +#include "qvalueaxis.h" -#include <QtQuick/QQuickWindow> -#include <QtGui/QOpenGLFramebufferObject> -#include <QOpenGLContext> -#include <QGuiApplication> -#include <QThread> -#include <QDebug> +QT_DATAVIS3D_BEGIN_NAMESPACE -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +const QString smoothString(QStringLiteral("Smooth")); -DeclarativeBars::DeclarativeBars(QQuickItem *parent): QQuickItem(parent), m_cachedState(new DeclarativeBarsCachedStatePrivate()), m_shared(0) +DeclarativeBars::DeclarativeBars(QQuickItem *parent) + : QQuickItem(parent), + m_shared(0), + m_initialisedSize(0, 0), + m_cameraPreset(QDataVis::NoPreset), + m_theme(QDataVis::ThemeDefault) { setFlags(QQuickItem::ItemHasContents); + setAcceptedMouseButtons(Qt::AllButtons); - setRotation(180.0); + // TODO: These seem to have no effect; find a way to activate anti-aliasing setAntialiasing(true); setSmooth(true); + + // Create the shared component on the main GUI thread. + m_shared = new Bars3dController(boundingRect().toRect()); + QObject::connect(m_shared, &Bars3dController::shadowQualityChanged, this, + &DeclarativeBars::handleShadowQualityUpdate); + + m_shared->setDataProxy(new QItemModelBarDataProxy); } DeclarativeBars::~DeclarativeBars() @@ -65,316 +52,329 @@ DeclarativeBars::~DeclarativeBars() delete m_shared; } -QSGNode *DeclarativeBars::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +void DeclarativeBars::handleShadowQualityUpdate(QDataVis::ShadowQuality quality) { - qDebug() << "Enter DeclarativeBars::updatePaintNode"; - // Delete old node and recreate it. This function gets called when window geometry changes. - if (oldNode) - delete oldNode; - - if (!m_shared) - m_shared = new Bars3dShared(boundingRect().toRect()); - - // Lazy initialization of shared object on the SGRenderThread - m_shared->initializeOpenGL(); - - // We need to create a node class that does the rendering (ie. a node that "captures" the rendering we do) - qDebug() << "DeclarativeBars::updatePaintNode Creating new node"; - - // Create the new render node - DeclarativeBarsRenderer *node = new DeclarativeBarsRenderer(window(), m_shared); - node->setRect(boundingRect()); - m_shared->setBoundingRect(boundingRect().toRect()); - - if (m_cachedState->m_isSampleSpaceSet) { - m_shared->setupSampleSpace(m_cachedState->m_samplesRow, m_cachedState->m_samplesColumn, m_cachedState->m_labelRow, m_cachedState->m_labelColumn, m_cachedState->m_labelHeight); - m_cachedState->m_isSampleSpaceSet = false; - } + emit shadowQualityChanged(quality); +} - if (m_cachedState->m_dataRow) { - m_shared->addDataRow(m_cachedState->m_dataRow); - m_cachedState->m_dataRow = 0; - } +void DeclarativeBars::classBegin() +{ + qDebug() << "classBegin"; +} - if (m_cachedState->m_isSelectionModeSet) { - m_shared->setSelectionMode(m_cachedState->m_selectionMode); - m_cachedState->m_isSelectionModeSet = false; - } +void DeclarativeBars::componentComplete() +{ + qDebug() << "componentComplete"; +} - if (m_cachedState->m_isLabelTransparencySet) { - m_shared->setLabelTransparency(m_cachedState->m_labelTransparency); - m_cachedState->m_isLabelTransparencySet = false; +QSGNode *DeclarativeBars::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + // If old node exists and has right size, reuse it. + if (oldNode && m_initialisedSize == boundingRect().size().toSize()) { + // Update bounding rectangle (that has same size as before). + static_cast<DeclarativeBarsRenderer *>( oldNode )->setRect(boundingRect()); + return oldNode; } - if (m_cachedState->m_isShadowQualitySet) { - m_shared->setShadowQuality(m_cachedState->m_shadowQuality); - m_cachedState->m_isShadowQualitySet = false; - } + // Create a new render node when size changes or if there is no node yet + m_initialisedSize = boundingRect().size().toSize(); - if (m_cachedState->m_isGridSet) { - m_shared->setGridEnabled(m_cachedState->m_isGridEnabled); - m_cachedState->m_isGridSet = false; - } + // Delete old node + if (oldNode) + delete oldNode; - qDebug() << "Exit DeclarativeBars::updatePaintNode"; + // Create a new one and set it's bounding rectangle + DeclarativeBarsRenderer *node = new DeclarativeBarsRenderer(window(), m_shared); + node->setRect(boundingRect()); + m_shared->setBoundingRect(boundingRect().toRect()); return node; } -void DeclarativeBars::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative) +void DeclarativeBars::setupSampleSpace(int rowCount, int columnCount) { - m_shared->setBarSpecs(thickness, spacing, relative); + m_shared->setupSampleSpace(rowCount, columnCount); } -void DeclarativeBars::setBarType(BarStyle style, bool smooth) +void DeclarativeBars::setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, + bool uniform) { - m_shared->setBarType(style, smooth); + m_shared->setObjectColor(baseColor, heightColor, depthColor, uniform); } -void DeclarativeBars::setupSampleSpace(int samplesRow, int samplesColumn, const QString &labelRow, - const QString &labelColumn, const QString &labelHeight) +void DeclarativeBars::setCameraPosition(qreal horizontal, qreal vertical, int distance) { - m_cachedState->m_samplesRow = samplesRow; - m_cachedState->m_samplesColumn = samplesColumn; - m_cachedState->m_labelRow = labelRow; - m_cachedState->m_labelColumn = labelColumn; - m_cachedState->m_labelHeight = labelHeight; - m_cachedState->m_isSampleSpaceSet = true; + m_shared->setCameraPosition(GLfloat(horizontal), GLfloat(vertical), GLint(distance)); } - -void DeclarativeBars::setCameraPreset(CameraPreset preset) +void DeclarativeBars::setData(QAbstractItemModel *data) { - m_shared->setCameraPreset(preset); + static_cast<QItemModelBarDataProxy *>(m_shared->dataProxy())->setItemModel(data); } -void DeclarativeBars::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) +QAbstractItemModel *DeclarativeBars::data() { - m_shared->setCameraPosition(horizontal, vertical, distance); + return static_cast<QItemModelBarDataProxy *>(m_shared->dataProxy())->itemModel(); } -void DeclarativeBars::setTheme(ColorTheme theme) +void DeclarativeBars::setMapping(QItemModelBarDataMapping *mapping) { - m_shared->setTheme(theme); + static_cast<QItemModelBarDataProxy *>(m_shared->dataProxy())->setMapping(mapping); } -void DeclarativeBars::setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, bool uniform) +QCategoryAxis *DeclarativeBars::axisX() const { - m_shared->setBarColor(baseColor, heightColor, depthColor, uniform); + return static_cast<QCategoryAxis *>(m_shared->axisX()); } +void DeclarativeBars::setAxisX(QCategoryAxis *axis) +{ + m_shared->setAxisX(axis); +} -void DeclarativeBars::setFontSize(float fontsize) +QValueAxis *DeclarativeBars::axisY() const { - m_shared->setFontSize(fontsize); + return static_cast<QValueAxis *>(m_shared->axisY()); } -float DeclarativeBars::fontSize() +void DeclarativeBars::setAxisY(QValueAxis *axis) { - return m_shared->fontSize(); + m_shared->setAxisY(axis); } -void DeclarativeBars::setFont(const QFont &font) +QCategoryAxis *DeclarativeBars::axisZ() const { - m_shared->setFont(font); + return static_cast<QCategoryAxis *>(m_shared->axisZ()); } -QFont DeclarativeBars::font() +void DeclarativeBars::setAxisZ(QCategoryAxis *axis) { - return m_shared->font(); + m_shared->setAxisZ(axis); } -void DeclarativeBars::setLabelTransparency(DeclarativeBars::LabelTransparency transparency) +QItemModelBarDataMapping *DeclarativeBars::mapping() const { - m_cachedState->m_labelTransparency = QtDataVis3D::LabelTransparency(transparency); - m_cachedState->m_isLabelTransparencySet = true; + return static_cast<QItemModelBarDataProxy *>(m_shared->dataProxy())->mapping(); } -DeclarativeBars::LabelTransparency DeclarativeBars::labelTransparency() +void DeclarativeBars::setBarThickness(QSizeF thickness) { - return DeclarativeBars::LabelTransparency(m_shared->labelTransparency()); + m_shared->setBarSpecs(thickness, barSpacing(), isBarSpacingRelative()); } -void DeclarativeBars::setGridEnabled(bool enable) +QSizeF DeclarativeBars::barThickness() { - m_cachedState->m_isGridEnabled = enable; - m_cachedState->m_isGridSet = true; + return m_shared->barThickness(); } -bool DeclarativeBars::gridEnabled() +void DeclarativeBars::setBarSpacing(QSizeF spacing) { - return m_shared->gridEnabled(); + m_shared->setBarSpecs(barThickness(), spacing, isBarSpacingRelative()); } -void DeclarativeBars::setBackgroundEnabled(bool enable) +QSizeF DeclarativeBars::barSpacing() { - m_shared->setBackgroundEnabled(enable); + return m_shared->barSpacing(); } -bool DeclarativeBars::backgroundEnabled() +void DeclarativeBars::setBarSpacingRelative(bool relative) { - return m_shared->backgroundEnabled(); + m_shared->setBarSpecs(barThickness(), barSpacing(), relative); } -void DeclarativeBars::setTickCount(GLint tickCount, GLfloat step, GLfloat minimum) +bool DeclarativeBars::isBarSpacingRelative() { - m_shared->setTickCount(tickCount, step, minimum); + return m_shared->isBarSpecRelative(); } -void DeclarativeBars::addDataRow(const QVector<float> &dataRow, const QString &labelRow, - const QVector<QString> &labelsColumn) +void DeclarativeBars::setBarType(QDataVis::MeshStyle style) { - qDebug() << "Enter DeclarativeBars::addDataRow(const QVector<float> &dataRow...)"; - m_shared->addDataRow(dataRow, labelRow, labelsColumn); + QString objFile = m_shared->meshFileName(); + bool smooth = objFile.endsWith(smoothString); + m_shared->setBarType(style, smooth); } -void DeclarativeBars::addDataRow(const QVector<QDataItem*> &dataRow, const QString &labelRow, - const QVector<QString> &labelsColumn) +QDataVis::MeshStyle DeclarativeBars::barType() { - qDebug() << "Enter DeclarativeBars::addDataRow(const QVector<QDataItem*> &dataRow...)"; - m_shared->addDataRow(dataRow, labelRow, labelsColumn); + QString objFile = m_shared->meshFileName(); + if (objFile.contains("/sphere")) + return QDataVis::Spheres; + else + return QDataVis::Dots; } -void DeclarativeBars::addDataRow(QDataRow *dataRow) +void DeclarativeBars::setBarSmooth(bool smooth) { - qDebug() << "Enter DeclarativeBars::addDataRow(QDataRow *dataRow)"; - m_cachedState->m_dataRow = dataRow; + QString objFile = m_shared->meshFileName(); + if (objFile.endsWith(smoothString)) { + if (smooth) + return; // Already smooth; do nothing + else // Rip Smooth off the end + objFile.resize(objFile.indexOf(smoothString)); + } else { + if (!smooth) // Already flat; do nothing + return; + else // Append Smooth to the end + objFile.append(smoothString); + } + m_shared->setMeshFileName(objFile); } -void DeclarativeBars::addDataSet(const QVector< QVector<float> > &data, const QVector<QString> &labelsRow, - const QVector<QString> &labelsColumn) +bool DeclarativeBars::barSmooth() { - m_shared->addDataSet(data, labelsRow,labelsColumn); + QString objFile = m_shared->meshFileName(); + return objFile.endsWith(smoothString); } -void DeclarativeBars::addDataSet(const QVector< QVector<QDataItem*> > &data, - const QVector<QString> &labelsRow, - const QVector<QString> &labelsColumn) +void DeclarativeBars::setMeshFileName(const QString &objFileName) { - m_shared->addDataSet(data, labelsRow, labelsColumn); + m_shared->setMeshFileName(objFileName); } -void DeclarativeBars::addDataSet(QDataSet* dataSet) +QString DeclarativeBars::meshFileName() { - m_shared->addDataSet(dataSet); + return m_shared->meshFileName(); } -void DeclarativeBars::setSelectionMode(DeclarativeBars::SelectionMode mode) +void DeclarativeBars::setCameraPreset(QDataVis::CameraPreset preset) { - m_cachedState->m_selectionMode = QtDataVis3D::SelectionMode(mode); - m_cachedState->m_isSelectionModeSet = true; + // TODO: Implement correctly once "improved camera api" (QTRD-2122) is implemented + // We need to save this locally, as there are no getters for it in controller + m_cameraPreset = preset; + m_shared->setCameraPreset(preset); } -DeclarativeBars::SelectionMode DeclarativeBars::selectionMode() +QDataVis::CameraPreset DeclarativeBars::cameraPreset() { - return DeclarativeBars::SelectionMode(m_shared->selectionMode()); + return m_cameraPreset; } -void DeclarativeBars::setShadow(DeclarativeBars::ShadowQuality quality) +void DeclarativeBars::setTheme(QDataVis::ColorTheme theme) { - m_cachedState->m_shadowQuality = QtDataVis3D::ShadowQuality(quality); - m_cachedState->m_isShadowQualitySet = true; + // TODO: Implement correctly once "user-modifiable themes" (QTRD-2120) is implemented + // We need to save this locally, as there are no getters for it in controller + m_theme = theme; + m_shared->setColorTheme(theme); } -DeclarativeBars::ShadowQuality DeclarativeBars::shadow() +QDataVis::ColorTheme DeclarativeBars::theme() { - return DeclarativeBars::ShadowQuality(m_shared->shadowQuality()); + return m_theme; } -void DeclarativeBars::setMeshFileName(const QString &objFileName) +void DeclarativeBars::setFontSize(float fontsize) { - m_shared->setMeshFileName(objFileName); + m_shared->setFontSize(fontsize); } +float DeclarativeBars::fontSize() +{ + return m_shared->fontSize(); +} +void DeclarativeBars::setFont(const QFont &font) +{ + m_shared->setFont(font); +} +QFont DeclarativeBars::font() +{ + return m_shared->font(); +} -DeclarativeBarsRenderer::DeclarativeBarsRenderer(QQuickWindow *window, Bars3dShared *renderer) - : m_fbo(0), - m_texture(0), - m_window(window), - m_barsRenderer(renderer) +void DeclarativeBars::setLabelTransparency(QDataVis::LabelTransparency transparency) { - qDebug() << "DeclarativeBarsRenderer::DeclarativeBarsRenderer()"; - connect(m_window, SIGNAL(beforeRendering()), this, SLOT(render()), Qt::DirectConnection); - qDebug() << "QQuickWindow::openglContext()->thread()" << m_window->openglContext()->thread(); - qDebug() << "QGuiApplication::instance()->thread()" << QGuiApplication::instance()->thread(); + m_shared->setLabelTransparency(transparency); } -DeclarativeBarsRenderer::~DeclarativeBarsRenderer() +QDataVis::LabelTransparency DeclarativeBars::labelTransparency() { - delete m_texture; - delete m_fbo; + return m_shared->labelTransparency(); } -void DeclarativeBarsRenderer::render() +void DeclarativeBars::setGridVisible(bool visible) { - static bool firstRender = true; - if (firstRender) qDebug() << "DeclarativeBarsRenderer::render() running on thread "<< QThread::currentThread(); - firstRender = false; + m_shared->setGridEnabled(visible); +} - QSize size = rect().size().toSize(); +bool DeclarativeBars::isGridVisible() +{ + return m_shared->gridEnabled(); +} - if (!m_fbo) { - QOpenGLFramebufferObjectFormat format; - format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); - m_fbo = new QOpenGLFramebufferObject(size, format); - m_texture = m_window->createTextureFromId(m_fbo->texture(), size); +void DeclarativeBars::setBackgroundVisible(bool visible) +{ + m_shared->setBackgroundEnabled(visible); +} - // TODO: If we create the vis3d this way, how do we connect it with QML? - // Should we create it at QML and give it to DataVisView using a property (setVisualizer or similar)? - // DataVisView can then give it here as an argument in constructor? +bool DeclarativeBars::isBackgroundVisible() +{ + return m_shared->backgroundEnabled(); +} - // TODO: For testing. Add some data to scene. - QVector< QVector<float> > data; - QVector<float> row; - for (float j = 0.0f; j < 5.0f; j++) { - for (float i = 0.0f; i < 5.0f; i++) - row.append(j / 10.0f + i / 10.0f); - data.append(row); - row.clear(); - } +void DeclarativeBars::setSelectionMode(QDataVis::SelectionMode mode) +{ + m_shared->setSelectionMode(mode); +} - setTexture(m_texture); - } +QDataVis::SelectionMode DeclarativeBars::selectionMode() +{ + return m_shared->selectionMode(); +} - m_fbo->bind(); +void DeclarativeBars::setShadowQuality(QDataVis::ShadowQuality quality) +{ + m_shared->setShadowQuality(quality); +} - // SGRendering State resets between calls... - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); +QDataVis::ShadowQuality DeclarativeBars::shadowQuality() +{ + return m_shared->shadowQuality(); +} - // Emulate mouse movement - // TODO: Remove this and implement properly - static int rot = 0; - rot += 5; - if (rot > 2870) rot = 0; - m_barsRenderer->m_mousePos.setX(rot); - m_barsRenderer->m_mousePos.setY(100); +int DeclarativeBars::rows() const +{ + return m_shared->rowCount(); +} - // Call the shared rendering function - m_barsRenderer->render(); +void DeclarativeBars::setRows(int rows) +{ + setupSampleSpace(rows, columns()); +} - m_fbo->bindDefault(); +int DeclarativeBars::columns() const +{ + return m_shared->columnCount(); +} - m_window->update(); +void DeclarativeBars::setColumns(int columns) +{ + setupSampleSpace(rows(), columns); } +void DeclarativeBars::mousePressEvent(QMouseEvent *event) +{ + QPoint mousePos = event->pos(); + //mousePos.setY(height() - mousePos.y()); + m_shared->mousePressEvent(event, mousePos); +} -DeclarativeBarsCachedStatePrivate::DeclarativeBarsCachedStatePrivate() : - m_isSampleSpaceSet(false), - m_labelRow(QStringLiteral("")), - m_labelColumn(QStringLiteral("")), - m_labelHeight(QStringLiteral("")), - m_dataRow(0) +void DeclarativeBars::mouseReleaseEvent(QMouseEvent *event) { + QPoint mousePos = event->pos(); + //mousePos.setY(height() - mousePos.y()); + m_shared->mouseReleaseEvent(event, mousePos); } -DeclarativeBarsCachedStatePrivate::~DeclarativeBarsCachedStatePrivate() +void DeclarativeBars::mouseMoveEvent(QMouseEvent *event) { + QPoint mousePos = event->pos(); + //mousePos.setY(height() - mousePos.y()); + m_shared->mouseMoveEvent(event, mousePos); } +void DeclarativeBars::wheelEvent(QWheelEvent *event) +{ + m_shared->wheelEvent(event); +} -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativebars.h b/src/datavis3dqml2/declarativebars.h deleted file mode 100644 index 8194cd7d..00000000 --- a/src/datavis3dqml2/declarativebars.h +++ /dev/null @@ -1,233 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef DECLARATIVEBARS_H -#define DECLARATIVEBARS_H - -#include "bars3dshared_p.h" -#include "qdatavis3dglobal.h" -#include "qdatavis3namespace.h" -#include "declarativebars_p.h" - -#include <qsgsimpletexturenode.h> -#include <QQuickItem> -#include <QObject> - -class QOpenGLFramebufferObject; -class QSGTexture; -class QQuickWindow; - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -class DeclarativeBars : public QQuickItem -{ - Q_OBJECT - Q_PROPERTY(SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) - Q_PROPERTY(LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) - Q_PROPERTY(ShadowQuality shadowQuality READ shadow WRITE setShadow) - Q_PROPERTY(bool grid READ gridEnabled WRITE setGridEnabled) - Q_PROPERTY(int width READ width WRITE setWidth) - Q_PROPERTY(int height READ height WRITE setHeight) - Q_ENUMS(SelectionMode) - Q_ENUMS(ShadowQuality) - Q_ENUMS(LabelTransparency) - -protected: - Bars3dShared *m_shared; - DeclarativeBarsCachedStatePrivate *m_cachedState; - -public: - // Duplicated here to be able to use the same enums - enum SelectionMode { - ModeNone = 0, - ModeBar, - ModeBarAndRow, - ModeBarAndColumn, - ModeBarRowAndColumn, - ModeZoomRow, - ModeZoomColumn - }; - - enum ShadowQuality { - ShadowNone = 0, - ShadowLow = 1, - ShadowMedium = 3, - ShadowHigh = 5 - }; - - enum LabelTransparency { - TransparencyNone = 0, // Full solid, using colors from theme - TransparencyFromTheme, // Use colors and transparencies from theme - TransparencyNoBackground // Draw just text on transparent background - }; - -public: - explicit DeclarativeBars(QQuickItem *parent = 0); - ~DeclarativeBars(); - - // Add a row of data. Each new row is added to the front of the sample space, moving previous - // rows back (if sample space is more than one row deep) - Q_INVOKABLE void addDataRow(const QVector<GLfloat> &dataRow, - const QString &labelRow = QString(), - const QVector<QString> &labelsColumn = QVector<QString>()); - // ownership of dataItems is transferred - Q_INVOKABLE void addDataRow(const QVector<QDataItem*> &dataRow, - const QString &labelRow = QString(), - const QVector<QString> &labelsColumn = QVector<QString>()); - // ownership of dataRow is transferred - Q_INVOKABLE void addDataRow(QDataRow *dataRow); - - // Add complete data set at a time, as a vector of data rows - Q_INVOKABLE void addDataSet(const QVector< QVector<GLfloat> > &data, - const QVector<QString> &labelsRow = QVector<QString>(), - const QVector<QString> &labelsColumn = QVector<QString>()); - - // ownership of dataItems is transferred - Q_INVOKABLE void addDataSet(const QVector< QVector<QDataItem*> > &data, - const QVector<QString> &labelsRow = QVector<QString>(), - const QVector<QString> &labelsColumn = QVector<QString>()); - // ownership of dataSet is transferred - Q_INVOKABLE void addDataSet(QDataSet* dataSet); - - // bar thickness, spacing between bars, and is spacing relative to thickness or absolute - // y -component sets the thickness/spacing of z -direction - // With relative 0.0f means side-to-side, 1.0f = one thickness in between - Q_INVOKABLE void setBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f), - QSizeF spacing = QSizeF(1.0f, 1.0f), - bool relative = true); - - // bar type; bars (=cubes), pyramids, cones, cylinders, etc. - Q_INVOKABLE void setBarType(BarStyle style, bool smooth = false); - - // override bar type with own mesh - Q_INVOKABLE void setMeshFileName(const QString &objFileName); - - // how many samples per row and column, and names for axes - Q_INVOKABLE void setupSampleSpace(int samplesRow, int samplesColumn, - const QString &labelRow = QString(), - const QString &labelColumn = QString(), - const QString &labelHeight = QString()); - - // Select preset camera placement - Q_INVOKABLE void setCameraPreset(CameraPreset preset); - - // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and - // vertical (0...90) (or (-90...90) if there are negative values) angles and distance in - // percentage (10...500)) - Q_INVOKABLE void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); - - // Set theme (bar colors, shaders, window color, background colors, light intensity and text - // colors are affected) - Q_INVOKABLE void setTheme(ColorTheme theme); - - // Set color if you don't want to use themes. Set uniform to false if you want the (height) - // color to change from bottom to top - Q_INVOKABLE void setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, - bool uniform = true); - - // Set tick count and step. Note; tickCount * step should be the maximum possible value of data - // set. Minimum is the absolute minimum possible value a bar can have. This is especially - // important to set if values can be negative. - Q_INVOKABLE void setTickCount(GLint tickCount, GLfloat step, GLfloat minimum = 0.0f); - - // TODO: light placement API - - // Change selection mode; single bar, bar and row, bar and column, or all - void setSelectionMode(SelectionMode mode); - SelectionMode selectionMode(); - - // Font size adjustment - void setFontSize(float fontsize); - float fontSize(); - - // Set font - void setFont(const QFont &font); - QFont font(); - - // Label transparency adjustment - void setLabelTransparency(LabelTransparency transparency); - LabelTransparency labelTransparency(); - - // Enable or disable background grid - void setGridEnabled(bool enable); - bool gridEnabled(); - - // Enable or disable background mesh - void setBackgroundEnabled(bool enable); - bool backgroundEnabled(); - - // Adjust shadow quality - void setShadowQuality(ShadowQuality quality); - ShadowQuality shadowQuality(); - - // Adjust shadow quality - void setShadow(DeclarativeBars::ShadowQuality quality); - DeclarativeBars::ShadowQuality shadow(); - - protected: - QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); - -}; - -// TODO: If we use texture node, our rendering is done into a texture that is then drawn to the -// qquickwindow -> selection will not work -class DeclarativeBarsRenderer : public QObject, public QSGSimpleTextureNode -{ - Q_OBJECT - -public: - DeclarativeBarsRenderer(QQuickWindow *window, Bars3dShared *shared); - ~DeclarativeBarsRenderer(); - -public slots: - void render(); - -private: - QOpenGLFramebufferObject *m_fbo; - QSGTexture *m_texture; - QQuickWindow *m_window; - Bars3dShared *m_barsRenderer; -}; - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE -QTENTERPRISE_DATAVIS3D_USE_NAMESPACE - -#endif diff --git a/src/datavis3dqml2/declarativebars_p.h b/src/datavis3dqml2/declarativebars_p.h index 62dcc708..07dc21d4 100644 --- a/src/datavis3dqml2/declarativebars_p.h +++ b/src/datavis3dqml2/declarativebars_p.h @@ -1,41 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ @@ -43,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an +// This file is not part of the QtDataVis3D API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // @@ -52,45 +29,178 @@ #ifndef DECLARATIVEBARS_P_H #define DECLARATIVEBARS_P_H -#include "QtDataVis3D/qdatavis3dglobal.h" -#include "QtDataVis3D/qdatavis3namespace.h" -#include <QString> +#include "datavis3dglobal_p.h" +#include "bars3dcontroller_p.h" +#include "declarativebars_p.h" +#include "qitemmodelbardatamapping.h" +#include "qvalueaxis.h" +#include "qcategoryaxis.h" -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +#include <QAbstractItemModel> +#include <QQuickItem> +#include <QObject> +#include <QQuickWindow> -class QDataRow; +QT_DATAVIS3D_BEGIN_NAMESPACE -class DeclarativeBarsCachedStatePrivate +class DeclarativeBars : public QQuickItem { + Q_OBJECT + Q_PROPERTY(QAbstractItemModel *data READ data WRITE setData) + Q_PROPERTY(QItemModelBarDataMapping *mapping READ mapping WRITE setMapping) + Q_PROPERTY(QCategoryAxis *axisX READ axisX WRITE setAxisX) + Q_PROPERTY(QValueAxis *axisY READ axisY WRITE setAxisY) + Q_PROPERTY(QCategoryAxis *axisZ READ axisZ WRITE setAxisZ) + Q_PROPERTY(QtDataVis3D::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + Q_PROPERTY(QtDataVis3D::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) + Q_PROPERTY(QtDataVis3D::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) + Q_PROPERTY(QtDataVis3D::QDataVis::MeshStyle barType READ barType WRITE setBarType) + Q_PROPERTY(QtDataVis3D::QDataVis::CameraPreset cameraPreset READ cameraPreset WRITE setCameraPreset) + Q_PROPERTY(QtDataVis3D::QDataVis::ColorTheme theme READ theme WRITE setTheme) + Q_PROPERTY(QSizeF barThickness READ barThickness WRITE setBarThickness) + Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing) + Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative) + Q_PROPERTY(bool barSmooth READ barSmooth WRITE setBarSmooth) + Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) + Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) + Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) + Q_PROPERTY(int rows READ rows WRITE setRows) + Q_PROPERTY(int columns READ columns WRITE setColumns) + Q_ENUMS(QtDataVis3D::QDataVis::SelectionMode) + Q_ENUMS(QtDataVis3D::QDataVis::ShadowQuality) + Q_ENUMS(QtDataVis3D::QDataVis::LabelTransparency) + Q_ENUMS(QtDataVis3D::QDataVis::MeshStyle) + Q_ENUMS(QtDataVis3D::QDataVis::CameraPreset) + Q_ENUMS(QtDataVis3D::QDataVis::ColorTheme) + public: - explicit DeclarativeBarsCachedStatePrivate(); - ~DeclarativeBarsCachedStatePrivate(); + explicit DeclarativeBars(QQuickItem *parent = 0); + ~DeclarativeBars(); + + void classBegin(); + void componentComplete(); + + // how many samples per row and column + Q_INVOKABLE void setupSampleSpace(int rowCount, int columnCount); + + // Set color if you don't want to use themes. Set uniform to false if you want the (height) + // color to change from bottom to top + Q_INVOKABLE void setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, + bool uniform = true); + + // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and + // vertical (0...90) (or (-90...90) if there are negative values) angles and distance in + // percentage (10...500)) + Q_INVOKABLE void setCameraPosition(qreal horizontal, qreal vertical, int distance); + + // Add whole data set. + void setData(QAbstractItemModel *data); + QAbstractItemModel *data(); + + QItemModelBarDataMapping *mapping() const; + void setMapping(QItemModelBarDataMapping *mapping); + + QCategoryAxis *axisX() const; + void setAxisX(QCategoryAxis *axis); + QValueAxis *axisY() const; + void setAxisY(QValueAxis *axis); + QCategoryAxis *axisZ() const; + void setAxisZ(QCategoryAxis *axis); + + // Set bar thickness. Y -component sets the thickness of z -direction. + void setBarThickness(QSizeF thickness); + QSizeF barThickness(); + + // Set spacing between bars. Y -component sets the spacing of z -direction. + // If spacing is relative, 0.0f means side-to-side and 1.0f = one thickness in between. + void setBarSpacing(QSizeF spacing); + QSizeF barSpacing(); + + // Set bar spacing relative to thickness or absolute + void setBarSpacingRelative(bool relative); + bool isBarSpacingRelative(); + + // Bar type + void setBarType(QDataVis::MeshStyle style); + QDataVis::MeshStyle barType(); + + // Bar smoothing + void setBarSmooth(bool smooth); + bool barSmooth(); + + // override object type with own mesh + void setMeshFileName(const QString &objFileName); + QString meshFileName(); + + // Select preset camera placement + void setCameraPreset(QDataVis::CameraPreset preset); + QDataVis::CameraPreset cameraPreset(); + + // Set theme (object colors, shaders, window color, background colors, light intensity and text + // colors are affected) + void setTheme(QDataVis::ColorTheme theme); + QDataVis::ColorTheme theme(); + + // Change selection mode; single bar, bar and row, bar and column, or all + void setSelectionMode(QDataVis::SelectionMode mode); + QDataVis::SelectionMode selectionMode(); + + // Font size adjustment + void setFontSize(float fontsize); + float fontSize(); + + // Set font + void setFont(const QFont &font); + QFont font(); + + // Label transparency adjustment + void setLabelTransparency(QDataVis::LabelTransparency transparency); + QDataVis::LabelTransparency labelTransparency(); + + // Enable or disable background grid + void setGridVisible(bool visible); + bool isGridVisible(); + + // Enable or disable background mesh + void setBackgroundVisible(bool visible); + bool isBackgroundVisible(); + + // Adjust shadow quality + void setShadowQuality(QDataVis::ShadowQuality quality); + QDataVis::ShadowQuality shadowQuality(); + + int rows() const; + void setRows(int rows); - bool m_isSampleSpaceSet; - int m_cachedState; - int m_samplesRow; - int m_samplesColumn; - QString m_labelRow; - QString m_labelColumn; - QString m_labelHeight; + int columns() const; + void setColumns(int columns); - QDataRow *m_dataRow; +public slots: + // Used to detect when shadow quality changes autonomously due to e.g. resizing. + void handleShadowQualityUpdate(QDataVis::ShadowQuality quality); - bool m_isSelectionModeSet; - SelectionMode m_selectionMode; +signals: + // Signals shadow quality changes. + void shadowQualityChanged(QDataVis::ShadowQuality quality); - bool m_isLabelTransparencySet; - LabelTransparency m_labelTransparency; +protected: + Bars3dController *m_shared; - bool m_isShadowQualitySet; - ShadowQuality m_shadowQuality; + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); - bool m_isGridSet; - bool m_isGridEnabled; +private: + QSize m_initialisedSize; + QDataVis::CameraPreset m_cameraPreset; + QDataVis::ColorTheme m_theme; }; -QTENTERPRISE_DATAVIS3D_END_NAMESPACE -QTENTERPRISE_DATAVIS3D_USE_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE -#endif // DECLARATIVEBARS_P_H +#endif diff --git a/src/datavis3dqml2/declarativebarsrenderer.cpp b/src/datavis3dqml2/declarativebarsrenderer.cpp new file mode 100644 index 00000000..1ecd4003 --- /dev/null +++ b/src/datavis3dqml2/declarativebarsrenderer.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "declarativebarsrenderer_p.h" + +#include <QtQuick/QQuickWindow> +#include <QtGui/QOpenGLFramebufferObject> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +DeclarativeBarsRenderer::DeclarativeBarsRenderer(QQuickWindow *window, Bars3dController *renderer) + : m_fbo(0), + m_texture(0), + m_window(window), + m_barsRenderer(renderer) +{ + connect(m_window, SIGNAL(beforeSynchronizing()), this, SLOT(synchDataToRenderer()), Qt::DirectConnection); + connect(m_window, SIGNAL(beforeRendering()), this, SLOT(renderFBO()), Qt::DirectConnection); +} + +DeclarativeBarsRenderer::~DeclarativeBarsRenderer() +{ + delete m_texture; + delete m_fbo; +} + +void DeclarativeBarsRenderer::synchDataToRenderer() +{ + m_barsRenderer->initializeOpenGL(); + m_barsRenderer->synchDataToRenderer(); +} + +void DeclarativeBarsRenderer::renderFBO() +{ + QSize size = rect().size().toSize(); + + // Create FBO + if (!m_fbo) { + QOpenGLFramebufferObjectFormat format; + format.setAttachment(QOpenGLFramebufferObject::Depth); + m_fbo = new QOpenGLFramebufferObject(size, format); + m_texture = m_window->createTextureFromId(m_fbo->texture(), size); + + setTexture(m_texture); + + // Flip texture + // TODO: Can be gotten rid of once support for texture flipping becomes available (in Qt5.2) + QSize ts = m_texture->textureSize(); + QRectF sourceRect(0, 0, ts.width(), ts.height()); + float tmp = sourceRect.top(); + sourceRect.setTop(sourceRect.bottom()); + sourceRect.setBottom(tmp); + QSGGeometry *geometry = this->geometry(); + QSGGeometry::updateTexturedRectGeometry(geometry, rect(), + m_texture->convertToNormalizedSourceRect(sourceRect)); + markDirty(DirtyMaterial); + //qDebug() << "create node" << m_fbo->handle() << m_texture->textureId() << m_fbo->size(); + } + + // Call the shared rendering function + m_fbo->bind(); + + m_barsRenderer->render(m_fbo->handle()); + + m_fbo->release(); + + // New view is in the FBO, request repaint of scene graph + m_window->update(); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativebarsrenderer_p.h b/src/datavis3dqml2/declarativebarsrenderer_p.h new file mode 100644 index 00000000..1b40d3df --- /dev/null +++ b/src/datavis3dqml2/declarativebarsrenderer_p.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 DECLARATIVEBARSRENDERER_H +#define DECLARATIVEBARSRENDERER_H + +#include "datavis3dglobal_p.h" +#include "bars3dcontroller_p.h" +#include <qsgsimpletexturenode.h> + +class QOpenGLFramebufferObject; +class QSGTexture; +class QQuickWindow; + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class DeclarativeBarsRenderer : public QObject, public QSGSimpleTextureNode +{ + Q_OBJECT + +public: + DeclarativeBarsRenderer(QQuickWindow *window, Bars3dController *shared); + ~DeclarativeBarsRenderer(); + +public slots: + // Used to synch up data model from controller to renderer while main thread is locked + void synchDataToRenderer(); + // Renders view to FBO before render cycle starts. + void renderFBO(); + +private: + QOpenGLFramebufferObject *m_fbo; + QSGTexture *m_texture; + QQuickWindow *m_window; + Bars3dController *m_barsRenderer; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3dqml2/declarativemaps.cpp b/src/datavis3dqml2/declarativemaps.cpp index a5bb2318..7be239f2 100644 --- a/src/datavis3dqml2/declarativemaps.cpp +++ b/src/datavis3dqml2/declarativemaps.cpp @@ -1,86 +1,229 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** ** This file is part of the QtDataVis3D module. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ -#include "declarativemaps.h" - -#include <QDebug> +#include "declarativemaps_p.h" +#include "declarativemapsrenderer_p.h" +#include "qitemmodelmapdataproxy.h" -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVIS3D_BEGIN_NAMESPACE -DeclarativeMaps::DeclarativeMaps() +DeclarativeMaps::DeclarativeMaps(QQuickItem *parent) + : QQuickItem(parent), + m_shared(0), + m_initializedSize(0, 0) { + setFlags(QQuickItem::ItemHasContents); + setAcceptedMouseButtons(Qt::AllButtons); + + // TODO: These seem to have no effect; find a way to activate anti-aliasing + setAntialiasing(true); + setSmooth(true); } DeclarativeMaps::~DeclarativeMaps() { + delete m_shared; +} + +void DeclarativeMaps::classBegin() +{ + qDebug() << "classBegin"; +} + +void DeclarativeMaps::componentComplete() +{ + qDebug() << "componentComplete"; +} + +QSGNode *DeclarativeMaps::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + if (!m_shared) { + m_shared = new Maps3DController(boundingRect().toRect()); + m_shared->setDataProxy(new QItemModelMapDataProxy); + m_shared->initializeOpenGL(); + } + + // If old node exists and has right size, reuse it. + if (oldNode && m_initializedSize == boundingRect().size().toSize()) { + // Update bounding rectangle (that has same size as before). + static_cast<DeclarativeMapsRenderer *>( oldNode )->setRect(boundingRect()); + return oldNode; + } + + // Create a new render node when size changes or if there is no node yet + m_initializedSize = boundingRect().size().toSize(); + + // Delete old node + if (oldNode) + delete oldNode; + + // Create a new one and set it's bounding rectangle + DeclarativeMapsRenderer *node = new DeclarativeMapsRenderer(window(), m_shared); + node->setRect(boundingRect()); + m_shared->setBoundingRect(boundingRect().toRect()); + return node; +} + +void DeclarativeMaps::setData(QAbstractItemModel *data) +{ + static_cast<QItemModelMapDataProxy *>(m_shared->dataProxy())->setItemModel(data); +} + +QAbstractItemModel *DeclarativeMaps::data() +{ + return static_cast<QItemModelMapDataProxy *>(m_shared->dataProxy())->itemModel(); +} + +void DeclarativeMaps::setBarSpecs(const QVector3D &thickness, + Q3DMaps::AdjustmentDirection direction) +{ + m_shared->setBarSpecs(thickness, direction); +} + +void DeclarativeMaps::setBarType(QDataVis::MeshStyle style, bool smooth) +{ + m_shared->setBarType(style, smooth); +} + +void DeclarativeMaps::setMeshFileName(const QString &objFileName) +{ + m_shared->setMeshFileName(objFileName); +} + +void DeclarativeMaps::setCameraPreset(QDataVis::CameraPreset preset) +{ + m_shared->setCameraPreset(preset); +} + +void DeclarativeMaps::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) +{ + m_shared->setCameraPosition(horizontal, vertical, distance); +} + +void DeclarativeMaps::setTheme(QDataVis::ColorTheme theme) +{ + m_shared->setTheme(theme); +} + +void DeclarativeMaps::setBarColor(QColor baseColor, QColor heightColor, bool uniform) +{ + m_shared->setBarColor(baseColor, heightColor, uniform); +} + +void DeclarativeMaps::setAreaSpecs(const QRect &areaRect, const QImage &image) +{ + m_shared->setAreaSpecs(areaRect, image); +} + +void DeclarativeMaps::setImage(const QImage &image) +{ + m_shared->setImage(image); +} + +void DeclarativeMaps::setImage(const QString &imageUrl) +{ + m_shared->setImage(QImage(imageUrl)); +} + +void DeclarativeMaps::setSelectionMode(QDataVis::SelectionMode mode) +{ + m_shared->setSelectionMode(mode); +} + +QDataVis::SelectionMode DeclarativeMaps::selectionMode() +{ + return m_shared->selectionMode(); +} + +void DeclarativeMaps::setFontSize(float fontsize) +{ + m_shared->setFontSize(fontsize); +} + +float DeclarativeMaps::fontSize() +{ + return m_shared->fontSize(); +} + +void DeclarativeMaps::setFont(const QFont &font) +{ + m_shared->setFont(font); +} + +QFont DeclarativeMaps::font() +{ + return m_shared->font(); +} + +void DeclarativeMaps::setLabelTransparency(QDataVis::LabelTransparency transparency) +{ + m_shared->setLabelTransparency(transparency); +} + +QDataVis::LabelTransparency DeclarativeMaps::labelTransparency() +{ + return m_shared->labelTransparency(); +} + +void DeclarativeMaps::setShadowQuality(QDataVis::ShadowQuality quality) +{ + m_shared->setShadowQuality(quality); +} + +QDataVis::ShadowQuality DeclarativeMaps::shadowQuality() +{ + return m_shared->shadowQuality(); } -void DeclarativeMaps::setSelMode(DeclarativeMaps::SelectionMode mode) +QItemModelMapDataMapping *DeclarativeMaps::mapping() const { - setSelectionMode(QtDataVis3D::SelectionMode(mode)); + return static_cast<QItemModelMapDataProxy *>(m_shared->dataProxy())->mapping(); } -DeclarativeMaps::SelectionMode DeclarativeMaps::selMode() +void DeclarativeMaps::setMapping(QItemModelMapDataMapping *mapping) { - return DeclarativeMaps::SelectionMode(selectionMode()); + static_cast<QItemModelMapDataProxy *>(m_shared->dataProxy())->setMapping(mapping); } -void DeclarativeMaps::setTransparency(DeclarativeMaps::LabelTransparency transparency) +void DeclarativeMaps::mousePressEvent(QMouseEvent *event) { - setLabelTransparency(QtDataVis3D::LabelTransparency(transparency)); + QPoint mousePos = event->pos(); + //mousePos.setY(height() - mousePos.y()); + m_shared->mousePressEvent(event, mousePos); } -DeclarativeMaps::LabelTransparency DeclarativeMaps::transparency() +void DeclarativeMaps::mouseReleaseEvent(QMouseEvent *event) { - return DeclarativeMaps::LabelTransparency(labelTransparency()); + QPoint mousePos = event->pos(); + //mousePos.setY(height() - mousePos.y()); + m_shared->mouseReleaseEvent(event, mousePos); } -void DeclarativeMaps::setShadow(DeclarativeMaps::ShadowQuality quality) +void DeclarativeMaps::mouseMoveEvent(QMouseEvent *event) { - setShadowQuality(QtDataVis3D::ShadowQuality(quality)); + QPoint mousePos = event->pos(); + //mousePos.setY(height() - mousePos.y()); + m_shared->mouseMoveEvent(event, mousePos); } -DeclarativeMaps::ShadowQuality DeclarativeMaps::shadow() +void DeclarativeMaps::wheelEvent(QWheelEvent *event) { - return DeclarativeMaps::ShadowQuality(shadowQuality()); + m_shared->wheelEvent(event); } -QTENTERPRISE_DATAVIS3D_END_NAMESPACE +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativemaps.h b/src/datavis3dqml2/declarativemaps.h deleted file mode 100644 index aef00c76..00000000 --- a/src/datavis3dqml2/declarativemaps.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtDataVis3D module. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef DECLARATIVEMAPS_H -#define DECLARATIVEMAPS_H - -#include "QtDataVis3D/qdatavis3dglobal.h" -#include "QtDataVis3D/qdatavis3namespace.h" -#include "q3dmaps.h" - -QTENTERPRISE_DATAVIS3D_BEGIN_NAMESPACE - -class DeclarativeMaps : public Q3DMaps -{ - Q_OBJECT - Q_PROPERTY(SelectionMode selectionMode READ selMode WRITE setSelMode) - Q_PROPERTY(LabelTransparency labelTransparency READ transparency WRITE setTransparency) - Q_PROPERTY(ShadowQuality shadowQuality READ shadow WRITE setShadow) - Q_ENUMS(SelectionMode) - Q_ENUMS(ShadowQuality) - Q_ENUMS(LabelTransparency) - -public: - // Duplicated here to be able to use the same enums - enum SelectionMode { - ModeNone = 0, - ModeBar, - ModeBarAndRow, - ModeBarAndColumn, - ModeBarRowAndColumn, - ModeZoomRow, - ModeZoomColumn - }; - - enum ShadowQuality { - ShadowNone = 0, - ShadowLow = 1, - ShadowMedium = 3, - ShadowHigh = 5 - }; - - enum LabelTransparency { - TransparencyNone = 0, // Full solid, using colors from theme - TransparencyFromTheme, // Use colors and transparencies from theme - TransparencyNoBackground // Draw just text on transparent background - }; - -public: - explicit DeclarativeMaps(); - ~DeclarativeMaps(); - - // Change selection mode; single bar, bar and row, bar and column, or all - void setSelMode(DeclarativeMaps::SelectionMode mode); - DeclarativeMaps::SelectionMode selMode(); - - // Label transparency adjustment - void setTransparency(DeclarativeMaps::LabelTransparency transparency); - DeclarativeMaps::LabelTransparency transparency(); - - // Adjust shadow quality - void setShadow(DeclarativeMaps::ShadowQuality quality); - DeclarativeMaps::ShadowQuality shadow(); -}; - -QTENTERPRISE_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3dqml2/declarativemaps_p.h b/src/datavis3dqml2/declarativemaps_p.h new file mode 100644 index 00000000..ba2da0b3 --- /dev/null +++ b/src/datavis3dqml2/declarativemaps_p.h @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// +// +// This file is not part of the QtDataVis3D 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 DECLARATIVEMAPS_P_H +#define DECLARATIVEMAPS_P_H + +#include "datavis3dglobal_p.h" +#include "maps3dcontroller_p.h" +#include "declarativemaps_p.h" +#include "qitemmodelmapdatamapping.h" + +#include <QAbstractItemModel> +#include <QQuickItem> +#include <QObject> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class DeclarativeMaps : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QAbstractItemModel *data READ data WRITE setData) + Q_PROPERTY(QtDataVis3D::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + Q_PROPERTY(QtDataVis3D::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) + Q_PROPERTY(QtDataVis3D::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) + Q_PROPERTY(QItemModelMapDataMapping *mapping READ mapping WRITE setMapping) + Q_ENUMS(QtDataVis3D::QDataVis::SelectionMode) + Q_ENUMS(QtDataVis3D::QDataVis::ShadowQuality) + Q_ENUMS(QtDataVis3D::QDataVis::LabelTransparency) + +public: + explicit DeclarativeMaps(QQuickItem *parent = 0); + ~DeclarativeMaps(); + + void classBegin(); + void componentComplete(); + + void setData(QAbstractItemModel *data); + QAbstractItemModel *data(); + + // bar specifications; base thickness in x, y and z, enum to indicate which direction is increased with value + // TODO: Start using thickness also in adjustment direction; use it as a relative value. + // For example, in AdjustAll mode setting thickness to (0.1f, 1.0f, 0.5f) would apply value to + // x at 10%, y at 100% and z at 50%. If a dimension is not included, given thickness states its absolute value. + Q_INVOKABLE void setBarSpecs(const QVector3D &thickness = QVector3D(1.0f, 1.0f, 1.0f), + Q3DMaps::AdjustmentDirection direction = Q3DMaps::AdjustHeight); + + // bar type; bars (=cubes), pyramids, cones, cylinders, balls, etc. + Q_INVOKABLE void setBarType(QDataVis::MeshStyle style, bool smooth = false); + + // override bar type with own mesh + Q_INVOKABLE void setMeshFileName(const QString &objFileName); + + // Select preset camera placement + Q_INVOKABLE void setCameraPreset(QDataVis::CameraPreset preset); + + // Set camera rotation if you don't want to use the presets (in horizontal (180...180) and + // vertical (0...90) angles and distance in percentage (10...500)) + Q_INVOKABLE void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); + + // Set theme (bar colors, shaders, window color, background colors, light intensity and text colors are affected) + Q_INVOKABLE void setTheme(QDataVis::ColorTheme theme); + + // Set color if you don't want to use themes. Set uniform to false if you want the (height) color to change from bottom to top + Q_INVOKABLE void setBarColor(QColor baseColor, QColor heightColor, bool uniform = true); + + // Set area specs + Q_INVOKABLE void setAreaSpecs(const QRect &areaRect, const QImage &image); + + // Set area image + Q_INVOKABLE void setImage(const QImage &image); + Q_INVOKABLE void setImage(const QString &imageUrl); + + // Change selection mode; single bar, bar and row, bar and column, or all + void setSelectionMode(QDataVis::SelectionMode mode); + QDataVis::SelectionMode selectionMode(); + + // Font size adjustment + void setFontSize(float fontsize); + float fontSize(); + + // Set font + void setFont(const QFont &font); + QFont font(); + + // Label transparency adjustment + void setLabelTransparency(QDataVis::LabelTransparency transparency); + QDataVis::LabelTransparency labelTransparency(); + + // Adjust shadow quality + void setShadowQuality(QDataVis::ShadowQuality quality); + QDataVis::ShadowQuality shadowQuality(); + + QItemModelMapDataMapping *mapping() const; + void setMapping(QItemModelMapDataMapping *mapping); + +protected: + Maps3DController *m_shared; + + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); + + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + +private: + QSize m_initializedSize; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3dqml2/declarativemapsrenderer.cpp b/src/datavis3dqml2/declarativemapsrenderer.cpp new file mode 100644 index 00000000..6e8dc2db --- /dev/null +++ b/src/datavis3dqml2/declarativemapsrenderer.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "declarativemapsrenderer_p.h" + +#include <QtQuick/QQuickWindow> +#include <QtGui/QOpenGLFramebufferObject> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +DeclarativeMapsRenderer::DeclarativeMapsRenderer(QQuickWindow *window, Maps3DController *renderer) + : m_fbo(0), + m_texture(0), + m_window(window), + m_mapsRenderer(renderer) +{ + connect(m_window, SIGNAL(beforeRendering()), this, SLOT(render()), Qt::DirectConnection); +} + +DeclarativeMapsRenderer::~DeclarativeMapsRenderer() +{ + delete m_texture; + delete m_fbo; +} + +void DeclarativeMapsRenderer::render() +{ + QSize size = rect().size().toSize(); + + // Create FBO + if (!m_fbo) { + QOpenGLFramebufferObjectFormat format; + format.setAttachment(QOpenGLFramebufferObject::Depth); + m_fbo = new QOpenGLFramebufferObject(size, format); + m_texture = m_window->createTextureFromId(m_fbo->texture(), size); + + setTexture(m_texture); + + // Flip texture + // TODO: Can be gotten rid of once support for texture flipping becomes available (in Qt5.2) + QSize ts = m_texture->textureSize(); + QRectF sourceRect(0, 0, ts.width(), ts.height()); + float tmp = sourceRect.top(); + sourceRect.setTop(sourceRect.bottom()); + sourceRect.setBottom(tmp); + QSGGeometry *geometry = this->geometry(); + QSGGeometry::updateTexturedRectGeometry(geometry, rect(), + m_texture->convertToNormalizedSourceRect(sourceRect)); + markDirty(DirtyMaterial); + //qDebug() << "create node" << m_fbo->handle() << m_texture->textureId() << m_fbo->size(); + } + + // Call the shared rendering function + m_fbo->bind(); + + m_mapsRenderer->render(m_fbo->handle()); + + m_fbo->release(); + + // New view is in the FBO, request repaint of scene graph + m_window->update(); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativemapsrenderer_p.h b/src/datavis3dqml2/declarativemapsrenderer_p.h new file mode 100644 index 00000000..755764c9 --- /dev/null +++ b/src/datavis3dqml2/declarativemapsrenderer_p.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 DECLARATIVEMAPSRENDERER_P_H +#define DECLARATIVEMAPSRENDERER_P_H + +#include "datavis3dglobal_p.h" +#include "maps3dcontroller_p.h" +#include <qsgsimpletexturenode.h> + +class QOpenGLFramebufferObject; +class QSGTexture; +class QQuickWindow; + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class DeclarativeMapsRenderer : public QObject, public QSGSimpleTextureNode +{ + Q_OBJECT + +public: + DeclarativeMapsRenderer(QQuickWindow *window, Maps3DController *shared); + ~DeclarativeMapsRenderer(); + +public slots: + void render(); + +private: + QOpenGLFramebufferObject *m_fbo; + QSGTexture *m_texture; + QQuickWindow *m_window; + Maps3DController *m_mapsRenderer; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3dqml2/declarativescatter.cpp b/src/datavis3dqml2/declarativescatter.cpp new file mode 100644 index 00000000..90daf0e3 --- /dev/null +++ b/src/datavis3dqml2/declarativescatter.cpp @@ -0,0 +1,328 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "declarativescatter_p.h" +#include "declarativescatterrenderer_p.h" +#include "qitemmodelscatterdataproxy.h" + +QT_DATAVIS3D_BEGIN_NAMESPACE + +const QString smoothString(QStringLiteral("Smooth")); + +DeclarativeScatter::DeclarativeScatter(QQuickItem *parent) + : QQuickItem(parent), + m_shared(0), + m_initialisedSize(0, 0), + m_cameraPreset(QDataVis::NoPreset), + m_theme(QDataVis::ThemeDefault) +{ + setFlags(QQuickItem::ItemHasContents); + setAcceptedMouseButtons(Qt::AllButtons); + + // TODO: These seem to have no effect; find a way to activate anti-aliasing + setAntialiasing(true); + setSmooth(true); + + // Create the shared component on the main GUI thread. + m_shared = new Scatter3DController(boundingRect().toRect()); + QObject::connect(m_shared, &Scatter3DController::shadowQualityChanged, this, + &DeclarativeScatter::handleShadowQualityUpdate); + + m_shared->setDataProxy(new QItemModelScatterDataProxy); +} + +DeclarativeScatter::~DeclarativeScatter() +{ + delete m_shared; +} + +void DeclarativeScatter::handleShadowQualityUpdate(QDataVis::ShadowQuality quality) +{ + emit shadowQualityChanged(quality); +} + +void DeclarativeScatter::classBegin() +{ + qDebug() << "classBegin"; +} + +void DeclarativeScatter::componentComplete() +{ + qDebug() << "componentComplete"; +} + +QSGNode *DeclarativeScatter::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + // If old node exists and has right size, reuse it. + if (oldNode && m_initialisedSize == boundingRect().size().toSize()) { + // Update bounding rectangle (that has same size as before). + static_cast<DeclarativeScatterRenderer *>( oldNode )->setRect(boundingRect()); + return oldNode; + } + + // Create a new render node when size changes or if there is no node yet + m_initialisedSize = boundingRect().size().toSize(); + + // Delete old node + if (oldNode) + delete oldNode; + + // Create a new one and set it's bounding rectangle + DeclarativeScatterRenderer *node = new DeclarativeScatterRenderer(window(), m_shared); + node->setRect(boundingRect()); + m_shared->setBoundingRect(boundingRect().toRect()); + return node; +} + +void DeclarativeScatter::setCameraPosition(qreal horizontal, qreal vertical, int distance) +{ + m_shared->setCameraPosition(GLfloat(horizontal), GLfloat(vertical), GLint(distance)); +} + +void DeclarativeScatter::setObjectColor(QColor baseColor, QColor heightColor, QColor depthColor, + bool uniform) +{ + m_shared->setObjectColor(baseColor, heightColor, depthColor, uniform); +} + +void DeclarativeScatter::setData(QAbstractItemModel *data) +{ + static_cast<QItemModelScatterDataProxy *>(m_shared->dataProxy())->setItemModel(data); +} + +QAbstractItemModel *DeclarativeScatter::data() +{ + return static_cast<QItemModelScatterDataProxy *>(m_shared->dataProxy())->itemModel(); +} + +void DeclarativeScatter::setMapping(QItemModelScatterDataMapping *mapping) +{ + static_cast<QItemModelScatterDataProxy *>(m_shared->dataProxy())->setMapping(mapping); +} + +QItemModelScatterDataMapping *DeclarativeScatter::mapping() const +{ + return static_cast<QItemModelScatterDataProxy *>(m_shared->dataProxy())->mapping(); +} + +QValueAxis *DeclarativeScatter::axisX() const +{ + return static_cast<QValueAxis *>(m_shared->axisX()); +} + +void DeclarativeScatter::setAxisX(QValueAxis *axis) +{ + m_shared->setAxisX(axis); +} + +QValueAxis *DeclarativeScatter::axisY() const +{ + return static_cast<QValueAxis *>(m_shared->axisY()); +} + +void DeclarativeScatter::setAxisY(QValueAxis *axis) +{ + m_shared->setAxisY(axis); +} + +QValueAxis *DeclarativeScatter::axisZ() const +{ + return static_cast<QValueAxis *>(m_shared->axisZ()); +} + +void DeclarativeScatter::setAxisZ(QValueAxis *axis) +{ + m_shared->setAxisZ(axis); +} + +void DeclarativeScatter::setObjectType(QDataVis::MeshStyle style) +{ + QString objFile = m_shared->meshFileName(); + bool smooth = objFile.endsWith(smoothString); + m_shared->setObjectType(style, smooth); +} + +QDataVis::MeshStyle DeclarativeScatter::objectType() +{ + QString objFile = m_shared->meshFileName(); + if (objFile.contains("/sphere")) + return QDataVis::Spheres; + else + return QDataVis::Dots; +} + +void DeclarativeScatter::setObjectSmooth(bool smooth) +{ + QString objFile = m_shared->meshFileName(); + if (objFile.endsWith(smoothString)) { + if (smooth) + return; // Already smooth; do nothing + else // Rip Smooth off the end + objFile.resize(objFile.indexOf(smoothString)); + } else { + if (!smooth) // Already flat; do nothing + return; + else // Append Smooth to the end + objFile.append(smoothString); + } + m_shared->setMeshFileName(objFile); +} + +bool DeclarativeScatter::objectSmooth() +{ + QString objFile = m_shared->meshFileName(); + return objFile.endsWith(smoothString); +} + +void DeclarativeScatter::setMeshFileName(const QString &objFileName) +{ + m_shared->setMeshFileName(objFileName); +} + +QString DeclarativeScatter::meshFileName() +{ + return m_shared->meshFileName(); +} + +void DeclarativeScatter::setCameraPreset(QDataVis::CameraPreset preset) +{ + // TODO: Implement correctly once "improved camera api" (QTRD-2122) is implemented + // We need to save this locally, as there are no getters for it in controller + m_cameraPreset = preset; + m_shared->setCameraPreset(preset); +} + +QDataVis::CameraPreset DeclarativeScatter::cameraPreset() +{ + return m_cameraPreset; +} + +void DeclarativeScatter::setTheme(QDataVis::ColorTheme theme) +{ + // TODO: Implement correctly once "user-modifiable themes" (QTRD-2120) is implemented + // We need to save this locally, as there are no getters for it in controller + m_theme = theme; + m_shared->setColorTheme(theme); + + // TODO: Investigate why the beforeSynchronizing() signal requires update and is not sent automatically when this value changes, + // but is sent wen e.g. enable/disable background changes. + update(); +} + +QDataVis::ColorTheme DeclarativeScatter::theme() +{ + return m_theme; +} + +void DeclarativeScatter::setFontSize(float fontsize) +{ + m_shared->setFontSize(fontsize); +} + +float DeclarativeScatter::fontSize() +{ + return m_shared->fontSize(); +} + +void DeclarativeScatter::setFont(const QFont &font) +{ + m_shared->setFont(font); +} + +QFont DeclarativeScatter::font() +{ + return m_shared->font(); +} + +void DeclarativeScatter::setLabelTransparency(QDataVis::LabelTransparency transparency) +{ + m_shared->setLabelTransparency(transparency); +} + +QDataVis::LabelTransparency DeclarativeScatter::labelTransparency() +{ + return m_shared->labelTransparency(); +} + +void DeclarativeScatter::setGridVisible(bool visible) +{ + m_shared->setGridEnabled(visible); +} + +bool DeclarativeScatter::isGridVisible() +{ + return m_shared->gridEnabled(); +} + +void DeclarativeScatter::setBackgroundVisible(bool visible) +{ + m_shared->setBackgroundEnabled(visible); +} + +bool DeclarativeScatter::isBackgroundVisible() +{ + return m_shared->backgroundEnabled(); +} + +void DeclarativeScatter::setSelectionMode(QDataVis::SelectionMode mode) +{ + m_shared->setSelectionMode(mode); +} + +QDataVis::SelectionMode DeclarativeScatter::selectionMode() +{ + return m_shared->selectionMode(); +} + +void DeclarativeScatter::setShadowQuality(QDataVis::ShadowQuality quality) +{ + m_shared->setShadowQuality(quality); +} + +QDataVis::ShadowQuality DeclarativeScatter::shadowQuality() +{ + return m_shared->shadowQuality(); +} + +void DeclarativeScatter::mousePressEvent(QMouseEvent *event) +{ + QPoint mousePos = event->pos(); + //mousePos.setY(height() - mousePos.y()); + m_shared->mousePressEvent(event, mousePos); +} + +void DeclarativeScatter::mouseReleaseEvent(QMouseEvent *event) +{ + QPoint mousePos = event->pos(); + //mousePos.setY(height() - mousePos.y()); + m_shared->mouseReleaseEvent(event, mousePos); +} + +void DeclarativeScatter::mouseMoveEvent(QMouseEvent *event) +{ + QPoint mousePos = event->pos(); + //mousePos.setY(height() - mousePos.y()); + m_shared->mouseMoveEvent(event, mousePos); +} + +void DeclarativeScatter::wheelEvent(QWheelEvent *event) +{ + m_shared->wheelEvent(event); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativescatter_p.h b/src/datavis3dqml2/declarativescatter_p.h new file mode 100644 index 00000000..dce5c021 --- /dev/null +++ b/src/datavis3dqml2/declarativescatter_p.h @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 "datavis3dglobal_p.h" +#include "scatter3dcontroller_p.h" +#include "declarativescatter_p.h" +#include "qitemmodelscatterdatamapping.h" +#include "qvalueaxis.h" + +#include <QAbstractItemModel> +#include <QQuickItem> +#include <QObject> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class DeclarativeScatter : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QAbstractItemModel *data READ data WRITE setData) + Q_PROPERTY(QItemModelScatterDataMapping *mapping READ mapping WRITE setMapping) + Q_PROPERTY(QValueAxis *axisX READ axisX WRITE setAxisX) + Q_PROPERTY(QValueAxis *axisY READ axisY WRITE setAxisY) + Q_PROPERTY(QValueAxis *axisZ READ axisZ WRITE setAxisZ) + Q_PROPERTY(QtDataVis3D::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + Q_PROPERTY(QtDataVis3D::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) + Q_PROPERTY(QtDataVis3D::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) + Q_PROPERTY(QtDataVis3D::QDataVis::MeshStyle objectType READ objectType WRITE setObjectType) + Q_PROPERTY(QtDataVis3D::QDataVis::CameraPreset cameraPreset READ cameraPreset WRITE setCameraPreset) + Q_PROPERTY(QtDataVis3D::QDataVis::ColorTheme theme READ theme WRITE setTheme) + Q_PROPERTY(bool objectSmooth READ objectSmooth WRITE setObjectSmooth) + Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) + Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) + Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) + Q_ENUMS(QtDataVis3D::QDataVis::SelectionMode) + Q_ENUMS(QtDataVis3D::QDataVis::ShadowQuality) + Q_ENUMS(QtDataVis3D::QDataVis::LabelTransparency) + Q_ENUMS(QtDataVis3D::QDataVis::MeshStyle) + Q_ENUMS(QtDataVis3D::QDataVis::CameraPreset) + Q_ENUMS(QtDataVis3D::QDataVis::ColorTheme) + +public: + explicit DeclarativeScatter(QQuickItem *parent = 0); + ~DeclarativeScatter(); + + void classBegin(); + void componentComplete(); + + // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and + // vertical (-90...90) angles and distance in percentage (10...500)) + Q_INVOKABLE void setCameraPosition(qreal horizontal, qreal vertical, int distance); + + // Set color if you don't want to use themes. Set uniform to false if you want the (height) + // color to change from bottom to top + Q_INVOKABLE void setObjectColor(QColor baseColor, QColor heightColor, QColor depthColor, + bool uniform = true); + + // Add whole data set. + void setData(QAbstractItemModel *data); + QAbstractItemModel *data(); + + QItemModelScatterDataMapping *mapping() const; + void setMapping(QItemModelScatterDataMapping *mapping); + + QValueAxis *axisX() const; + void setAxisX(QValueAxis *axis); + QValueAxis *axisY() const; + void setAxisY(QValueAxis *axis); + QValueAxis *axisZ() const; + void setAxisZ(QValueAxis *axis); + + // Object type + void setObjectType(QDataVis::MeshStyle style); + QDataVis::MeshStyle objectType(); + + // Object smoothing + void setObjectSmooth(bool smooth); + bool objectSmooth(); + + // override object type with own mesh + void setMeshFileName(const QString &objFileName); + QString meshFileName(); + + // Select preset camera placement + void setCameraPreset(QDataVis::CameraPreset preset); + QDataVis::CameraPreset cameraPreset(); + + // Set theme (object colors, shaders, window color, background colors, light intensity and text + // colors are affected) + void setTheme(QDataVis::ColorTheme theme); + QDataVis::ColorTheme theme(); + + // Change selection mode + void setSelectionMode(QDataVis::SelectionMode mode); + QDataVis::SelectionMode selectionMode(); + + // Font size adjustment + void setFontSize(float fontsize); + float fontSize(); + + // Set font + void setFont(const QFont &font); + QFont font(); + + // Label transparency adjustment + void setLabelTransparency(QDataVis::LabelTransparency transparency); + QDataVis::LabelTransparency labelTransparency(); + + // Enable or disable background grid + void setGridVisible(bool visible); + bool isGridVisible(); + + // Enable or disable background mesh + void setBackgroundVisible(bool visible); + bool isBackgroundVisible(); + + // Adjust shadow quality + void setShadowQuality(QDataVis::ShadowQuality quality); + QDataVis::ShadowQuality shadowQuality(); + +public slots: + // Used to detect when shadow quality changes autonomously due to e.g. resizing. + void handleShadowQualityUpdate(QDataVis::ShadowQuality quality); + +signals: + // Signals shadow quality changes. + void shadowQualityChanged(QDataVis::ShadowQuality quality); + +protected: + Scatter3DController *m_shared; + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); + + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + +private: + QSize m_initialisedSize; + QDataVis::CameraPreset m_cameraPreset; + QDataVis::ColorTheme m_theme; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3dqml2/declarativescatterrenderer.cpp b/src/datavis3dqml2/declarativescatterrenderer.cpp new file mode 100644 index 00000000..23c59c26 --- /dev/null +++ b/src/datavis3dqml2/declarativescatterrenderer.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "declarativescatterrenderer_p.h" + +#include <QtQuick/QQuickWindow> +#include <QtGui/QOpenGLFramebufferObject> + +QT_DATAVIS3D_BEGIN_NAMESPACE + +DeclarativeScatterRenderer::DeclarativeScatterRenderer(QQuickWindow *window, + Scatter3DController *renderer) + : m_fbo(0), + m_texture(0), + m_window(window), + m_scatterRenderer(renderer) +{ + connect(m_window, SIGNAL(beforeSynchronizing()), this, SLOT(synchDataToRenderer()), Qt::DirectConnection); + connect(m_window, SIGNAL(beforeRendering()), this, SLOT(renderFBO()), Qt::DirectConnection); +} + +DeclarativeScatterRenderer::~DeclarativeScatterRenderer() +{ + delete m_texture; + delete m_fbo; +} + +void DeclarativeScatterRenderer::synchDataToRenderer() +{ + m_scatterRenderer->initializeOpenGL(); + m_scatterRenderer->synchDataToRenderer(); +} + +void DeclarativeScatterRenderer::renderFBO() +{ + QSize size = rect().size().toSize(); + + // Create FBO + if (!m_fbo) { + QOpenGLFramebufferObjectFormat format; + format.setAttachment(QOpenGLFramebufferObject::Depth); + m_fbo = new QOpenGLFramebufferObject(size, format); + m_texture = m_window->createTextureFromId(m_fbo->texture(), size); + + setTexture(m_texture); + + // Flip texture + // TODO: Can be gotten rid of once support for texture flipping becomes available (in Qt5.2) + QSize ts = m_texture->textureSize(); + QRectF sourceRect(0, 0, ts.width(), ts.height()); + float tmp = sourceRect.top(); + sourceRect.setTop(sourceRect.bottom()); + sourceRect.setBottom(tmp); + QSGGeometry *geometry = this->geometry(); + QSGGeometry::updateTexturedRectGeometry(geometry, rect(), + m_texture->convertToNormalizedSourceRect(sourceRect)); + markDirty(DirtyMaterial); + //qDebug() << "create node" << m_fbo->handle() << m_texture->textureId() << m_fbo->size(); + } + + // Call the shared rendering function + m_fbo->bind(); + + m_scatterRenderer->render(m_fbo->handle()); + + m_fbo->release(); + + // New view is in the FBO, request repaint of scene graph + m_window->update(); +} + +QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativescatterrenderer_p.h b/src/datavis3dqml2/declarativescatterrenderer_p.h new file mode 100644 index 00000000..498b1d83 --- /dev/null +++ b/src/datavis3dqml2/declarativescatterrenderer_p.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D 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 DECLARATIVESCATTERRENDERER_P_H +#define DECLARATIVESCATTERRENDERER_P_H + +#include "datavis3dglobal_p.h" +#include "scatter3dcontroller_p.h" +#include <qsgsimpletexturenode.h> + +class QOpenGLFramebufferObject; +class QSGTexture; +class QQuickWindow; + +QT_DATAVIS3D_BEGIN_NAMESPACE + +class DeclarativeScatterRenderer : public QObject, public QSGSimpleTextureNode +{ + Q_OBJECT + +public: + DeclarativeScatterRenderer(QQuickWindow *window, Scatter3DController *shared); + ~DeclarativeScatterRenderer(); + +public slots: + // Used to synch up data model from controller to renderer while main thread is locked + void synchDataToRenderer(); + // Renders view to FBO before render cycle starts. + void renderFBO(); + +private: + QOpenGLFramebufferObject *m_fbo; + QSGTexture *m_texture; + QQuickWindow *m_window; + Scatter3DController *m_scatterRenderer; +}; + +QT_DATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/src.pro b/src/src.pro index d25722eb..171f9fde 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs SUBDIRS += datavis3d \ - datavis3dqml2 + datavis3dqml2 |