From 88cd10aa7b3559b092cf5575b0a17d002dc100ae Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 13 Feb 2014 09:59:52 +0200 Subject: Fix examples installation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Had to add one folder to the examples structure so installation works correctly. Change-Id: Ic92dfe9997413a6243abcf5eeba12744ba9e938c Reviewed-by: Tomi Korpipää --- .../itemmodel/doc/images/itemmodel-example-2.png | Bin 0 -> 78536 bytes .../itemmodel/doc/images/itemmodel-example.png | Bin 0 -> 45381 bytes .../itemmodel/doc/src/itemmodel.qdoc | 181 +++++++++++++ examples/datavisualization/itemmodel/itemmodel.pro | 7 + examples/datavisualization/itemmodel/main.cpp | 285 +++++++++++++++++++++ 5 files changed, 473 insertions(+) create mode 100644 examples/datavisualization/itemmodel/doc/images/itemmodel-example-2.png create mode 100644 examples/datavisualization/itemmodel/doc/images/itemmodel-example.png create mode 100644 examples/datavisualization/itemmodel/doc/src/itemmodel.qdoc create mode 100644 examples/datavisualization/itemmodel/itemmodel.pro create mode 100644 examples/datavisualization/itemmodel/main.cpp (limited to 'examples/datavisualization/itemmodel') 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 Binary files /dev/null and b/examples/datavisualization/itemmodel/doc/images/itemmodel-example-2.png 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 Binary files /dev/null and b/examples/datavisualization/itemmodel/doc/images/itemmodel-example.png 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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] +} -- cgit v1.2.3