summaryrefslogtreecommitdiffstats
path: root/examples/datavisualization/itemmodel
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2014-02-13 09:59:52 +0200
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2014-02-13 10:09:17 +0200
commit88cd10aa7b3559b092cf5575b0a17d002dc100ae (patch)
tree9d6e7efdec49419558bb4ef4a9bc02ae3cb1cfc4 /examples/datavisualization/itemmodel
parentecabd51692b476567dc42a745f51996ec665b385 (diff)
Fix examples installation
Had to add one folder to the examples structure so installation works correctly. Change-Id: Ic92dfe9997413a6243abcf5eeba12744ba9e938c Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Diffstat (limited to 'examples/datavisualization/itemmodel')
-rw-r--r--examples/datavisualization/itemmodel/doc/images/itemmodel-example-2.pngbin0 -> 78536 bytes
-rw-r--r--examples/datavisualization/itemmodel/doc/images/itemmodel-example.pngbin0 -> 45381 bytes
-rw-r--r--examples/datavisualization/itemmodel/doc/src/itemmodel.qdoc181
-rw-r--r--examples/datavisualization/itemmodel/itemmodel.pro7
-rw-r--r--examples/datavisualization/itemmodel/main.cpp285
5 files changed, 473 insertions, 0 deletions
diff --git a/examples/datavisualization/itemmodel/doc/images/itemmodel-example-2.png b/examples/datavisualization/itemmodel/doc/images/itemmodel-example-2.png
new file mode 100644
index 00000000..677b7eec
--- /dev/null
+++ b/examples/datavisualization/itemmodel/doc/images/itemmodel-example-2.png
Binary files differ
diff --git a/examples/datavisualization/itemmodel/doc/images/itemmodel-example.png b/examples/datavisualization/itemmodel/doc/images/itemmodel-example.png
new file mode 100644
index 00000000..c042f84d
--- /dev/null
+++ b/examples/datavisualization/itemmodel/doc/images/itemmodel-example.png
Binary files differ
diff --git a/examples/datavisualization/itemmodel/doc/src/itemmodel.qdoc b/examples/datavisualization/itemmodel/doc/src/itemmodel.qdoc
new file mode 100644
index 00000000..16cd1974
--- /dev/null
+++ b/examples/datavisualization/itemmodel/doc/src/itemmodel.qdoc
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 QtDataVisualization 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 itemmodel
+ \title Item Model Example
+ \ingroup qtdatavisualization_examples
+ \brief Using an item model as data source for Q3DBars.
+
+ The item model example shows how to make a simple 3D bar graph using Q3DBars and how to modify
+ the data being drawn at run-time. The example shows how to:
+
+ \list
+ \li Create an application with Q3DBars and widgets
+ \li Use QItemModelBarDataProxy to set data to the graph
+ \li Use a table widget to modify the data in the graph
+ \endlist
+
+ For instructions about how to interact with the graph, see \l{Qt Data Visualization Interacting with Data}{this page}.
+
+ \image itemmodel-example-2.png
+
+ \section1 Creating the application
+
+ First, in main.cpp, we create a QApplication, instantiate Q3DBars and a window container for it:
+
+ \snippet ../examples/itemmodel/main.cpp 0
+
+ The call to QWidget::createWindowContainer is required, as all data visualization types
+ (Q3DBars, Q3DScatter, and Q3DSurface) inherit QWindow. Any class inheriting QWindow cannot be used
+ as a widget any other way.
+
+ Then we'll create a layout and add the graph and the table widget into it:
+
+ \snippet ../examples/itemmodel/main.cpp 1
+
+ The table widget is going to be used to display the numerical data being inserted into the
+ graph, and to modify it (See \l {Adding data to the graph} and \l {Interacting with the data}).
+
+ We need to instantiate QItemModelBarDataProxy and a QBar3DSeries for it, and give the series
+ to the graph:
+
+ \snippet ../examples/itemmodel/main.cpp 2
+
+ Here we tell the proxy to directly map the model's rows and columns into the proxy's rows and
+ columns instead of defining row and column roles to map for them. Then we give the model from
+ the table widget to the proxy. We also create a series instance and set the proxy to it.
+ We customize the series visuals a bit by changing the object mesh to pyramids, and finally
+ add the series to the graph.
+
+ Next, let's create another class to handle the data addition and other interaction with the
+ graph. Let's call it \c GraphDataGenerator (See \l {Setting up the graph} and
+ \l {Adding data to the graph} for details) and connect some signals between QBar3DSeries,
+ \c GraphDataGenerator, and QTableWidget (See \l {Interacting with the data} for a closer look):
+
+ \snippet ../examples/itemmodel/main.cpp 3
+
+ The application main is done and we can show the graph and start the event loop:
+
+ \snippet ../examples/itemmodel/main.cpp 4
+
+ \section1 Setting up the graph
+
+ Let's set up the visual attributes for the graph in the constructor of \c GraphDataGenerator:
+
+ \snippet ../examples/itemmodel/main.cpp 5
+ \snippet ../examples/itemmodel/main.cpp 6
+ \snippet ../examples/itemmodel/main.cpp 7
+
+ First we set bar thickness ratio to 1.0, which means bars will be as wide as they are deep. 1.0
+ is also the default value, so the line is basically unnecessary. It's left there so you could
+ easily try how changing it affects the graph. The second line sets bar spacings to 0.2, which
+ means there will be a gap of 20% of the bar's thickness between the bars in both directions.
+
+ We want to be able to select rows of data for a closer inspection, so we set the selection mode
+ to slice item and row. This means that whenever we select a bar in the graph, the whole row will be
+ displayed separately and the selected bar will be highlighted.
+
+ We don't want to use the default colors, so we set one of the predefined themes as the active theme.
+
+ Next line sets the font to \c Impact. If your system doesn't have it, it will be replaced by
+ the system default.
+
+ And finally, we set the camera position to one of the predefined camera positions.
+ Now the initial graph settings are done.
+
+ \note You do not need to set any of these in case you're happy with the defaults. You can
+ easily try them by commenting out the contents of the constructor.
+
+ \section1 Adding data to the graph
+
+ We created the data generator in the application main and gave it the graph and the table
+ widget as parameters:
+
+ \code GraphDataGenerator generator(graph, tableWidget); \endcode
+
+ We added a separate start method to the generator, so that it wouldn't start doing anything
+ until everything else is set up. We then called the method when starting the application:
+
+ \code generator.start(); \endcode
+
+ Let's have a look at the contents of the \c start() method:
+
+ \snippet ../examples/itemmodel/main.cpp 8
+
+ The main thing \c start() does is set up the data model. It also activates a timer for getting
+ the accurate dimensions of the table widget after it's been filled with data. The reason we
+ do this is that the widget doesn't know its final visual domensions until all the data has been
+ inserted to it and it has been shown. The data timer usage is not vital for the
+ application, so we won't take a closer look at it. It's just there to make QTableWidget look better.
+
+ In \c setupModel() we first introduce the row and column labels, and the actual data:
+
+ \snippet ../examples/itemmodel/main.cpp 9
+
+ Then we set up the axes:
+
+ \snippet ../examples/itemmodel/main.cpp 10
+
+ Next we will set up the table widget:
+
+ \snippet ../examples/itemmodel/main.cpp 11
+
+ After that all that's left is adding the data to the table widget:
+
+ \snippet ../examples/itemmodel/main.cpp 12
+
+ Now we have a bar graph and a table widget, both displaying the same data.
+
+ You're probably wondering how the data can be displayed in the graph, as the only thing we did
+ was add it to the table widget? That's because of what we did earlier, in the application main:
+
+ \snippet ../examples/itemmodel/main.cpp 2
+
+ We created QItemModelBarDataProxy instance, and gave the proxy the model of the table widget
+ we just created. The proxy maps the rows and the columns in the model of the table widget into
+ rows and columns for itself directly, as we set the QItemModelBarDataProxy::useModelCategories
+ property to true, and the graph gets the data to be displayed via the series that owns the proxy.
+
+ \section1 Interacting with the data
+
+ We made a couple of signal connections in the application main earlier:
+
+ \snippet ../examples/itemmodel/main.cpp 3
+
+ Now we'll find out what these were for.
+
+ The first one connects a signal from Q3DBars to the \c GraphDataGenerator. Signal
+ QBar3DSeries::selectedBarChanged() is emitted when a bar is selected from the series. We connect
+ that to a method in the data generator that selects the same data item in the table widget:
+
+ \snippet ../examples/itemmodel/main.cpp 13
+
+ The second connection does the opposite; it connects a signal from the table widget to a
+ method in the data generator. The method then selects the corresponding bar in the series:
+
+ \snippet ../examples/itemmodel/main.cpp 14
+
+ You can even select an item in the widget and change the value of it, and the new value is
+ updated to the graph. This is handled again by the proxy with mapping between the data
+ in the table widget and itself.
+
+ \image itemmodel-example.png
+
+ \section1 Example contents
+*/
diff --git a/examples/datavisualization/itemmodel/itemmodel.pro b/examples/datavisualization/itemmodel/itemmodel.pro
new file mode 100644
index 00000000..844fe3d8
--- /dev/null
+++ b/examples/datavisualization/itemmodel/itemmodel.pro
@@ -0,0 +1,7 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+SOURCES += main.cpp
+
+QT += widgets
diff --git a/examples/datavisualization/itemmodel/main.cpp b/examples/datavisualization/itemmodel/main.cpp
new file mode 100644
index 00000000..2fce72aa
--- /dev/null
+++ b/examples/datavisualization/itemmodel/main.cpp
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 QtDataVisualization 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 <QtDataVisualization/q3dbars.h>
+#include <QtDataVisualization/qcategory3daxis.h>
+#include <QtDataVisualization/qitemmodelbardataproxy.h>
+#include <QtDataVisualization/qvalue3daxis.h>
+#include <QtDataVisualization/q3dscene.h>
+#include <QtDataVisualization/q3dcamera.h>
+#include <QtDataVisualization/qbar3dseries.h>
+#include <QtDataVisualization/q3dtheme.h>
+
+#include <QApplication>
+#include <QVBoxLayout>
+#include <QTableWidget>
+#include <QScreen>
+#include <QTimer>
+#include <QFont>
+#include <QDebug>
+#include <QHeaderView>
+
+#define USE_STATIC_DATA
+
+using namespace QtDataVisualization;
+
+class GraphDataGenerator : public QObject
+{
+public:
+ explicit GraphDataGenerator(Q3DBars *bargraph, QTableWidget *tableWidget);
+ ~GraphDataGenerator();
+
+ void setupModel();
+ void addRow();
+ void changeStyle();
+ void changePresetCamera();
+ void changeTheme();
+ void start();
+ void selectFromTable(const QPoint &selection);
+ void selectedFromTable(int currentRow, int currentColumn, int previousRow, int previousColumn);
+ void fixTableSize();
+
+private:
+ Q3DBars *m_graph;
+ QTimer *m_dataTimer;
+ QTimer *m_styleTimer;
+ QTimer *m_presetTimer;
+ QTimer *m_themeTimer;
+ int m_columnCount;
+ int m_rowCount;
+ QTableWidget *m_tableWidget; // not owned
+};
+
+GraphDataGenerator::GraphDataGenerator(Q3DBars *bargraph, QTableWidget *tableWidget)
+ : m_graph(bargraph),
+ m_dataTimer(0),
+ m_styleTimer(0),
+ m_presetTimer(0),
+ m_themeTimer(0),
+ m_columnCount(100),
+ m_rowCount(50),
+ m_tableWidget(tableWidget)
+{
+ //! [5]
+ // Set up bar specifications; make the bars as wide as they are deep,
+ // and add a small space between them
+ m_graph->setBarThickness(1.0f);
+ m_graph->setBarSpacing(QSizeF(0.2, 0.2));
+
+ //! [5]
+#ifndef USE_STATIC_DATA
+ // Set up sample space; make it as deep as it's wide
+ m_graph->rowAxis()->setRange(0, m_rowCount);
+ m_graph->columnAxis()->setRange(0, m_columnCount);
+ m_tableWidget->setColumnCount(m_columnCount);
+
+ // Set selection mode to full
+ m_graph->setSelectionMode(QAbstract3DGraph::SelectionItemRowAndColumn);
+
+ // Hide axis labels by explicitly setting one empty string as label list
+ m_graph->rowAxis()->setLabels(QStringList(QString()));
+ m_graph->columnAxis()->setLabels(QStringList(QString()));
+
+ m_graph->seriesList().at(0)->setItemLabelFormat(QStringLiteral("@valueLabel"));
+#else
+ //! [6]
+ // Set selection mode to slice row
+ m_graph->setSelectionMode(QAbstract3DGraph::SelectionItemAndRow | QAbstract3DGraph::SelectionSlice);
+
+ //! [6]
+#endif
+
+ //! [7]
+ // Set theme
+ m_graph->activeTheme()->setType(Q3DTheme::ThemeDigia);
+
+ // Set font
+ m_graph->activeTheme()->setFont(QFont("Impact", 20));
+
+ // Set preset camera position
+ m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
+ //! [7]
+}
+
+GraphDataGenerator::~GraphDataGenerator()
+{
+ if (m_dataTimer) {
+ m_dataTimer->stop();
+ delete m_dataTimer;
+ }
+ delete m_graph;
+}
+
+void GraphDataGenerator::start()
+{
+#ifndef USE_STATIC_DATA
+ m_dataTimer = new QTimer();
+ m_dataTimer->setTimerType(Qt::CoarseTimer);
+ QObject::connect(m_dataTimer, &QTimer::timeout, this, &GraphDataGenerator::addRow);
+ m_dataTimer->start(0);
+ m_tableWidget->setFixedWidth(m_graph->width());
+#else
+ //! [8]
+ setupModel();
+
+ // Table needs to be shown before the size of its headers can be accurately obtained,
+ // so we postpone it a bit
+ m_dataTimer = new QTimer();
+ m_dataTimer->setSingleShot(true);
+ QObject::connect(m_dataTimer, &QTimer::timeout, this, &GraphDataGenerator::fixTableSize);
+ m_dataTimer->start(0);
+ //! [8]
+#endif
+}
+
+void GraphDataGenerator::setupModel()
+{
+ //! [9]
+ // Set up row and column names
+ QStringList days;
+ days << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday" << "Saturday" << "Sunday";
+ 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, 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, 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
+ //! [9]
+
+ // Add labels
+ //! [10]
+ m_graph->rowAxis()->setTitle("Week of year");
+ m_graph->columnAxis()->setTitle("Day of week");
+ m_graph->valueAxis()->setTitle("Hours spent on the Internet");
+ m_graph->valueAxis()->setLabelFormat("%.1f h");
+ //! [10]
+
+ //! [11]
+ m_tableWidget->setRowCount(5);
+ m_tableWidget->setColumnCount(7);
+ m_tableWidget->setHorizontalHeaderLabels(days);
+ m_tableWidget->setVerticalHeaderLabels(weeks);
+ m_tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ m_tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ m_tableWidget->setCurrentCell(-1, -1);
+ //! [11]
+
+ //! [12]
+ for (int week = 0; week < weeks.size(); week++) {
+ for (int day = 0; day < days.size(); day++) {
+ QModelIndex index = m_tableWidget->model()->index(week, day);
+ m_tableWidget->model()->setData(index, hours[week][day]);
+ }
+ }
+ //! [12]
+}
+
+void GraphDataGenerator::addRow()
+{
+ m_tableWidget->model()->insertRow(0);
+ if (m_tableWidget->model()->rowCount() > m_rowCount)
+ m_tableWidget->model()->removeRow(m_rowCount);
+ for (int i = 0; i < m_columnCount; i++) {
+ QModelIndex index = m_tableWidget->model()->index(0, i);
+ m_tableWidget->model()->setData(index,
+ ((float)i / (float)m_columnCount) / 2.0f + (float)(rand() % 30) / 100.0f);
+ }
+ m_tableWidget->resizeColumnsToContents();
+}
+
+//! [13]
+void GraphDataGenerator::selectFromTable(const QPoint &selection)
+{
+ m_tableWidget->setFocus();
+ m_tableWidget->setCurrentCell(selection.x(), selection.y());
+}
+//! [13]
+
+//! [14]
+void GraphDataGenerator::selectedFromTable(int currentRow, int currentColumn,
+ int previousRow, int previousColumn)
+{
+ Q_UNUSED(previousRow)
+ Q_UNUSED(previousColumn)
+ m_graph->seriesList().at(0)->setSelectedBar(QPoint(currentRow, currentColumn));
+}
+//! [14]
+
+void GraphDataGenerator::fixTableSize()
+{
+ int width = m_tableWidget->horizontalHeader()->length();
+ width += m_tableWidget->verticalHeader()->width();
+ m_tableWidget->setFixedWidth(width + 2);
+ int height = m_tableWidget->verticalHeader()->length();
+ height += m_tableWidget->horizontalHeader()->height();
+ m_tableWidget->setFixedHeight(height + 2);
+}
+
+int main(int argc, char **argv)
+{
+ //! [0]
+ QApplication app(argc, argv);
+ Q3DBars *graph = new Q3DBars();
+ QWidget *container = QWidget::createWindowContainer(graph);
+ //! [0]
+
+ QSize screenSize = graph->screen()->size();
+ container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 2));
+ container->setMaximumSize(screenSize);
+ container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ container->setFocusPolicy(Qt::StrongFocus);
+
+ //! [1]
+ QWidget widget;
+ QVBoxLayout *layout = new QVBoxLayout(&widget);
+ QTableWidget *tableWidget = new QTableWidget(&widget);
+ layout->addWidget(container, 1);
+ layout->addWidget(tableWidget, 1, Qt::AlignHCenter);
+ //! [1]
+
+ tableWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ tableWidget->setAlternatingRowColors(true);
+ widget.setWindowTitle(QStringLiteral("Hours spent on the Internet"));
+
+ //! [2]
+ // Since we are dealing with QTableWidget, the model will already have data sorted properly
+ // into rows and columns, so we simply set useModelCategories property to true to utilize this.
+ QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(tableWidget->model());
+ proxy->setUseModelCategories(true);
+ QBar3DSeries *series = new QBar3DSeries(proxy);
+ series->setMesh(QAbstract3DSeries::MeshPyramid);
+ graph->addSeries(series);
+ //! [2]
+
+ //! [3]
+ GraphDataGenerator generator(graph, tableWidget);
+ QObject::connect(series, &QBar3DSeries::selectedBarChanged, &generator,
+ &GraphDataGenerator::selectFromTable);
+ QObject::connect(tableWidget, &QTableWidget::currentCellChanged, &generator,
+ &GraphDataGenerator::selectedFromTable);
+ //! [3]
+
+ //! [4]
+ widget.show();
+ generator.start();
+ return app.exec();
+ //! [4]
+}