diff options
author | Tomi Korpipaa <tomi.korpipaa@qt.io> | 2023-02-09 13:54:07 +0200 |
---|---|---|
committer | Tomi Korpipaa <tomi.korpipaa@qt.io> | 2023-02-23 11:22:54 +0200 |
commit | 00272ac80843d94217e4f1ea36392e22919afa22 (patch) | |
tree | f6befa6852760e8edd0ffe26546f719964c14647 /examples | |
parent | 351a282e8ed94d697ba4b43302249e7894d0e1a9 (diff) |
Combine 2 widget examples into graph gallery
Combine the 2 bar graph examples into graph gallery example.
Note: surface and scatter examples will be combined into graph gallery
in other commits, to avoid making one gigantic commit.
Pick-to: 6.5
Task-number: QTBUG-110698
Change-Id: Iadf32e4e4d13c06325c89cf9259393d0b9fbda0e
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
Diffstat (limited to 'examples')
29 files changed, 832 insertions, 847 deletions
diff --git a/examples/datavisualization/CMakeLists.txt b/examples/datavisualization/CMakeLists.txt index 3022d14f..b4c0bb46 100644 --- a/examples/datavisualization/CMakeLists.txt +++ b/examples/datavisualization/CMakeLists.txt @@ -8,8 +8,7 @@ if(TARGET Qt::Quick) qt_internal_add_example(qmlsurfacegallery) endif() if(NOT ANDROID AND NOT IOS AND NOT WINRT) - qt_internal_add_example(bars) - qt_internal_add_example(customproxy) + qt_internal_add_example(graphgallery) qt_internal_add_example(scatter) qt_internal_add_example(surface) qt_internal_add_example(draggableaxes) diff --git a/examples/datavisualization/bars/CMakeLists.txt b/examples/datavisualization/bars/CMakeLists.txt deleted file mode 100644 index 1b7ddbae..00000000 --- a/examples/datavisualization/bars/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(bars LANGUAGES CXX) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) -set(CMAKE_AUTOUIC ON) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}") - -find_package(Qt6 COMPONENTS Core) -find_package(Qt6 COMPONENTS Quick) -find_package(Qt6 COMPONENTS Gui) -find_package(Qt6 COMPONENTS Widgets) -find_package(Qt6 COMPONENTS DataVisualization) - -qt_add_executable(bars - graphmodifier.cpp graphmodifier.h - main.cpp -) -set_target_properties(bars PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) -target_link_libraries(bars PUBLIC - Qt::Core - Qt::Gui - Qt::Widgets - Qt::DataVisualization -) - -install(TARGETS bars - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/datavisualization/bars/bars.pro b/examples/datavisualization/bars/bars.pro deleted file mode 100644 index 148fc66e..00000000 --- a/examples/datavisualization/bars/bars.pro +++ /dev/null @@ -1,17 +0,0 @@ -android|ios|winrt { - error( "This example is not supported for android, ios, or winrt." ) -} - -!include( ../examples.pri ) { - error( "Couldn't find the examples.pri file!" ) -} - -SOURCES += main.cpp graphmodifier.cpp -HEADERS += graphmodifier.h - -QT += widgets -requires(qtConfig(fontcombobox)) -requires(qtConfig(combobox)) - -OTHER_FILES += doc/src/* \ - doc/images/* diff --git a/examples/datavisualization/bars/doc/images/bars-example.png b/examples/datavisualization/bars/doc/images/bars-example.png Binary files differdeleted file mode 100644 index c06fe2c1..00000000 --- a/examples/datavisualization/bars/doc/images/bars-example.png +++ /dev/null diff --git a/examples/datavisualization/bars/doc/src/bars.qdoc b/examples/datavisualization/bars/doc/src/bars.qdoc deleted file mode 100644 index b3cb8df8..00000000 --- a/examples/datavisualization/bars/doc/src/bars.qdoc +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example bars - \meta tags {DataVisualization, Q3DBars} - \meta category {Graphics} - \title Bar Graph - \ingroup qtdatavisualization_examples - \brief Using Q3DBars in a widget application. - - The bars example shows how to make a 3D bar graph using Q3DBars and combining the use of - widgets for adjusting several adjustable qualities. The example shows how to: - - \list - \li Create an application with Q3DBars and some widgets - \li Use QBar3DSeries and QBarDataProxy to set data to the graph - \li Adjust some graph and series properties using widget controls - \li Select a row or a column by clicking an axis label - \endlist - - It also demonstrates how having negative bar values affects the graph. - - For instructions about how to interact with the graph, see \l{Qt Data Visualization Interacting with Data}{this page}. - - \image bars-example.png - - \include examples-run.qdocinc - - \section1 Creating the Application - - First, in main.cpp, we create a QApplication, instantiate Q3DBars and a window container - for it: - - \snippet bars/main.cpp 0 - - The call to QWidget::createWindowContainer is required, as all data visualization graph classes - (Q3DBars, Q3DScatter, Q3DSurface) inherit QWindow. Any class inheriting QWindow cannot be used - as a widget any other way. - - Then we'll create horizontal and vertical layouts. We'll add the graph and the vertical - layout into the horizontal one: - - \snippet bars/main.cpp 1 - - We're not using the vertical layout for anything yet, but we'll get back to it in - \l {Using widgets to control the graph} - - Next, let's create another class to handle the data addition and other interaction with the - graph. Let's call it \c GraphModifier (See \l {Setting up the graph} and - \l {Adding data to the graph} for details): - - \snippet bars/main.cpp 2 - - The application main is done and we can show the graph and start the event loop: - - \snippet bars/main.cpp 3 - - \section1 Setting up the Graph - - Let's set up the graph in the constructor of the \c GraphModifier class we instantiated in the - application main: - - \snippet bars/graphmodifier.cpp 0 - - Let's take a closer look at parts of the code. - - First we're creating the axes and the series into member variables to support changing them - easily later on, if we want to: - - \snippet bars/graphmodifier.cpp 1 - - Then we're setting some of the visual qualities for the graph: - - \snippet bars/graphmodifier.cpp 2 - - We're also setting up the axes and setting them to the graph as active axes: - - \snippet bars/graphmodifier.cpp 3 - - We give axis labels a small autorotation angle to make them orient somewhat toward the - camera. This is done to improve axis label readability at extreme camera angles. - - Next we initialize the visual properties of the series. - Note that the second series is initially not visible: - - \snippet bars/graphmodifier.cpp 8 - - The series need to be added to the graph to show them: - - \snippet bars/graphmodifier.cpp 4 - - Finally, we set the camera angle by calling the same method the camera angle change button - in the UI uses to cycle through various camera angles: - - \snippet bars/graphmodifier.cpp 6 - - There you can see that the camera is controlled via the scene object of the graph: - - \snippet bars/graphmodifier.cpp 10 - - For more information about using scene and cameras, see Q3DScene and Q3DCamera. - - That concludes setting up the graph. - - \section1 Adding Data to the Graph - - At the end of the constructor there's a call: - - \snippet bars/graphmodifier.cpp 9 - - This method is used to add data to the proxies of the two series: - - \snippet bars/graphmodifier.cpp 5 - - Now the series have data to show. - - \section1 Using Widgets to Control the Graph - - There isn't much interaction yet, so let's continue by adding some widgets back in the - application main. Let's just focus on two as an example: - - \snippet bars/main.cpp 4 - - We can use these slider widgets to rotate the graph instead of just using the mouse or - touch. - - Let's add them to the vertical layout we created earlier: - - \snippet bars/main.cpp 5 - - Then we'll connect them to methods in \c GraphModifier: - - \snippet bars/main.cpp 6 - - Here are the methods in \c GraphModifier the signals were connected to. The camera - is controlled via the scene object. This time we specify the actual camera position - along the orbit around the center point, instead of specifying a preset camera angle: - - \snippet bars/graphmodifier.cpp 7 - - Now these two sliders can be used to rotate the graph. - - And so we have an application in which we can control: - - \list - \li Graph rotation - \li Label style - \li Camera preset - \li Background visibility - \li Grid visibility - \li Bar shading smoothness - \li Visibility of the second bar series - \li Value axis direction - \li Axis title visibility and rotation - \li Data range to be shown - \li Bar style - \li Selection mode - \li Theme - \li Shadow quality - \li Font - \li Font size - \li Axis label rotation - \endlist - - \section1 Selecting a Row/column by Clicking an Axis Label - - Selection by axis label is default functionality for bar graphs. As an example, you can select - rows by clicking an axis label in the following way: - - \list - \li Change selection mode to \c SelectionRow - \li Click a year label - \li The row with the clicked year is selected - \endlist - - You can use the same method with \c SelectionSlice and \c SelectionItem flags, as long as - you have either \c SelectionRow or \c SelectionColumn set as well. - - \section1 Zooming to Selection - - As an example of adjusting camera target we have implemented an animation of zooming to - selection via a button press. Animation initializations are done in the constructor: - - \snippet bars/graphmodifier.cpp 12 - - The function \c{GraphModifier::zoomToSelectedBar()} contains the rest of the functionality: - - \snippet bars/graphmodifier.cpp 11 - - The QPropertyAnimation \c m_animationCameraTarget targets Q3DCamera::target property, - which takes a value normalized to the range (-1, 1). We figure out where the selected bar - is relative to axes, and use that as the end value for \c{m_animationCameraTarget}: - - \snippet bars/graphmodifier.cpp 13 - \dots - \snippet bars/graphmodifier.cpp 14 - - Likewise, we want to angle the camera so that it always points approximately to the center of - the graph at the end of the animation: - - \snippet bars/graphmodifier.cpp 15 - - \section1 Example Contents - -*/ diff --git a/examples/datavisualization/customproxy/data/raindata.txt b/examples/datavisualization/customproxy/data/raindata.txt deleted file mode 100644 index 531d66be..00000000 --- a/examples/datavisualization/customproxy/data/raindata.txt +++ /dev/null @@ -1,158 +0,0 @@ -# Rainfall per month from 2000 to 2012 in Northern Finland (Sodankylä, Utsjoki, Kuusamo) -# Format: year, month, rainfall -2000,1, 72, -2000,2, 47, -2000,3, 37, -2000,4, 79, -2000,5, 42, -2000,6, 73, -2000,7, 94, -2000,8, 37, -2000,9, 17, -2000,10,69, -2000,11,42, -2000,12,42, -2001,1, 25, -2001,2, 47, -2001,3, 20, -2001,4, 70, -2001,5, 27, -2001,6, 40, -2001,7, 123, -2001,8, 39, -2001,9, 66, -2001,10,55, -2001,11,29, -2001,12,12, -2002,1, 24, -2002,2, 45, -2002,3, 27, -2002,4, 30, -2002,5, 16, -2002,6, 98, -2002,7, 122, -2002,8, 20, -2002,9, 50, -2002,10,24, -2002,11,22, -2002,12,12, -2003,1, 43, -2003,2, 17, -2003,3, 26, -2003,4, 22, -2003,5, 60, -2003,6, 14, -2003,7, 86, -2003,8, 77, -2003,9, 69, -2003,10,49, -2003,11,23, -2003,12,44, -2004,1, 15, -2004,2, 19, -2004,3, 10, -2004,4, 11, -2004,5, 41, -2004,6, 29, -2004,7, 49, -2004,8, 72, -2004,9, 50, -2004,10,18, -2004,11,19, -2004,12,40, -2005,1, 60, -2005,2, 24, -2005,3, 12, -2005,4, 50, -2005,5, 88, -2005,6, 32, -2005,7, 76, -2005,8, 55, -2005,9, 92, -2005,10,35, -2005,11,105, -2005,12,59, -2006,1, 27, -2006,2, 18, -2006,3, 17, -2006,4, 26, -2006,5, 24, -2006,6, 18, -2006,7, 35, -2006,8, 28, -2006,9, 80, -2006,10,52, -2006,11,43, -2006,12,44, -2007,1, 41, -2007,2, 21, -2007,3, 30, -2007,4, 20, -2007,5, 53, -2007,6, 29, -2007,7, 139, -2007,8, 52, -2007,9, 51, -2007,10,24, -2007,11,47, -2007,12,33, -2008,1, 67, -2008,2, 19, -2008,3, 30, -2008,4, 31, -2008,5, 29, -2008,6, 79, -2008,7, 75, -2008,8, 99, -2008,9, 34, -2008,10,52, -2008,11,60, -2008,12,20, -2009,1, 9, -2009,2, 22, -2009,3, 11, -2009,4, 10, -2009,5, 69, -2009,6, 30, -2009,7, 78, -2009,8, 93, -2009,9, 70, -2009,10,32, -2009,11,56, -2009,12,23, -2010,1, 12, -2010,2, 28, -2010,3, 55, -2010,4, 20, -2010,5, 65, -2010,6, 26, -2010,7, 134, -2010,8, 57, -2010,9, 51, -2010,10,53, -2010,11,8, -2010,12,9, -2011,1, 34, -2011,2, 20, -2011,3, 30, -2011,4, 31, -2011,5, 42, -2011,6, 78, -2011,7, 85, -2011,8, 33, -2011,9, 42, -2011,10,87, -2011,11,41, -2011,12,72, -2012,1, 32, -2012,2, 42, -2012,3, 30, -2012,4, 50, -2012,5, 30, -2012,6, 70, -2012,7, 52, -2012,8, 20, -2012,9, 99, -2012,10,70, -2012,11,69, -2012,12,49 diff --git a/examples/datavisualization/customproxy/doc/images/customproxy-example.png b/examples/datavisualization/customproxy/doc/images/customproxy-example.png Binary files differdeleted file mode 100644 index 4f82943a..00000000 --- a/examples/datavisualization/customproxy/doc/images/customproxy-example.png +++ /dev/null diff --git a/examples/datavisualization/customproxy/doc/src/customproxy.qdoc b/examples/datavisualization/customproxy/doc/src/customproxy.qdoc deleted file mode 100644 index 42cd2768..00000000 --- a/examples/datavisualization/customproxy/doc/src/customproxy.qdoc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example customproxy - \meta tags {DataVisualization, Q3DBars, Bar Graph} - \meta category {Graphics} - \title Data from Custom Proxy - \ingroup qtdatavisualization_examples - \brief Using Q3DBars with a custom proxy. - - The custom proxy example shows how to create a custom proxy to use with Q3DBars. - - \image customproxy-example.png - - This example describes how to use a custom dataset and the corresponding proxy. For more - information about basic Q3DBars functionality, see the \l{Bar Graph} example. - - This example defines a simple flexible data set \c VariantDataSet where each data item is a - a variant list. Each item can have multiple different values, identified by their index in - the list. In this example, the data set is storing monthly rainfall data, where the value in - index zero is the year, the value in index one is the month, and the value in index two is - the amount of rainfall in that month. - - The custom proxy we provide here is similar to item model based proxies provided by Qt - Data Visualization in that it requires a mapping to interpret the data. - - \include examples-run.qdocinc - - \section1 VariantDataSet - - \c VariantDataSet class provides a simple API: - - \snippet customproxy/variantdataset.h 1 - \dots 0 - \codeline - \snippet customproxy/variantdataset.h 0 - - As you can see, the data items are simply QVariantList objects, and the data can be added either - singly or in lists. The only additional functionality provided is clearing the data set and querying - for a reference to the data contained in the set. Signals are emitted when data is added or the set - is cleared. - - \section1 VariantBarDataProxy - - \c VariantBarDataProxy is a subclass of QBarDataProxy and provides a simple API of just getters - and setters for the data set and the mapping: - - \snippet customproxy/variantbardataproxy.h 0 - \dots 0 - \codeline - \snippet customproxy/variantbardataproxy.h 1 - - On the implementation side, the proxy listens for the changes in the data set and the mapping, - and resolves the data set if any changes are detected. It is not particularly efficient - implementation in that any change will cause re-resolving of the entire data set, but that is not - an issue for this example. The interesting part is the \c resolveDataSet() method: - - \snippet customproxy/variantbardataproxy.cpp 0 - - In \c resolveDataSet() method we sort the variant data values into rows and columns based on the - mapping. This is very similar to how QItemModelBarDataProxy handles mapping, except we use - list indexes instead of item model roles here. Once the values are sorted, we generate \c QBarDataArray - out of them, and call \c resetArray() method on the parent class. - - \section1 VariantBarDataMapping - - \c VariantBarDataMapping stores the mapping information between \c VariantDataSet data item indexes - and rows, columns, and values of \c QBarDataArray. It also contains the lists of rows and columns to - be included in the resolved data: - - \snippet customproxy/variantbardatamapping.h 0 - \dots 0 - \codeline - \snippet customproxy/variantbardatamapping.h 1 - \dots 0 - \codeline - \snippet customproxy/variantbardatamapping.h 2 - \dots 0 - \codeline - \snippet customproxy/variantbardatamapping.h 3 - - The primary way to use a \c VariantBarDataMapping object is to give the mappings already at the - constructor, though they can be set later individually or all together with the \c remap() method. - A signal is emitted if mapping changes. It is basically a simplified version of the mapping - functionality of QItemModelBarDataProxy adapted to work with variant lists instead of item models. - - \section1 RainfallGraph - - \c RainfallGraph class handles the setup of the graph. The interesting part is the \c addDataSet() - method: - - \snippet customproxy/rainfallgraph.cpp 0 - - The bulk of that method is used for populating the variant data set. Once the set is populated, - visualizing the data is trivial with the help of our custom proxy: - - \snippet customproxy/rainfallgraph.cpp 1 -*/ diff --git a/examples/datavisualization/customproxy/main.cpp b/examples/datavisualization/customproxy/main.cpp deleted file mode 100644 index 9ca74d3b..00000000 --- a/examples/datavisualization/customproxy/main.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -#include "rainfallgraph.h" -#include <QtGui/QGuiApplication> - -int main(int argc, char **argv) -{ - qputenv("QSG_RHI_BACKEND", "opengl"); - QGuiApplication app(argc, argv); - - Q3DBars *rainfall = new Q3DBars; - - if (!rainfall->hasContext()) { - qWarning() << QStringLiteral("Couldn't initialize the OpenGL context.") ; - return -1; - } - - rainfall->setFlags(rainfall->flags() ^ Qt::FramelessWindowHint); - rainfall->resize(1000, 800); - rainfall->setPosition(QPoint(10, 30)); - rainfall->show(); - - RainfallGraph rainfallgraph(rainfall); - rainfallgraph.start(); - - return app.exec(); -} diff --git a/examples/datavisualization/customproxy/rainfallgraph.h b/examples/datavisualization/customproxy/rainfallgraph.h deleted file mode 100644 index 62a1f67c..00000000 --- a/examples/datavisualization/customproxy/rainfallgraph.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -#ifndef RAINFALLGRAPH_H -#define RAINFALLGRAPH_H - -#include "variantbardataproxy.h" -#include <QtDataVisualization/q3dbars.h> - -class RainfallGraph : public QObject -{ - Q_OBJECT -public: - explicit RainfallGraph(Q3DBars *rainfall); - ~RainfallGraph(); - - void addDataSet(); - void start(); - -private: - - void updateYearsList(int start, int end); - Q3DBars *m_graph; - int m_columnCount; - int m_rowCount; - QStringList m_years; - QStringList m_numericMonths; - VariantBarDataProxy *m_proxy; - VariantBarDataMapping *m_mapping; - VariantDataSet *m_dataSet; -}; - - -#endif diff --git a/examples/datavisualization/datavisualization.pro b/examples/datavisualization/datavisualization.pro index 194b4860..1cf117f3 100644 --- a/examples/datavisualization/datavisualization.pro +++ b/examples/datavisualization/datavisualization.pro @@ -7,9 +7,7 @@ qtHaveModule(quick) { } !android:!ios:!winrt { - SUBDIRS += bars \ - customproxy \ - scatter \ + SUBDIRS += scatter \ surface \ draggableaxes \ customitems \ diff --git a/examples/datavisualization/customproxy/CMakeLists.txt b/examples/datavisualization/graphgallery/CMakeLists.txt index a87653c0..9a53ece6 100644 --- a/examples/datavisualization/customproxy/CMakeLists.txt +++ b/examples/datavisualization/graphgallery/CMakeLists.txt @@ -1,8 +1,8 @@ -# Copyright (C) 2022 The Qt Company Ltd. +# Copyright (C) 2023 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause cmake_minimum_required(VERSION 3.16) -project(customproxy LANGUAGES CXX) +project(graphgallery LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -18,37 +18,41 @@ set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}") find_package(Qt6 COMPONENTS Core) find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) find_package(Qt6 COMPONENTS DataVisualization) -qt_add_executable(customproxy +qt_add_executable(graphgallery main.cpp - rainfallgraph.cpp rainfallgraph.h + bargraph.cpp bargraph.h + graphmodifier.cpp graphmodifier.h + rainfalldata.cpp rainfalldata.h variantbardatamapping.cpp variantbardatamapping.h variantbardataproxy.cpp variantbardataproxy.h variantdataset.cpp variantdataset.h ) -set_target_properties(customproxy PROPERTIES +set_target_properties(graphgallery PROPERTIES WIN32_EXECUTABLE TRUE MACOSX_BUNDLE TRUE ) -target_link_libraries(customproxy PUBLIC +target_link_libraries(graphgallery PUBLIC Qt::Core Qt::Gui + Qt::Widgets Qt::DataVisualization ) -set(customproxy_resource_files +set(graphgallery_resource_files "data/raindata.txt" ) -qt6_add_resources(customproxy "customproxy" +qt6_add_resources(graphgallery "graphgallery" PREFIX "/" FILES - ${customproxy_resource_files} + ${graphgallery_resource_files} ) -install(TARGETS customproxy +install(TARGETS graphgallery RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" diff --git a/examples/datavisualization/bars/main.cpp b/examples/datavisualization/graphgallery/bargraph.cpp index 69e7e8a7..b8d450f9 100644 --- a/examples/datavisualization/bars/main.cpp +++ b/examples/datavisualization/graphgallery/bargraph.cpp @@ -1,54 +1,60 @@ -// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "bargraph.h" #include "graphmodifier.h" -#include <QtWidgets/QApplication> -#include <QtWidgets/QWidget> -#include <QtWidgets/QHBoxLayout> -#include <QtWidgets/QVBoxLayout> -#include <QtWidgets/QPushButton> -#include <QtWidgets/QCheckBox> -#include <QtWidgets/QSlider> -#include <QtWidgets/QFontComboBox> -#include <QtWidgets/QLabel> -#include <QtWidgets/QMessageBox> -#include <QtGui/QScreen> -#include <QtGui/QFontDatabase> - -int main(int argc, char **argv) +#include <QtWidgets/qboxlayout.h> +#include <QtWidgets/qpushbutton.h> +#include <QtWidgets/qcheckbox.h> +#include <QtWidgets/qslider.h> +#include <QtWidgets/qfontcombobox.h> +#include <QtWidgets/qlabel.h> +#include <QtWidgets/qmessagebox.h> +#include <QtWidgets/qradiobutton.h> +#include <QtWidgets/qbuttongroup.h> +#include <QtGui/qfontdatabase.h> + +BarGraph::BarGraph() { - qputenv("QSG_RHI_BACKEND", "opengl"); //! [0] - QApplication app(argc, argv); - Q3DBars *widgetgraph = new Q3DBars(); - QWidget *container = QWidget::createWindowContainer(widgetgraph); + m_barsGraph = new Q3DBars(); + m_container = QWidget::createWindowContainer(m_barsGraph); //! [0] +} - if (!widgetgraph->hasContext()) { +BarGraph::~BarGraph() +{ + delete m_container; +} + +bool BarGraph::initialize() +{ + if (!m_barsGraph->hasContext()) { QMessageBox msgBox; msgBox.setText("Couldn't initialize the OpenGL context."); msgBox.exec(); - return -1; + return false; } - QSize screenSize = widgetgraph->screen()->size(); - container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 1.5)); - container->setMaximumSize(screenSize); - container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - container->setFocusPolicy(Qt::StrongFocus); + QSize screenSize = m_barsGraph->screen()->size(); + m_container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 1.5)); + m_container->setMaximumSize(screenSize); + m_container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_container->setFocusPolicy(Qt::StrongFocus); //! [1] - QWidget *widget = new QWidget; - QHBoxLayout *hLayout = new QHBoxLayout(widget); + m_barsWidget = new QWidget; + QHBoxLayout *hLayout = new QHBoxLayout(m_barsWidget); QVBoxLayout *vLayout = new QVBoxLayout(); - hLayout->addWidget(container, 1); + hLayout->addWidget(m_container, 1); hLayout->addLayout(vLayout); //! [1] - widget->setWindowTitle(QStringLiteral("Average temperatures in Oulu and Helsinki, Finland (2015-2022)")); + // TODO: Add a label into the main widget to show the title of the current example? + //m_barsWidget->setWindowTitle(QStringLiteral("Average temperatures in Oulu and Helsinki, Finland (2015-2022)")); - QComboBox *themeList = new QComboBox(widget); + QComboBox *themeList = new QComboBox(m_barsWidget); themeList->addItem(QStringLiteral("Qt")); themeList->addItem(QStringLiteral("Primary Colors")); themeList->addItem(QStringLiteral("Digia")); @@ -59,15 +65,14 @@ int main(int argc, char **argv) themeList->addItem(QStringLiteral("Isabelle")); themeList->setCurrentIndex(0); - QPushButton *labelButton = new QPushButton(widget); + QPushButton *labelButton = new QPushButton(m_barsWidget); labelButton->setText(QStringLiteral("Change label style")); - QCheckBox *smoothCheckBox = new QCheckBox(widget); + QCheckBox *smoothCheckBox = new QCheckBox(m_barsWidget); smoothCheckBox->setText(QStringLiteral("Smooth bars")); smoothCheckBox->setChecked(false); - - QComboBox *barStyleList = new QComboBox(widget); + QComboBox *barStyleList = new QComboBox(m_barsWidget); barStyleList->addItem(QStringLiteral("Bar"), int(QAbstract3DSeries::MeshBar)); barStyleList->addItem(QStringLiteral("Pyramid"), int(QAbstract3DSeries::MeshPyramid)); barStyleList->addItem(QStringLiteral("Cone"), int(QAbstract3DSeries::MeshCone)); @@ -76,13 +81,13 @@ int main(int argc, char **argv) barStyleList->addItem(QStringLiteral("Sphere"), int(QAbstract3DSeries::MeshSphere)); barStyleList->setCurrentIndex(4); - QPushButton *cameraButton = new QPushButton(widget); + QPushButton *cameraButton = new QPushButton(m_barsWidget); cameraButton->setText(QStringLiteral("Change camera preset")); - QPushButton *zoomToSelectedButton = new QPushButton(widget); + QPushButton *zoomToSelectedButton = new QPushButton(m_barsWidget); zoomToSelectedButton->setText(QStringLiteral("Zoom to selected bar")); - QComboBox *selectionModeList = new QComboBox(widget); + QComboBox *selectionModeList = new QComboBox(m_barsWidget); selectionModeList->addItem(QStringLiteral("None"), int(QAbstract3DGraph::SelectionNone)); selectionModeList->addItem(QStringLiteral("Bar"), @@ -118,52 +123,52 @@ int main(int argc, char **argv) | QAbstract3DGraph::SelectionMultiSeries)); selectionModeList->setCurrentIndex(1); - QCheckBox *backgroundCheckBox = new QCheckBox(widget); + QCheckBox *backgroundCheckBox = new QCheckBox(m_barsWidget); backgroundCheckBox->setText(QStringLiteral("Show background")); backgroundCheckBox->setChecked(false); - QCheckBox *gridCheckBox = new QCheckBox(widget); + QCheckBox *gridCheckBox = new QCheckBox(m_barsWidget); gridCheckBox->setText(QStringLiteral("Show grid")); gridCheckBox->setChecked(true); - QCheckBox *seriesCheckBox = new QCheckBox(widget); + QCheckBox *seriesCheckBox = new QCheckBox(m_barsWidget); seriesCheckBox->setText(QStringLiteral("Show second series")); seriesCheckBox->setChecked(false); - QCheckBox *reverseValueAxisCheckBox = new QCheckBox(widget); + QCheckBox *reverseValueAxisCheckBox = new QCheckBox(m_barsWidget); reverseValueAxisCheckBox->setText(QStringLiteral("Reverse value axis")); reverseValueAxisCheckBox->setChecked(false); - QCheckBox *reflectionCheckBox = new QCheckBox(widget); + QCheckBox *reflectionCheckBox = new QCheckBox(m_barsWidget); reflectionCheckBox->setText(QStringLiteral("Show reflections")); reflectionCheckBox->setChecked(false); - //! [4] - QSlider *rotationSliderX = new QSlider(Qt::Horizontal, widget); + //! [3] + QSlider *rotationSliderX = new QSlider(Qt::Horizontal, m_barsWidget); rotationSliderX->setTickInterval(30); rotationSliderX->setTickPosition(QSlider::TicksBelow); rotationSliderX->setMinimum(-180); rotationSliderX->setValue(0); rotationSliderX->setMaximum(180); - QSlider *rotationSliderY = new QSlider(Qt::Horizontal, widget); + //! [3] + QSlider *rotationSliderY = new QSlider(Qt::Horizontal, m_barsWidget); rotationSliderY->setTickInterval(15); rotationSliderY->setTickPosition(QSlider::TicksAbove); rotationSliderY->setMinimum(-90); rotationSliderY->setValue(0); rotationSliderY->setMaximum(90); - //! [4] - QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, widget); + QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, m_barsWidget); fontSizeSlider->setTickInterval(10); fontSizeSlider->setTickPosition(QSlider::TicksBelow); fontSizeSlider->setMinimum(1); fontSizeSlider->setValue(30); fontSizeSlider->setMaximum(100); - QFontComboBox *fontList = new QFontComboBox(widget); + QFontComboBox *fontList = new QFontComboBox(m_barsWidget); fontList->setCurrentFont(QFont("Times New Roman")); - QComboBox *shadowQuality = new QComboBox(widget); + QComboBox *shadowQuality = new QComboBox(m_barsWidget); shadowQuality->addItem(QStringLiteral("None")); shadowQuality->addItem(QStringLiteral("Low")); shadowQuality->addItem(QStringLiteral("Medium")); @@ -173,7 +178,7 @@ int main(int argc, char **argv) shadowQuality->addItem(QStringLiteral("High Soft")); shadowQuality->setCurrentIndex(5); - QComboBox *rangeList = new QComboBox(widget); + QComboBox *rangeList = new QComboBox(m_barsWidget); rangeList->addItem(QStringLiteral("2015")); rangeList->addItem(QStringLiteral("2016")); rangeList->addItem(QStringLiteral("2017")); @@ -185,27 +190,34 @@ int main(int argc, char **argv) rangeList->addItem(QStringLiteral("All")); rangeList->setCurrentIndex(8); - QCheckBox *axisTitlesVisibleCB = new QCheckBox(widget); + QCheckBox *axisTitlesVisibleCB = new QCheckBox(m_barsWidget); axisTitlesVisibleCB->setText(QStringLiteral("Axis titles visible")); axisTitlesVisibleCB->setChecked(true); - QCheckBox *axisTitlesFixedCB = new QCheckBox(widget); + QCheckBox *axisTitlesFixedCB = new QCheckBox(m_barsWidget); axisTitlesFixedCB->setText(QStringLiteral("Axis titles fixed")); axisTitlesFixedCB->setChecked(true); - QSlider *axisLabelRotationSlider = new QSlider(Qt::Horizontal, widget); + QSlider *axisLabelRotationSlider = new QSlider(Qt::Horizontal, m_barsWidget); axisLabelRotationSlider->setTickInterval(10); axisLabelRotationSlider->setTickPosition(QSlider::TicksBelow); axisLabelRotationSlider->setMinimum(0); axisLabelRotationSlider->setValue(30); axisLabelRotationSlider->setMaximum(90); - //! [5] + QButtonGroup *modeGroup = new QButtonGroup(m_barsWidget); + QRadioButton *modeWeather = new QRadioButton(QStringLiteral("Temperature Data"), m_barsWidget); + modeWeather->setChecked(true); + QRadioButton *modeCustomProxy = new QRadioButton(QStringLiteral("Custom Proxy Data"), m_barsWidget); + modeGroup->addButton(modeWeather); + modeGroup->addButton(modeCustomProxy); + + //! [4] vLayout->addWidget(new QLabel(QStringLiteral("Rotate horizontally"))); vLayout->addWidget(rotationSliderX, 0, Qt::AlignTop); + //! [4] vLayout->addWidget(new QLabel(QStringLiteral("Rotate vertically"))); vLayout->addWidget(rotationSliderY, 0, Qt::AlignTop); - //! [5] vLayout->addWidget(labelButton, 0, Qt::AlignTop); vLayout->addWidget(cameraButton, 0, Qt::AlignTop); vLayout->addWidget(zoomToSelectedButton, 0, Qt::AlignTop); @@ -232,16 +244,18 @@ int main(int argc, char **argv) vLayout->addWidget(new QLabel(QStringLiteral("Adjust font size"))); vLayout->addWidget(fontSizeSlider); vLayout->addWidget(new QLabel(QStringLiteral("Axis label rotation"))); - vLayout->addWidget(axisLabelRotationSlider, 1, Qt::AlignTop); + vLayout->addWidget(axisLabelRotationSlider, 0, Qt::AlignTop); + vLayout->addWidget(modeWeather, 0, Qt::AlignTop); + vLayout->addWidget(modeCustomProxy, 1, Qt::AlignTop); //! [2] - GraphModifier *modifier = new GraphModifier(widgetgraph); + GraphModifier *modifier = new GraphModifier(m_barsGraph); //! [2] - //! [6] + //! [5] QObject::connect(rotationSliderX, &QSlider::valueChanged, modifier, &GraphModifier::rotateX); + //! [5] QObject::connect(rotationSliderY, &QSlider::valueChanged, modifier, &GraphModifier::rotateY); - //! [6] QObject::connect(labelButton, &QPushButton::clicked, modifier, &GraphModifier::changeLabelBackground); @@ -285,7 +299,7 @@ int main(int argc, char **argv) QObject::connect(modifier, &GraphModifier::shadowQualityChanged, shadowQuality, &QComboBox::setCurrentIndex); - QObject::connect(widgetgraph, &Q3DBars::shadowQualityChanged, modifier, + QObject::connect(m_barsGraph, &Q3DBars::shadowQualityChanged, modifier, &GraphModifier::shadowQualityUpdatedByVisual); QObject::connect(fontSizeSlider, &QSlider::valueChanged, modifier, @@ -304,8 +318,21 @@ int main(int argc, char **argv) &GraphModifier::setAxisTitleFixed); QObject::connect(axisLabelRotationSlider, &QSlider::valueChanged, modifier, &GraphModifier::changeLabelRotation); - //! [3] - widget->show(); - return app.exec(); - //! [3] + + QObject::connect(modeWeather, &QRadioButton::toggled, modifier, + &GraphModifier::setDataModeToWeather); + QObject::connect(modeCustomProxy, &QRadioButton::toggled, modifier, + &GraphModifier::setDataModeToCustom); + QObject::connect(modeWeather, &QRadioButton::toggled, seriesCheckBox, + &QCheckBox::setEnabled); + QObject::connect(modeWeather, &QRadioButton::toggled, rangeList, + &QComboBox::setEnabled); + QObject::connect(modeWeather, &QRadioButton::toggled, axisTitlesVisibleCB, + &QCheckBox::setEnabled); + QObject::connect(modeWeather, &QRadioButton::toggled, axisTitlesFixedCB, + &QCheckBox::setEnabled); + QObject::connect(modeWeather, &QRadioButton::toggled, axisLabelRotationSlider, + &QSlider::setEnabled); + + return true; } diff --git a/examples/datavisualization/graphgallery/bargraph.h b/examples/datavisualization/graphgallery/bargraph.h new file mode 100644 index 00000000..dae991f9 --- /dev/null +++ b/examples/datavisualization/graphgallery/bargraph.h @@ -0,0 +1,26 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef BARGRAPH_H +#define BARGRAPH_H + +#include <QtDataVisualization/q3dbars.h> +#include <QtCore/qobject.h> + +class BarGraph : public QObject +{ + Q_OBJECT +public: + explicit BarGraph(); + ~BarGraph(); + + bool initialize(); + QWidget *barsWidget() { return m_barsWidget; } + +private: + Q3DBars *m_barsGraph = nullptr; + QWidget *m_container = nullptr; + QWidget *m_barsWidget = nullptr; +}; + +#endif diff --git a/examples/datavisualization/graphgallery/data/raindata.txt b/examples/datavisualization/graphgallery/data/raindata.txt new file mode 100644 index 00000000..d9558921 --- /dev/null +++ b/examples/datavisualization/graphgallery/data/raindata.txt @@ -0,0 +1,158 @@ +# Rainfall per month from 2010 to 2022 in Northern Finland (Oulu) +# Format: year, month, rainfall +2010,1, 0, +2010,2, 3.4, +2010,3, 52, +2010,4, 33.8, +2010,5, 45.6, +2010,6, 43.8, +2010,7, 104.6, +2010,8, 105.4, +2010,9, 107.2, +2010,10,38.6, +2010,11,17.8, +2010,12,0, +2011,1, 8.2, +2011,2, 1.6, +2011,3, 27.4, +2011,4, 15.8, +2011,5, 57.6, +2011,6, 85.2, +2011,7, 127, +2011,8, 72.2, +2011,9, 82.2, +2011,10,62.4, +2011,11,31.6, +2011,12,53.8, +2012,1, 0, +2012,2, 5, +2012,3, 32.4, +2012,4, 57.6, +2012,5, 71.4, +2012,6, 60.8, +2012,7, 109, +2012,8, 43.6, +2012,9, 79.4, +2012,10,117.2, +2012,11,59, +2012,12,0.2, +2013,1, 28, +2013,2, 19, +2013,3, 0, +2013,4, 37.6, +2013,5, 44.2, +2013,6, 104.8, +2013,7, 84.2, +2013,8, 57.2, +2013,9, 37.2, +2013,10,64.6, +2013,11,77.8, +2013,12,92.8, +2014,1, 23.8, +2014,2, 23.6, +2014,3, 15.4, +2014,4, 13.2, +2014,5, 36.4, +2014,6, 26.4, +2014,7, 95.8, +2014,8, 81.8, +2014,9, 13.8, +2014,10,94.6, +2014,11,44.6, +2014,12,31, +2015,1, 37.4, +2015,2, 21, +2015,3, 42, +2015,4, 8.8, +2015,5, 82.4, +2015,6, 150, +2015,7, 56.8, +2015,8, 67.2, +2015,9, 131.2, +2015,10,38.4, +2015,11,83.4, +2015,12,47.8, +2016,1, 12.4, +2016,2, 34.8, +2016,3, 29, +2016,4, 40.4, +2016,5, 32.4, +2016,6, 80.2, +2016,7, 102.6, +2016,8, 95.6, +2016,9, 40.2, +2016,10,7.8, +2016,11,39.6, +2016,12,8.8, +2017,1, 9.4, +2017,2, 6.6, +2017,3, 29, +2017,4, 46.2, +2017,5, 43.2, +2017,6, 25.2, +2017,7, 72.4, +2017,8, 58.8, +2017,9, 68.8, +2017,10,45.8, +2017,11,36.8, +2017,12,29.6, +2018,1, 19.8, +2018,2, 0.8, +2018,3, 4, +2018,4, 23.2, +2018,5, 13.2, +2018,6, 62.8, +2018,7, 33, +2018,8, 96.6, +2018,9, 72.6, +2018,10,48.8, +2018,11,31.8, +2018,12,12.8, +2019,1, 0.2, +2019,2, 24.8, +2019,3, 32, +2019,4, 8.8, +2019,5, 71.4, +2019,6, 65.8, +2019,7, 17.6, +2019,8, 90, +2019,9, 50, +2019,10,77, +2019,11,27, +2019,12,43.2, +2020,1, 28.8, +2020,2, 45, +2020,3, 18.6, +2020,4, 13, +2020,5, 30.8, +2020,6, 21.4, +2020,7, 163.6, +2020,8, 12, +2020,9, 102.4, +2020,10,133.2, +2020,11,69.8, +2020,12,40.6, +2021,1, 0.4, +2021,2, 21.6, +2021,3, 24, +2021,4, 51.4, +2021,5, 76.4, +2021,6, 29.2, +2021,7, 36.4, +2021,8, 116, +2021,9, 72.4, +2021,10,93.4, +2021,11,21, +2021,12,10.2, +2022,1, 8.6, +2022,2, 6.6, +2022,3, 5.2, +2022,4, 15.2, +2022,5, 37.6, +2022,6, 45, +2022,7, 67.4, +2022,8, 161.6, +2022,9, 22.8, +2022,10,75.2, +2022,11,21.8, +2022,12,0.2 diff --git a/examples/datavisualization/graphgallery/doc/src/graphgallery.qdoc b/examples/datavisualization/graphgallery/doc/src/graphgallery.qdoc new file mode 100644 index 00000000..e2695592 --- /dev/null +++ b/examples/datavisualization/graphgallery/doc/src/graphgallery.qdoc @@ -0,0 +1,282 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \example graphgallery + \meta tags {DataVisualization, Q3DBars, Bar Graph, Custom Proxy} + \meta category {Graphics} + \title Graph Gallery + \ingroup qtdatavisualization_examples + \brief Gallery of Bar, Scatter, and Surface graphs. + + \e {Graph Gallery} demonstrates all three graph types and some of their special features. + The graphs have their own tabs in the application. + + \image qmlgraphgallery-example.png + + \include examples-run.qdocinc + + \section1 Bar Graph + + In the \uicontrol {Bar Graph} tab, create a 3D bar graph using Q3DBars and combine the use of + widgets to adjust various bar graph qualities. The example shows how to: + + \list + \li Create an application with Q3DBars and some widgets + \li Use QBar3DSeries and QBarDataProxy to set data to the graph + \li Adjust some graph and series properties using widget controls + \li Select a row or a column by clicking an axis label + \li Create a custom proxy to use with Q3DBars + \endlist + + For information about interacting with the graph, see + \l{Qt Data Visualization Interacting with Data}{this page}. + + \section2 Creating the Application + + First, in \c{bargraph.cpp}, instantiate Q3DBars and a window container for it: + + \snippet graphgallery/bargraph.cpp 0 + + The call to QWidget::createWindowContainer is required, as all data visualization graph classes + (Q3DBars, Q3DScatter, Q3DSurface) inherit QWindow. This is the only way to use a class that + inherits QWindow as a widget. + + Then, create horizontal and vertical layouts. Add the graph and the vertical layout to the + horizontal one: + + \snippet graphgallery/bargraph.cpp 1 + + Next, create another class to handle the data addition and other interaction with the + graph: + + \snippet graphgallery/bargraph.cpp 2 + + \section2 Setting up the Graph + + Set up the graph in the constructor of the \c GraphModifier class: + + \snippet graphgallery/graphmodifier.cpp 0 + + First, create the axes and the series into member variables to support changing them easily: + + \snippet graphgallery/graphmodifier.cpp 1 + + Then, set some visual qualities for the graph: + + \snippet graphgallery/graphmodifier.cpp 2 + + Set up the axes and make them the active axes of the graph: + + \snippet graphgallery/graphmodifier.cpp 3 + + Give axis labels a small autorotation angle with setLabelAutoRotation() to make them orient + slightly toward the camera. This improves axis label readability at extreme camera angles. + + Next, initialize the visual properties of the series. Note that the second series is initially + not visible: + + \snippet graphgallery/graphmodifier.cpp 4 + + Add the series to the graph: + + \snippet graphgallery/graphmodifier.cpp 5 + + Finally, set the camera angle by calling the same method the camera angle change button + in the UI uses to cycle through various camera angles: + + \snippet graphgallery/graphmodifier.cpp 6 + + The camera is controlled via the scene object of the graph: + + \snippet graphgallery/graphmodifier.cpp 7 + + For more information about using scene and cameras, see Q3DScene and Q3DCamera. + + \section2 Adding Data to the Graph + + At the end of the constructor, call a method that sets up the data: + + \snippet graphgallery/graphmodifier.cpp 8 + + This method adds data to the proxies of the two series: + + \snippet graphgallery/graphmodifier.cpp 9a + \dots 0 + \snippet graphgallery/graphmodifier.cpp 9b + + \section2 Using Widgets to Control the Graph + + Continue by adding some widgets in \c{bargraph.cpp}. Add a slider: + + \snippet graphgallery/bargraph.cpp 3 + + Use the slider to rotate the graph instead of just using a mouse or touch. Add it to the + vertical layout: + + \snippet graphgallery/bargraph.cpp 4 + + Then, connect it to a method in \c GraphModifier: + + \snippet graphgallery/bargraph.cpp 5 + + Create a slot in \c GraphModifier for the signal connection. The camera is controlled via the + scene object. This time, specify the actual camera position along the orbit around the center + point, instead of specifying a preset camera angle: + + \snippet graphgallery/graphmodifier.cpp 10 + + You can now use the slider to rotate the graph. + + Add more widgets to the vertical layout to control: + + \list + \li Graph rotation + \li Label style + \li Camera preset + \li Background visibility + \li Grid visibility + \li Bar shading smoothness + \li Visibility of the second bar series + \li Value axis direction + \li Axis title visibility and rotation + \li Data range to be shown + \li Bar style + \li Selection mode + \li Theme + \li Shadow quality + \li Font + \li Font size + \li Axis label rotation + \li Data mode + \endlist + + Some widget controls are intentionally disabled when in the \uicontrol {Custom Proxy Data} + data mode. + + \section2 Selecting a Row or Column by Clicking an Axis Label + + Selection by axis label is default functionality for bar graphs. As an example, you can select + rows by clicking an axis label in the following way: + + \list 1 + \li Change selection mode to \c SelectionRow + \li Click a year label + \li The row with the clicked year is selected + \endlist + + The same method works with \c SelectionSlice and \c SelectionItem flags, as long as + either \c SelectionRow or \c SelectionColumn is set as well. + + \section2 Zooming to Selection + + As an example of adjusting the camera target, implement an animation of zooming to + selection via a button press. Animation initializations are done in the constructor: + + \snippet graphgallery/graphmodifier.cpp 11 + + Function \c{GraphModifier::zoomToSelectedBar()} contains the zooming functionality. + QPropertyAnimation \c m_animationCameraTarget targets Q3DCamera::target property, + which takes a value normalized to the range (-1, 1). + + Figure out where the selected bar is relative to axes, and use that as the end value for + \c{m_animationCameraTarget}: + + \snippet graphgallery/graphmodifier.cpp 12 + \dots 0 + \snippet graphgallery/graphmodifier.cpp 13 + + Then, rotate the camera so that it always points approximately to the center of + the graph at the end of the animation: + + \snippet graphgallery/graphmodifier.cpp 14 + + \section2 Custom Proxy for Data + + By toggling \uicontrol {Custom Proxy Data} data mode on, a custom dataset and the corresponding + proxy are taken into use. + + Define a simple flexible data set, \c{VariantDataSet}, where each data item is + a variant list. Each item can have multiple values, identified by their index in + the list. In this case, the data set is storing monthly rainfall data, where the value in + index zero is the year, the value in index one is the month, and the value in index two is + the amount of rainfall in that month. + + The custom proxy is similar to itemmodel-based proxies provided by Qt Data Visualization, and + it requires mapping to interpret the data. + + \section3 VariantDataSet + + Define the data items as QVariantList objects. Add functionality for clearing the data set and + querying for a reference to the data contained in the set. Also, add signals to be emitted when + data is added or the set is cleared: + + \snippet graphgallery/variantdataset.h 0 + \dots 0 + \codeline + \snippet graphgallery/variantdataset.h 1 + + \section3 VariantBarDataProxy + + Subclass \c VariantBarDataProxy from QBarDataProxy and provide a simple API of getters and + setters for the data set and the mapping: + + \snippet graphgallery/variantbardataproxy.h 0 + \dots 0 + \codeline + \snippet graphgallery/variantbardataproxy.h 1 + + The proxy listens for the changes in the data set and the mapping, and resolves the data set + if any changes are detected. This is not a particularly efficient implementation, as any change + will cause re-resolving of the entire data set, but that is not an issue for this example. + + In \c resolveDataSet() method, sort the variant data values into rows and columns based on the + mapping. This is very similar to how QItemModelBarDataProxy handles mapping, except you use + list indexes instead of item model roles here. Once the values are sorted, generate + \c QBarDataArray out of them, and call the \c resetArray() method in the parent class: + + \snippet graphgallery/variantbardataproxy.cpp 0 + + \section3 VariantBarDataMapping + + Store the mapping information between \c VariantDataSet data item indexes and rows, columns, + and values of \c QBarDataArray in \c VariantBarDataMapping. It contains the lists of rows and + columns to be included in the resolved data: + + \snippet graphgallery/variantbardatamapping.h 0 + \dots 0 + \codeline + \snippet graphgallery/variantbardatamapping.h 1 + \dots 0 + \codeline + \snippet graphgallery/variantbardatamapping.h 2 + \dots 0 + \codeline + \snippet graphgallery/variantbardatamapping.h 3 + + The primary way to use a \c VariantBarDataMapping object is to give the mappings in the + constructor, though you can use the \c remap() method to set them later, either individually or + all together. Emit a signal if mapping changes. The outcome is a simplified version of the + mapping functionality of QItemModelBarDataProxy, adapted to work with variant lists instead of + item models. + + \section3 RainfallData + + Handle the setup of QBar3DSeries with the custom proxy in the \c RainfallData class: + + \snippet graphgallery/rainfalldata.cpp 0 + + Populate the variant data set in the \c addDataSet() method: + + \snippet graphgallery/rainfalldata.cpp 1 + \dots + + Add the data set to the custom proxy and set the mapping: + + \snippet graphgallery/rainfalldata.cpp 2 + + Finally, add a function for getting the created series for displaying: + + \snippet graphgallery/rainfalldata.h 0 + +*/ diff --git a/examples/datavisualization/customproxy/customproxy.pro b/examples/datavisualization/graphgallery/graphgallery.pro index fd5e0852..1f8ce428 100644 --- a/examples/datavisualization/customproxy/customproxy.pro +++ b/examples/datavisualization/graphgallery/graphgallery.pro @@ -6,19 +6,25 @@ android|ios|winrt { error( "Couldn't find the examples.pri file!" ) } +QT += widgets +requires(qtConfig(fontcombobox)) +requires(qtConfig(combobox)) + SOURCES += main.cpp \ - rainfallgraph.cpp \ + graphmodifier.cpp \ + rainfalldata.cpp \ variantdataset.cpp \ variantbardataproxy.cpp \ variantbardatamapping.cpp \ HEADERS += \ - rainfallgraph.h \ + graphmodifier.h \ + rainfalldata.h \ variantdataset.h \ variantbardataproxy.h \ variantbardatamapping.h -RESOURCES += customproxy.qrc +RESOURCES += graphgallery.qrc OTHER_FILES += doc/src/* \ doc/images/* \ diff --git a/examples/datavisualization/customproxy/customproxy.qrc b/examples/datavisualization/graphgallery/graphgallery.qrc index 53cd4915..53cd4915 100644 --- a/examples/datavisualization/customproxy/customproxy.qrc +++ b/examples/datavisualization/graphgallery/graphgallery.qrc diff --git a/examples/datavisualization/bars/graphmodifier.cpp b/examples/datavisualization/graphgallery/graphmodifier.cpp index 8dcf78e6..56ec102a 100644 --- a/examples/datavisualization/bars/graphmodifier.cpp +++ b/examples/datavisualization/graphgallery/graphmodifier.cpp @@ -1,7 +1,9 @@ -// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "graphmodifier.h" +#include "rainfalldata.h" + #include <QtDataVisualization/qcategory3daxis.h> #include <QtDataVisualization/qvalue3daxis.h> #include <QtDataVisualization/qbardataproxy.h> @@ -9,29 +11,22 @@ #include <QtDataVisualization/q3dcamera.h> #include <QtDataVisualization/qbar3dseries.h> #include <QtDataVisualization/q3dtheme.h> -#include <QtCore/QTime> -#include <QtWidgets/QComboBox> #include <QtCore/qmath.h> +#include <QtWidgets/qcombobox.h> + +// TODO: Many of the values do not affect custom proxy series now - should be fixed //! [0] GraphModifier::GraphModifier(Q3DBars *bargraph) : m_graph(bargraph), - m_xRotation(0.0f), - m_yRotation(0.0f), - m_fontSize(30), - m_segments(4), - m_subSegments(3), - m_minval(-20.0f), - m_maxval(20.0f), + //! [0] //! [1] m_temperatureAxis(new QValue3DAxis), m_yearAxis(new QCategory3DAxis), m_monthAxis(new QCategory3DAxis), m_primarySeries(new QBar3DSeries), - m_secondarySeries(new QBar3DSeries), - //! [1] - m_barMesh(QAbstract3DSeries::MeshBevelBar), - m_smooth(false) + m_secondarySeries(new QBar3DSeries) + //! [1] { //! [2] m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftMedium); @@ -65,7 +60,7 @@ GraphModifier::GraphModifier(Q3DBars *bargraph) m_graph->setColumnAxis(m_monthAxis); //! [3] - //! [8] + //! [4] m_primarySeries->setItemLabelFormat(QStringLiteral("Oulu - @colLabel @rowLabel: @valueLabel")); m_primarySeries->setMesh(QAbstract3DSeries::MeshBevelBar); m_primarySeries->setMeshSmooth(false); @@ -74,23 +69,23 @@ GraphModifier::GraphModifier(Q3DBars *bargraph) m_secondarySeries->setMesh(QAbstract3DSeries::MeshBevelBar); m_secondarySeries->setMeshSmooth(false); m_secondarySeries->setVisible(false); - //! [8] - //! [4] + + //! [5] m_graph->addSeries(m_primarySeries); m_graph->addSeries(m_secondarySeries); - //! [4] + //! [5] //! [6] changePresetCamera(); //! [6] - //! [9] + //! [8] resetTemperatureData(); - //! [9] + //! [8] // Set up property animations for zooming to the selected bar - //! [12] + //! [11] Q3DCamera *camera = m_graph->scene()->activeCamera(); m_defaultAngleX = camera->xRotation(); m_defaultAngleY = camera->yRotation(); @@ -120,22 +115,25 @@ GraphModifier::GraphModifier(Q3DBars *bargraph) m_animationCameraZoom.setKeyValueAt(zoomOutFraction, QVariant::fromValue(50.0f)); m_animationCameraTarget.setKeyValueAt(zoomOutFraction, QVariant::fromValue(QVector3D(0.0f, 0.0f, 0.0f))); - //! [12] + //! [11] + + m_customData = new RainfallData(); } -//! [0] GraphModifier::~GraphModifier() { + delete m_customData; delete m_graph; } void GraphModifier::resetTemperatureData() { - //! [5] + //! [9a] // Set up data static const float tempOulu[8][12] = { {-7.4f, -2.4f, 0.0f, 3.0f, 8.2f, 11.6f, 14.7f, 15.4f, 11.4f, 4.2f, 2.1f, -2.3f}, // 2015 {-13.4f, -3.9f, -1.8f, 3.1f, 10.6f, 13.7f, 17.8f, 13.6f, 10.7f, 3.5f, -3.1f, -4.2f}, // 2016 + //! [9a] {-5.7f, -6.7f, -3.0f, -0.1f, 4.7f, 12.4f, 16.1f, 14.1f, 9.4f, 3.0f, -0.3f, -3.2f}, // 2017 {-6.4f, -11.9f, -7.4f, 1.9f, 11.4f, 12.4f, 21.5f, 16.1f, 11.0f, 4.4f, 2.1f, -4.1f}, // 2018 {-11.7f, -6.1f, -2.4f, 3.9f, 7.2f, 14.5f, 15.6f, 14.4f, 8.5f, 2.0f, -3.0f, -1.5f}, // 2019 @@ -156,10 +154,11 @@ void GraphModifier::resetTemperatureData() }; // Create data arrays + //! [9b] QBarDataArray *dataSet = new QBarDataArray; QBarDataArray *dataSet2 = new QBarDataArray; - QBarDataRow *dataRow; - QBarDataRow *dataRow2; + QBarDataRow *dataRow = nullptr; + QBarDataRow *dataRow2= nullptr; dataSet->reserve(m_years.size()); for (int year = 0; year < m_years.size(); year++) { @@ -179,7 +178,7 @@ void GraphModifier::resetTemperatureData() // Add data to the data proxy (the data proxy assumes ownership of it) m_primarySeries->dataProxy()->resetArray(dataSet, m_years, m_months); m_secondarySeries->dataProxy()->resetArray(dataSet2, m_years, m_months); - //! [5] + //! [9b] } void GraphModifier::changeRange(int range) @@ -197,6 +196,7 @@ void GraphModifier::changeStyle(int style) m_barMesh = QAbstract3DSeries::Mesh(comboBox->itemData(style).toInt()); m_primarySeries->setMesh(m_barMesh); m_secondarySeries->setMesh(m_barMesh); + m_customData->customSeries()->setMesh(m_barMesh); } } @@ -210,14 +210,14 @@ void GraphModifier::changePresetCamera() // Restore camera target in case animation has changed it m_graph->scene()->activeCamera()->setTarget(QVector3D(0.0f, 0.0f, 0.0f)); - //! [10] + //! [7] static int preset = Q3DCamera::CameraPresetFront; m_graph->scene()->activeCamera()->setCameraPreset((Q3DCamera::CameraPreset)preset); if (++preset > Q3DCamera::CameraPresetDirectlyBelow) preset = Q3DCamera::CameraPresetFrontLow; - //! [10] + //! [7] } void GraphModifier::changeTheme(int theme) @@ -286,7 +286,6 @@ void GraphModifier::setAxisTitleFixed(bool enabled) m_yearAxis->setTitleFixed(enabled); } -//! [11] void GraphModifier::zoomToSelectedBar() { m_animationCameraX.stop(); @@ -311,7 +310,7 @@ void GraphModifier::zoomToSelectedBar() if (selectedBar != QBar3DSeries::invalidSelectionPosition()) { // Normalize selected bar position within axis range to determine target coordinates - //! [13] + //! [12] QVector3D endTarget; float xMin = m_graph->columnAxis()->min(); float xRange = m_graph->columnAxis()->max() - xMin; @@ -319,10 +318,10 @@ void GraphModifier::zoomToSelectedBar() float zRange = m_graph->rowAxis()->max() - zMin; endTarget.setX((selectedBar.y() - xMin) / xRange * 2.0f - 1.0f); endTarget.setZ((selectedBar.x() - zMin) / zRange * 2.0f - 1.0f); - //! [13] + //! [12] // Rotate the camera so that it always points approximately to the graph center - //! [15] + //! [14] qreal endAngleX = 90.0 - qRadiansToDegrees(qAtan(qreal(endTarget.z() / endTarget.x()))); if (endTarget.x() > 0.0f) endAngleX -= 180.0f; @@ -331,14 +330,14 @@ void GraphModifier::zoomToSelectedBar() float endAngleY = barValue >= 0.0f ? 30.0f : -30.0f; if (m_graph->valueAxis()->reversed()) endAngleY *= -1.0f; - //! [15] + //! [14] m_animationCameraX.setEndValue(QVariant::fromValue(float(endAngleX))); m_animationCameraY.setEndValue(QVariant::fromValue(endAngleY)); m_animationCameraZoom.setEndValue(QVariant::fromValue(250)); - //! [14] + //! [13] m_animationCameraTarget.setEndValue(QVariant::fromValue(endTarget)); - //! [14] + //! [13] } else { // No selected bar, so return to the default view m_animationCameraX.setEndValue(QVariant::fromValue(m_defaultAngleX)); @@ -352,7 +351,18 @@ void GraphModifier::zoomToSelectedBar() m_animationCameraZoom.start(); m_animationCameraTarget.start(); } -//! [11] + +void GraphModifier::setDataModeToWeather(bool enabled) +{ + if (enabled) + changeDataMode(false); +} + +void GraphModifier::setDataModeToCustom(bool enabled) +{ + if (enabled) + changeDataMode(true); +} void GraphModifier::changeShadowQuality(int quality) { @@ -361,19 +371,19 @@ void GraphModifier::changeShadowQuality(int quality) emit shadowQualityChanged(quality); } -//! [7] +//! [10] void GraphModifier::rotateX(int rotation) { m_xRotation = rotation; m_graph->scene()->activeCamera()->setCameraPosition(m_xRotation, m_yRotation); } +//! [10] void GraphModifier::rotateY(int rotation) { m_yRotation = rotation; m_graph->scene()->activeCamera()->setCameraPosition(m_xRotation, m_yRotation); } -//! [7] void GraphModifier::setBackgroundEnabled(int enabled) { @@ -390,6 +400,7 @@ void GraphModifier::setSmoothBars(int smooth) m_smooth = bool(smooth); m_primarySeries->setMeshSmooth(m_smooth); m_secondarySeries->setMeshSmooth(m_smooth); + m_customData->customSeries()->setMeshSmooth(m_smooth); } void GraphModifier::setSeriesVisibility(int enabled) @@ -406,3 +417,23 @@ void GraphModifier::setReflection(bool enabled) { m_graph->setReflection(enabled); } + +void GraphModifier::changeDataMode(bool customData) +{ + // Change between weather data and data from custom proxy + if (customData) { + m_graph->removeSeries(m_primarySeries); + m_graph->removeSeries(m_secondarySeries); + m_graph->addSeries(m_customData->customSeries()); + m_graph->setValueAxis(m_customData->valueAxis()); + m_graph->setRowAxis(m_customData->rowAxis()); + m_graph->setColumnAxis(m_customData->colAxis()); + } else { + m_graph->removeSeries(m_customData->customSeries()); + m_graph->addSeries(m_primarySeries); + m_graph->addSeries(m_secondarySeries); + m_graph->setValueAxis(m_temperatureAxis); + m_graph->setRowAxis(m_yearAxis); + m_graph->setColumnAxis(m_monthAxis); + } +} diff --git a/examples/datavisualization/bars/graphmodifier.h b/examples/datavisualization/graphgallery/graphmodifier.h index c1a6476e..09110768 100644 --- a/examples/datavisualization/bars/graphmodifier.h +++ b/examples/datavisualization/graphgallery/graphmodifier.h @@ -1,4 +1,4 @@ -// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef GRAPHMODIFIER_H @@ -7,12 +7,9 @@ #include <QtDataVisualization/q3dbars.h> #include <QtDataVisualization/qbardataproxy.h> #include <QtDataVisualization/qabstract3dseries.h> +#include <QtCore/qpropertyanimation.h> -#include <QtGui/QFont> -#include <QtCore/QDebug> -#include <QtCore/QStringList> -#include <QtCore/QPointer> -#include <QtCore/QPropertyAnimation> +class RainfallData; class GraphModifier : public QObject { @@ -34,6 +31,7 @@ public: void setSeriesVisibility(int enabled); void setReverseValueAxis(int enabled); void setReflection(bool enabled); + void changeDataMode(bool customData); public Q_SLOTS: void changeRange(int range); @@ -46,6 +44,8 @@ public Q_SLOTS: void setAxisTitleVisibility(bool enabled); void setAxisTitleFixed(bool enabled); void zoomToSelectedBar(); + void setDataModeToWeather(bool enabled); + void setDataModeToCustom(bool enabled); Q_SIGNALS: void shadowQualityChanged(int quality); @@ -55,32 +55,33 @@ Q_SIGNALS: void fontSizeChanged(int size); private: - Q3DBars *m_graph; - float m_xRotation; - float m_yRotation; - int m_fontSize; - int m_segments; - int m_subSegments; - float m_minval; - float m_maxval; - QStringList m_months; - QStringList m_years; - QValue3DAxis *m_temperatureAxis; - QCategory3DAxis *m_yearAxis; - QCategory3DAxis *m_monthAxis; - QBar3DSeries *m_primarySeries; - QBar3DSeries *m_secondarySeries; - QAbstract3DSeries::Mesh m_barMesh; - bool m_smooth; - QPropertyAnimation m_animationCameraX; - QPropertyAnimation m_animationCameraY; - QPropertyAnimation m_animationCameraZoom; - QPropertyAnimation m_animationCameraTarget; - float m_defaultAngleX; - float m_defaultAngleY; - float m_defaultZoom; - QVector3D m_defaultTarget; + Q3DBars *m_graph = nullptr; + float m_xRotation = 0.f; + float m_yRotation = 0.f; + int m_fontSize = 30; + int m_segments = 4; + int m_subSegments = 3; + float m_minval = -20.f; + float m_maxval = 20.f; + QStringList m_months = {}; + QStringList m_years = {}; + QValue3DAxis *m_temperatureAxis = nullptr; + QCategory3DAxis *m_yearAxis = nullptr; + QCategory3DAxis *m_monthAxis = nullptr; + QBar3DSeries *m_primarySeries = nullptr; + QBar3DSeries *m_secondarySeries = nullptr; + QAbstract3DSeries::Mesh m_barMesh = QAbstract3DSeries::MeshBevelBar; + bool m_smooth = false; + QPropertyAnimation m_animationCameraX = {}; + QPropertyAnimation m_animationCameraY = {}; + QPropertyAnimation m_animationCameraZoom = {}; + QPropertyAnimation m_animationCameraTarget = {}; + float m_defaultAngleX = 0.f; + float m_defaultAngleY = 0.f; + float m_defaultZoom = 0.f; + QVector3D m_defaultTarget = {}; const QString m_celsiusString = QString(QChar(0xB0)) + QLatin1String("C"); + RainfallData *m_customData = nullptr; }; #endif diff --git a/examples/datavisualization/graphgallery/main.cpp b/examples/datavisualization/graphgallery/main.cpp new file mode 100644 index 00000000..ad8eeefd --- /dev/null +++ b/examples/datavisualization/graphgallery/main.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "bargraph.h" + +#include <QtWidgets/qapplication.h> +#include <QtWidgets/qwidget.h> +#include <QtWidgets/qtabwidget.h> + +int main(int argc, char **argv) +{ + qputenv("QSG_RHI_BACKEND", "opengl"); + + QApplication app(argc, argv); + + // Create bar graph + BarGraph *bars = new BarGraph(); + if (!bars->initialize()) + return -1; + + // Create a tab widget for creating own tabs for Bars3D, Scatter3D, and Surface3D + QTabWidget *tabWidget = new QTabWidget(); + tabWidget->setWindowTitle(QLatin1String("Graph Gallery")); + + // Add bars widget + tabWidget->addTab(bars->barsWidget(), QLatin1String("Bar Graph")); + + tabWidget->show(); + return app.exec(); +} diff --git a/examples/datavisualization/customproxy/rainfallgraph.cpp b/examples/datavisualization/graphgallery/rainfalldata.cpp index da9416fe..941e2171 100644 --- a/examples/datavisualization/customproxy/rainfallgraph.cpp +++ b/examples/datavisualization/graphgallery/rainfalldata.cpp @@ -1,21 +1,15 @@ -// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#include "rainfallgraph.h" -#include <QtDataVisualization/qcategory3daxis.h> -#include <QtDataVisualization/qvalue3daxis.h> +#include "rainfalldata.h" #include <QtDataVisualization/q3dscene.h> #include <QtDataVisualization/q3dcamera.h> #include <QtDataVisualization/qbar3dseries.h> #include <QtDataVisualization/q3dtheme.h> -#include <QtGui/QGuiApplication> -#include <QtGui/QFont> -#include <QtCore/QDebug> -#include <QtCore/QTextStream> -#include <QtCore/QFile> - -RainfallGraph::RainfallGraph(Q3DBars *rainfall) - : m_graph(rainfall) +#include <QtCore/qtextstream.h> +#include <QtCore/qfile.h> + +RainfallData::RainfallData() { // In data file the months are in numeric format, so create custom list for (int i = 1; i <= 12; i++) @@ -23,79 +17,59 @@ RainfallGraph::RainfallGraph(Q3DBars *rainfall) m_columnCount = m_numericMonths.size(); + updateYearsList(2010, 2022); + + // Create proxy and series + //! [0] m_proxy = new VariantBarDataProxy; - QBar3DSeries *series = new QBar3DSeries(m_proxy); - m_graph->addSeries(series); + m_series = new QBar3DSeries(m_proxy); + //! [0] - updateYearsList(2000, 2012); + m_series->setItemLabelFormat(QString(QStringLiteral("%.1f mm"))); - // Set up bar specifications; make the bars as wide as they are deep, - // and add a small space between the bars - m_graph->setBarThickness(1.0f); - m_graph->setBarSpacing(QSizeF(1.1, 1.1)); + // Create the axes + m_rowAxis = new QCategory3DAxis(this); + m_colAxis = new QCategory3DAxis(this); + m_valueAxis = new QValue3DAxis(this); + m_rowAxis->setAutoAdjustRange(true); + m_colAxis->setAutoAdjustRange(true); + m_valueAxis->setAutoAdjustRange(true); // Set axis labels and titles QStringList months; months << "January" << "February" << "March" << "April" << "May" << "June" << "July" << "August" << "September" << "October" << "November" << "December"; - m_graph->rowAxis()->setTitle("Year"); - m_graph->columnAxis()->setTitle("Month"); - m_graph->valueAxis()->setTitle("rainfall"); - m_graph->valueAxis()->setLabelFormat("%d mm"); - m_graph->valueAxis()->setSegmentCount(5); - m_graph->rowAxis()->setLabels(m_years); - m_graph->columnAxis()->setLabels(months); - - // Set bar type to cylinder - series->setMesh(QAbstract3DSeries::MeshCylinder); - - // Set shadows to medium - m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualityMedium); - - // Set selection mode to bar and column - m_graph->setSelectionMode(QAbstract3DGraph::SelectionItemAndColumn | QAbstract3DGraph::SelectionSlice); - - // Set theme - m_graph->activeTheme()->setType(Q3DTheme::ThemeArmyBlue); - - // Override font in theme - m_graph->activeTheme()->setFont(QFont("Century Gothic", 30)); - - // Override label background for theme - m_graph->activeTheme()->setLabelBackgroundEnabled(false); - - // Set camera position and zoom - m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetIsometricRightHigh); - - // Set window title - m_graph->setTitle(QStringLiteral("Monthly rainfall in Northern Finland")); + m_rowAxis->setTitle("Year"); + m_colAxis->setTitle("Month"); + m_valueAxis->setTitle("rainfall"); + m_valueAxis->setSegmentCount(5); + m_rowAxis->setLabels(m_years); + m_colAxis->setLabels(months); + m_rowAxis->setTitleVisible(true); + m_colAxis->setTitleVisible(true); + m_valueAxis->setTitleVisible(true); - // Set reflections on - m_graph->setReflection(true); + addDataSet(); } -RainfallGraph::~RainfallGraph() +RainfallData::~RainfallData() { delete m_mapping; delete m_dataSet; - delete m_graph; -} - -void RainfallGraph::start() -{ - addDataSet(); + delete m_proxy; } -void RainfallGraph::updateYearsList(int start, int end) +void RainfallData::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(); } -//! [0] -void RainfallGraph::addDataSet() +//! [1] +void RainfallData::addDataSet() { // Create a new variant data set and data item list m_dataSet = new VariantDataSet; @@ -127,15 +101,15 @@ void RainfallGraph::addDataSet() } else { qWarning() << "Unable to open data file:" << dataFile.fileName(); } - //! [1] + + //! [2] // Add items to the data set and set it to the proxy m_dataSet->addItems(itemList); m_proxy->setDataSet(m_dataSet); // Create new mapping for the data and set it to the proxy - m_mapping = new VariantBarDataMapping(0, 1, 2, m_years, m_numericMonths); + m_mapping = new VariantBarDataMapping(0, 1, 2, m_years, m_numericMonths); m_proxy->setMapping(m_mapping); - //! [1] + //! [2] } -//! [0] diff --git a/examples/datavisualization/graphgallery/rainfalldata.h b/examples/datavisualization/graphgallery/rainfalldata.h new file mode 100644 index 00000000..cf4866b1 --- /dev/null +++ b/examples/datavisualization/graphgallery/rainfalldata.h @@ -0,0 +1,43 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef RAINFALLDATA_H +#define RAINFALLDATA_H + +#include "variantbardataproxy.h" +#include <QtDataVisualization/qcategory3daxis.h> +#include <QtDataVisualization/qvalue3daxis.h> + +class RainfallData : public QObject +{ + Q_OBJECT +public: + explicit RainfallData(); + ~RainfallData(); + + void addDataSet(); + + //! [0] + QBar3DSeries *customSeries() { return m_series; } + //! [0] + + QValue3DAxis *valueAxis() { return m_valueAxis; } + QCategory3DAxis *rowAxis() { return m_rowAxis; } + QCategory3DAxis *colAxis() { return m_colAxis; } + +private: + void updateYearsList(int start, int end); + int m_columnCount; + int m_rowCount; + QStringList m_years; + QStringList m_numericMonths; + VariantBarDataProxy *m_proxy; + VariantBarDataMapping *m_mapping; + VariantDataSet *m_dataSet; + QBar3DSeries *m_series; + QValue3DAxis *m_valueAxis; + QCategory3DAxis *m_rowAxis; + QCategory3DAxis *m_colAxis; +}; + +#endif diff --git a/examples/datavisualization/customproxy/variantbardatamapping.cpp b/examples/datavisualization/graphgallery/variantbardatamapping.cpp index 3a4396f7..2e375f10 100644 --- a/examples/datavisualization/customproxy/variantbardatamapping.cpp +++ b/examples/datavisualization/graphgallery/variantbardatamapping.cpp @@ -1,21 +1,15 @@ -// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "variantbardatamapping.h" VariantBarDataMapping::VariantBarDataMapping() - : QObject(0), - m_rowIndex(0), - m_columnIndex(1), - m_valueIndex(2) + : QObject(0) { } VariantBarDataMapping::VariantBarDataMapping(const VariantBarDataMapping &other) - : QObject(0), - m_rowIndex(0), - m_columnIndex(1), - m_valueIndex(2) + : QObject(0) { operator=(other); } @@ -23,10 +17,7 @@ VariantBarDataMapping::VariantBarDataMapping(const VariantBarDataMapping &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) + : QObject(0) { m_rowIndex = rowIndex; m_columnIndex = columnIndex; diff --git a/examples/datavisualization/customproxy/variantbardatamapping.h b/examples/datavisualization/graphgallery/variantbardatamapping.h index 6a33cee4..bd4749a3 100644 --- a/examples/datavisualization/customproxy/variantbardatamapping.h +++ b/examples/datavisualization/graphgallery/variantbardatamapping.h @@ -1,11 +1,11 @@ -// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef VARIANTBARDATAMAPPING_H #define VARIANTBARDATAMAPPING_H -#include <QtCore/QObject> -#include <QtCore/QStringList> +#include <QtCore/qobject.h> +#include <QtCore/qstringlist.h> class VariantBarDataMapping : public QObject { @@ -22,8 +22,8 @@ public: VariantBarDataMapping(const VariantBarDataMapping &other); //! [1] VariantBarDataMapping(int rowIndex, int columnIndex, int valueIndex, - const QStringList &rowCategories, - const QStringList &columnCategories); + const QStringList &rowCategories, + const QStringList &columnCategories); //! [1] virtual ~VariantBarDataMapping(); @@ -58,13 +58,13 @@ Q_SIGNALS: private: // Indexes of the mapped items in the VariantDataItem - int m_rowIndex; - int m_columnIndex; - int m_valueIndex; + int m_rowIndex = 0; + int m_columnIndex = 1; + int m_valueIndex = 2; // For row/column items, sort items into these categories. Other categories are ignored. - QStringList m_rowCategories; - QStringList m_columnCategories; + QStringList m_rowCategories = {}; + QStringList m_columnCategories = {}; }; #endif diff --git a/examples/datavisualization/customproxy/variantbardataproxy.cpp b/examples/datavisualization/graphgallery/variantbardataproxy.cpp index f94f37b5..e15a8148 100644 --- a/examples/datavisualization/customproxy/variantbardataproxy.cpp +++ b/examples/datavisualization/graphgallery/variantbardataproxy.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "variantbardataproxy.h" @@ -44,15 +44,17 @@ VariantDataSet *VariantBarDataProxy::dataSet() void VariantBarDataProxy::setMapping(VariantBarDataMapping *mapping) { - if (!m_mapping.isNull()) + if (!m_mapping.isNull()) { QObject::disconnect(m_mapping.data(), &VariantBarDataMapping::mappingChanged, this, &VariantBarDataProxy::handleMappingChanged); + } m_mapping = mapping; - if (!m_mapping.isNull()) + if (!m_mapping.isNull()) { QObject::connect(m_mapping.data(), &VariantBarDataMapping::mappingChanged, this, &VariantBarDataProxy::handleMappingChanged); + } resolveDataSet(); } @@ -103,14 +105,14 @@ void VariantBarDataProxy::resolveDataSet() // Sort values into rows and columns typedef QHash<QString, float> ColumnValueMap; QHash <QString, ColumnValueMap> itemValueMap; - foreach (const VariantDataItem *item, itemList) { + for (const VariantDataItem *item : itemList) { itemValueMap[item->at(rowIndex).toString()][item->at(columnIndex).toString()] = item->at(valueIndex).toReal(); } // Create a new data array in format the parent class understands QBarDataArray *newProxyArray = new QBarDataArray; - foreach (QString rowKey, rowList) { + for (const 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)]); diff --git a/examples/datavisualization/customproxy/variantbardataproxy.h b/examples/datavisualization/graphgallery/variantbardataproxy.h index 9fec86a0..d2ed185a 100644 --- a/examples/datavisualization/customproxy/variantbardataproxy.h +++ b/examples/datavisualization/graphgallery/variantbardataproxy.h @@ -1,15 +1,15 @@ -// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef VARIANTBARDATAPROXY_H #define VARIANTBARDATAPROXY_H -#include <QtDataVisualization/qbardataproxy.h> #include "variantdataset.h" #include "variantbardatamapping.h" -#include <QtCore/QStringList> -#include <QtCore/QMap> -#include <QtCore/QPointer> +#include <QtDataVisualization/qbardataproxy.h> +#include <QtCore/qstringlist.h> +#include <QtCore/qmap.h> +#include <QtCore/qpointer.h> //! [0] class VariantBarDataProxy : public QBarDataProxy diff --git a/examples/datavisualization/customproxy/variantdataset.cpp b/examples/datavisualization/graphgallery/variantdataset.cpp index 63a81b98..400ff2a4 100644 --- a/examples/datavisualization/customproxy/variantdataset.cpp +++ b/examples/datavisualization/graphgallery/variantdataset.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "variantdataset.h" @@ -15,7 +15,7 @@ VariantDataSet::~VariantDataSet() void VariantDataSet::clear() { - foreach (VariantDataItem *item, m_variantData) { + for (VariantDataItem *item : m_variantData) { item->clear(); delete item; } diff --git a/examples/datavisualization/customproxy/variantdataset.h b/examples/datavisualization/graphgallery/variantdataset.h index 55d31606..ce52db10 100644 --- a/examples/datavisualization/customproxy/variantdataset.h +++ b/examples/datavisualization/graphgallery/variantdataset.h @@ -1,16 +1,15 @@ -// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef VARIANTDATASET_H #define VARIANTDATASET_H -#include <QtCore/QScopedPointer> -#include <QtCore/QVariantList> +#include <QtCore/qvariantlist.h> -//! [1] +//! [0] typedef QVariantList VariantDataItem; typedef QList<VariantDataItem *> VariantDataItemList; -//! [1] +//! [0] class VariantDataSet : public QObject { @@ -20,7 +19,7 @@ public: explicit VariantDataSet(); ~VariantDataSet(); - //! [0] + //! [1] void clear(); int addItem(VariantDataItem *item); @@ -31,7 +30,7 @@ public: Q_SIGNALS: void itemsAdded(int index, int count); void dataCleared(); - //! [0] + //! [1] private: VariantDataItemList m_variantData; |