diff options
author | Tomi Korpipää <tomi.korpipaa@digia.com> | 2013-10-09 08:55:09 +0300 |
---|---|---|
committer | Tomi Korpipää <tomi.korpipaa@digia.com> | 2013-10-09 09:13:06 +0300 |
commit | 5f02a038891db0cfd6a9fa08d7576141485e5d71 (patch) | |
tree | 383c8173283a043d0815f85d1745a771554fbc2d | |
parent | 36e42a1988e5c88c76c06415a1aaa19209a6e720 (diff) |
Renamed examples
Task-number: QTRD-2418
Change-Id: Ic0cae9a8caebcbd0f1cf57eb98fb7d543d7d7289
Change-Id: Ic0cae9a8caebcbd0f1cf57eb98fb7d543d7d7289
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
-rw-r--r-- | examples/bars/bars.pro | 7 | ||||
-rw-r--r-- | examples/bars/doc/images/bars-example.png | bin | 135559 -> 322046 bytes | |||
-rw-r--r-- | examples/bars/doc/src/bars.qdoc | 171 | ||||
-rw-r--r-- | examples/bars/graphmodifier.cpp (renamed from examples/widget/graphmodifier.cpp) | 0 | ||||
-rw-r--r-- | examples/bars/graphmodifier.h (renamed from examples/widget/graphmodifier.h) | 0 | ||||
-rw-r--r-- | examples/bars/main.cpp | 406 | ||||
-rw-r--r-- | examples/customproxy/customproxy.pro (renamed from examples/rainfall/rainfall.pro) | 3 | ||||
-rw-r--r-- | examples/customproxy/customproxy.qrc (renamed from examples/rainfall/rainfall.qrc) | 0 | ||||
-rw-r--r-- | examples/customproxy/data/raindata.txt (renamed from examples/rainfall/data/raindata.txt) | 0 | ||||
-rw-r--r-- | examples/customproxy/doc/images/customproxy-example.png | bin | 0 -> 399112 bytes | |||
-rw-r--r-- | examples/customproxy/doc/src/customproxy.qdoc (renamed from examples/rainfall/doc/src/rainfall.qdoc) | 8 | ||||
-rw-r--r-- | examples/customproxy/main.cpp (renamed from examples/rainfall/main.cpp) | 0 | ||||
-rw-r--r-- | examples/customproxy/rainfallgraph.cpp (renamed from examples/rainfall/rainfallgraph.cpp) | 0 | ||||
-rw-r--r-- | examples/customproxy/rainfallgraph.h (renamed from examples/rainfall/rainfallgraph.h) | 0 | ||||
-rw-r--r-- | examples/customproxy/variantbardatamapping.cpp (renamed from examples/rainfall/variantbardatamapping.cpp) | 0 | ||||
-rw-r--r-- | examples/customproxy/variantbardatamapping.h (renamed from examples/rainfall/variantbardatamapping.h) | 0 | ||||
-rw-r--r-- | examples/customproxy/variantbardataproxy.cpp (renamed from examples/rainfall/variantbardataproxy.cpp) | 0 | ||||
-rw-r--r-- | examples/customproxy/variantbardataproxy.h (renamed from examples/rainfall/variantbardataproxy.h) | 0 | ||||
-rw-r--r-- | examples/customproxy/variantdataset.cpp (renamed from examples/rainfall/variantdataset.cpp) | 0 | ||||
-rw-r--r-- | examples/customproxy/variantdataset.h (renamed from examples/rainfall/variantdataset.h) | 0 | ||||
-rw-r--r-- | examples/examples.pro | 4 | ||||
-rw-r--r-- | examples/itemmodel/doc/images/itemmodel-example-2.png (renamed from examples/bars/doc/images/bars-example-2.png) | bin | 198263 -> 198263 bytes | |||
-rw-r--r-- | examples/itemmodel/doc/images/itemmodel-example.png | bin | 0 -> 135559 bytes | |||
-rw-r--r-- | examples/itemmodel/doc/src/itemmodel.qdoc | 182 | ||||
-rw-r--r-- | examples/itemmodel/itemmodel.pro (renamed from examples/widget/widget.pro) | 8 | ||||
-rw-r--r-- | examples/itemmodel/main.cpp | 287 | ||||
-rw-r--r-- | examples/rainfall/doc/images/rainfall-example.png | bin | 294202 -> 0 bytes | |||
-rw-r--r-- | examples/widget/doc/images/widget-example.png | bin | 322046 -> 0 bytes | |||
-rw-r--r-- | examples/widget/doc/src/widget.qdoc | 159 | ||||
-rw-r--r-- | examples/widget/main.cpp | 211 | ||||
-rw-r--r-- | src/datavisualization/doc/src/qtdatavisualization.qdoc | 6 | ||||
-rw-r--r-- | src/datavisualization/engine/q3dbars.cpp | 4 |
32 files changed, 727 insertions, 729 deletions
diff --git a/examples/bars/bars.pro b/examples/bars/bars.pro index f319f690..e4e2c5fa 100644 --- a/examples/bars/bars.pro +++ b/examples/bars/bars.pro @@ -2,11 +2,12 @@ error( "Couldn't find the examples.pri file!" ) } -SOURCES += main.cpp - -INSTALLS += target +SOURCES += main.cpp graphmodifier.cpp +HEADERS += graphmodifier.h QT += widgets +INSTALLS += target + OTHER_FILES += doc/src/* \ doc/images/* diff --git a/examples/bars/doc/images/bars-example.png b/examples/bars/doc/images/bars-example.png Binary files differindex a87f4bdf..c2d4d598 100644 --- a/examples/bars/doc/images/bars-example.png +++ b/examples/bars/doc/images/bars-example.png diff --git a/examples/bars/doc/src/bars.qdoc b/examples/bars/doc/src/bars.qdoc index a8de709b..379aa871 100644 --- a/examples/bars/doc/src/bars.qdoc +++ b/examples/bars/doc/src/bars.qdoc @@ -20,22 +20,25 @@ \example bars \title Bars Example \ingroup qtdatavisualization_examples - \brief Using an item model as data source for Q3DBars. + \brief Using Q3DBars in a widget application. - The bars 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: + 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 How to create an application with Q3DBars and widgets - \li How to use QItemModelBarDataMapping and QItemModelBarDataProxy to set data to the graph - \li How to use a table widget to modify the data in the graph + \li Create an application with Q3DBars and some widgets + \li Use QBarDataProxy to set data to the graph + \li Adjust some graph properties using widget controls \endlist - \image bars-example-2.png + It also demonstrates how having negative bar values affects the graph. + + \image bars-example.png \section1 Creating the application - First, in main.cpp, we create a QApplication, instantiate Q3DBars and a window container for it: + First, in main.cpp, we create a QApplication, instantiate Q3DBars and a window container + for it: \snippet ../examples/bars/main.cpp 0 @@ -43,140 +46,114 @@ (Q3DBars, Q3DScatter, 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: + Then we'll create horizontal and vertical layouts. We'll add the graph and the vertical + layout into the horizontal one: \snippet ../examples/bars/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 QItemModelBarDataMapping and QItemModelBarDataProxy and give them to the - graph: - - \snippet ../examples/bars/main.cpp 2 - - Here we tell the mapping object to directly map model's rows and columns into 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 and the mapping object to the proxy. Finally we set the proxy as the active - data proxy for the graph. + 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 GraphDataGenerator (See \l {Setting up the graph} and - \l {Adding data to the graph} for details) and connect some signals between Q3DBars, - GraphDataGenerator and QTableWidget (See \l {Interacting with the data} for a closer look): + graph. Let's call it GraphModifier (See \l {Setting up the graph} and + \l {Adding data to the graph} for details): - \snippet ../examples/bars/main.cpp 3 + \snippet ../examples/bars/main.cpp 2 The application main is done and we can show the graph and start the event loop: - \snippet ../examples/bars/main.cpp 4 + \snippet ../examples/bars/main.cpp 3 \section1 Setting up the graph - Let's set up the visual attributes for the graph in the constructor of GraphDataGenerator: + Let's set up the graph in the constructor of the GraphModifier class we instantiated in the + application main: - \snippet ../examples/bars/main.cpp 5 - \snippet ../examples/bars/main.cpp 6 - \snippet ../examples/bars/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. + \snippet ../examples/bars/graphmodifier.cpp 0 - Then, we set the bar type to flat pyramids, overriding the default bar type. - We want to be able to select rows of data for a closer inspection, so we set the selection mode - to slice row. This means that whenever we select a bar in the graph, the whole row will be - displayed separately. + Let's take a closer look at parts of the code. - Next line sets the font to \c Impact. If your system doesn't have it, it will be replaced by - system default. + First we're creating the axes and the proxy into member variables to support changing them + easily later on, if we want to: - And finally, we set theme to \c Digia and camera position to \c {Preset Front}. Now the initial - graph settings are done. + \snippet ../examples/bars/graphmodifier.cpp 1 - \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. + Then we're setting some of the visual qualities for the graph: - \section1 Adding data to the graph + \snippet ../examples/bars/graphmodifier.cpp 2 - We created the data generator in the application main and gave it the graph and the table - widget as parameters: + We're also setting up the axes and adding them to the graph. Notice that we're not setting them + active yet: - \code GraphDataGenerator generator(graph, tableWidget); \endcode + \snippet ../examples/bars/graphmodifier.cpp 3 - 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: + And add the proxy. Note that we're not setting it active yet, but just adding it: - \code generator.start(); \endcode + \snippet ../examples/bars/graphmodifier.cpp 4 - Let's have a look at the contents of the \c start() method: + That concludes setting up the graph. - \snippet ../examples/bars/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 whole data timer implementation is not vital for the - application, so we won't take a closer look at it. It's just there to make the table look better. - - In \c setupModel() we first introduce the row and column labels, and the actual data: + \section1 Adding data to the graph - \snippet ../examples/bars/main.cpp 9 + At the end of the constructor there's a call: - Then we set up the axes: + \code resetTemperatureData(); \endcode - \snippet ../examples/bars/main.cpp 10 + The method is used to add data to the proxy: - The other lines there are pretty self-explanatory except for the one with the segment count. - We're setting it to five as we want the value axis (the Y-axis) to show more values than just - the lowest and the highest. + \snippet ../examples/bars/graphmodifier.cpp 5 - Next we will set up the table widget: + Now the data is in the proxy, but not in the graph. We have not set the proxy active yet. - \snippet ../examples/bars/main.cpp 11 + In application main, we called \c {modifier->start()} after constructing all the necessary + objects. This is what is done in it: - After that all that's left is adding the data to the table widget: + \snippet ../examples/bars/graphmodifier.cpp 6 - \snippet ../examples/bars/main.cpp 12 + Finally we set the proxy and the axes active. Now our graph has the data and is ready to be + used. - Now we have a bar graph and a table widget, both displaying the same data. + \section1 Using widgets to control the graph - 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: + 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: - \snippet ../examples/bars/main.cpp 2 - - We created QItemModelBarDataMapping and QItemModelBarDataProxy instances, and gave the proxy - the model of the table widget and the model mapping we just created. Then we set the proxy as - the active proxy for the graph. The proxy maps the rows and the columns in the model of the table - widget into rows and columns for itself using the model mapping, and the graph gets the data - to be displayed from its active proxy. + \snippet ../examples/bars/main.cpp 4 - \section1 Interacting with the data + We can use these to rotate the graph using slider widgets instead of just using the mouse or + touch. - We made a couple of signal connections in the application main earlier: + Let's add them to the vertical layout we created earlier: - \snippet ../examples/bars/main.cpp 3 + \snippet ../examples/bars/main.cpp 5 - Now we'll find out what these were for. + Then we'll connect them to methods in GraphModifier: - The first one connects a signal from Q3DBars to the GraphDataGenerator. Signal - Q3DBars::selectedBarPosChanged() is emitted when a bar is selected from the graph. We connect - that to a method in the data generator that selects the same data item in the table widget: + \snippet ../examples/bars/main.cpp 6 - \snippet ../examples/bars/main.cpp 13 + Here are the methods in GraphModifier the signals were connected to: - 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 graph: + \snippet ../examples/bars/graphmodifier.cpp 7 - \snippet ../examples/bars/main.cpp 14 + Now these two sliders can be used to rotate the graph. - 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 active proxy with mapping between the data - in the table widget and itself. + And so we have an application in which we can control: - \image bars-example.png + \list + \li Graph rotation + \li Label style + \li Camera preset + \li Background visibility + \li Grid visibility + \li Bar shading smoothness + \li Bar style + \li Selection mode + \li Theme + \li Shadow quality + \li Font + \li Font size + \endlist \section1 Example contents + */ diff --git a/examples/widget/graphmodifier.cpp b/examples/bars/graphmodifier.cpp index 0b33bde0..0b33bde0 100644 --- a/examples/widget/graphmodifier.cpp +++ b/examples/bars/graphmodifier.cpp diff --git a/examples/widget/graphmodifier.h b/examples/bars/graphmodifier.h index 2e18ffd2..2e18ffd2 100644 --- a/examples/widget/graphmodifier.h +++ b/examples/bars/graphmodifier.h diff --git a/examples/bars/main.cpp b/examples/bars/main.cpp index 6ab685ed..158244b4 100644 --- a/examples/bars/main.cpp +++ b/examples/bars/main.cpp @@ -16,272 +16,196 @@ ** ****************************************************************************/ -#include <QtDataVisualization/q3dbars.h> -#include <QtDataVisualization/q3dcategoryaxis.h> -#include <QtDataVisualization/qitemmodelbardataproxy.h> -#include <QtDataVisualization/q3dvalueaxis.h> -#include <QtDataVisualization/q3dscene.h> -#include <QtDataVisualization/q3dcamera.h> +#include "graphmodifier.h" #include <QApplication> +#include <QWidget> +#include <QHBoxLayout> #include <QVBoxLayout> -#include <QTableWidget> +#include <QPushButton> +#include <QCheckBox> +#include <QSlider> +#include <QFontComboBox> +#include <QLabel> #include <QScreen> -#include <QTimer> -#include <QFont> -#include <QDebug> -#include <QHeaderView> +#include <QFontDatabase> -#define USE_STATIC_DATA - -using namespace QtDataVisualization; - -class GraphDataGenerator : public QObject +int main(int argc, char **argv) { -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(); + //! [0] + QApplication app(argc, argv); + Q3DBars *widgetgraph = new Q3DBars(); + QWidget *container = QWidget::createWindowContainer(widgetgraph); + //! [0] -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 -}; + 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); -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.0); - m_graph->setBarSpacing(QSizeF(0.2, 0.2)); + //! [1] + QWidget *widget = new QWidget; + QHBoxLayout *hLayout = new QHBoxLayout(widget); + QVBoxLayout *vLayout = new QVBoxLayout(); + hLayout->addWidget(container, 1); + hLayout->addLayout(vLayout); + //! [1] - // Set bar type to flat pyramids - m_graph->setBarType(QDataVis::MeshStylePyramids, false); + widget->setWindowTitle(QStringLiteral("Average temperatures in Oulu, Finland (2006-2012)")); + + QComboBox *themeList = new QComboBox(widget); + themeList->addItem(QStringLiteral("Qt")); + themeList->addItem(QStringLiteral("Primary Colors")); + themeList->addItem(QStringLiteral("Digia")); + themeList->addItem(QStringLiteral("Stone Moss")); + themeList->addItem(QStringLiteral("Army Blue")); + themeList->addItem(QStringLiteral("Retro")); + themeList->addItem(QStringLiteral("Ebony")); + themeList->addItem(QStringLiteral("Isabelle")); + themeList->setCurrentIndex(0); + + QPushButton *labelButton = new QPushButton(widget); + labelButton->setText(QStringLiteral("Change label style")); + + QCheckBox *smoothCheckBox = new QCheckBox(widget); + smoothCheckBox->setText(QStringLiteral("Smooth bars")); + smoothCheckBox->setChecked(false); + + QComboBox *barStyleList = new QComboBox(widget); + barStyleList->addItem(QStringLiteral("Bars")); + barStyleList->addItem(QStringLiteral("Pyramids")); + barStyleList->addItem(QStringLiteral("Cones")); + barStyleList->addItem(QStringLiteral("Cylinders")); + barStyleList->addItem(QStringLiteral("Beveled Bars")); + barStyleList->setCurrentIndex(4); + + QPushButton *cameraButton = new QPushButton(widget); + cameraButton->setText(QStringLiteral("Change camera preset")); + + QComboBox *selectionModeList = new QComboBox(widget); + selectionModeList->addItem(QStringLiteral("None")); + selectionModeList->addItem(QStringLiteral("Bar")); + selectionModeList->addItem(QStringLiteral("Bar and Row")); + selectionModeList->addItem(QStringLiteral("Bar and Column")); + selectionModeList->addItem(QStringLiteral("Bar, Row and Column")); + selectionModeList->addItem(QStringLiteral("Slice into Row")); + selectionModeList->addItem(QStringLiteral("Slice into Column")); + selectionModeList->setCurrentIndex(1); + + QCheckBox *backgroundCheckBox = new QCheckBox(widget); + backgroundCheckBox->setText(QStringLiteral("Show background")); + backgroundCheckBox->setChecked(false); + + QCheckBox *gridCheckBox = new QCheckBox(widget); + gridCheckBox->setText(QStringLiteral("Show grid")); + gridCheckBox->setChecked(true); - //! [5] + //! [4] + QSlider *rotationSliderX = new QSlider(Qt::Horizontal, widget); + rotationSliderX->setTickInterval(30); + rotationSliderX->setTickPosition(QSlider::TicksBelow); + rotationSliderX->setMinimum(-180); + rotationSliderX->setValue(0); + rotationSliderX->setMaximum(180); + QSlider *rotationSliderY = new QSlider(Qt::Horizontal, widget); + rotationSliderY->setTickInterval(15); + rotationSliderY->setTickPosition(QSlider::TicksAbove); + rotationSliderY->setMinimum(-90); + rotationSliderY->setValue(0); + rotationSliderY->setMaximum(90); + //! [4] -#ifndef USE_STATIC_DATA - // Set up sample space; make it as deep as it's wide - m_graph->setDataWindow(m_rowCount, m_columnCount); - m_tableWidget->setColumnCount(m_columnCount); + QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, widget); + fontSizeSlider->setTickInterval(10); + fontSizeSlider->setTickPosition(QSlider::TicksBelow); + fontSizeSlider->setMinimum(1); + fontSizeSlider->setValue(30); + fontSizeSlider->setMaximum(100); + + QFontComboBox *fontList = new QFontComboBox(widget); + fontList->setCurrentFont(QFont("Times New Roman")); + + QComboBox *shadowQuality = new QComboBox(widget); + shadowQuality->addItem(QStringLiteral("None")); + shadowQuality->addItem(QStringLiteral("Low")); + shadowQuality->addItem(QStringLiteral("Medium")); + shadowQuality->addItem(QStringLiteral("High")); + shadowQuality->addItem(QStringLiteral("Low Soft")); + shadowQuality->addItem(QStringLiteral("Medium Soft")); + shadowQuality->addItem(QStringLiteral("High Soft")); + shadowQuality->setCurrentIndex(5); - // Set selection mode to full - m_graph->setSelectionMode(QDataVis::SelectionModeItemRowAndColumn); + //! [5] + vLayout->addWidget(new QLabel(QStringLiteral("Rotate horizontally"))); + vLayout->addWidget(rotationSliderX, 0, Qt::AlignTop); + 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(backgroundCheckBox); + vLayout->addWidget(gridCheckBox); + vLayout->addWidget(smoothCheckBox, 0, Qt::AlignTop); + vLayout->addWidget(new QLabel(QStringLiteral("Change bar style"))); + vLayout->addWidget(barStyleList); + vLayout->addWidget(new QLabel(QStringLiteral("Change selection mode"))); + vLayout->addWidget(selectionModeList); + vLayout->addWidget(new QLabel(QStringLiteral("Change theme"))); + vLayout->addWidget(themeList); + vLayout->addWidget(new QLabel(QStringLiteral("Adjust shadow quality"))); + vLayout->addWidget(shadowQuality); + vLayout->addWidget(new QLabel(QStringLiteral("Change font"))); + vLayout->addWidget(fontList); + vLayout->addWidget(new QLabel(QStringLiteral("Adjust font size"))); + vLayout->addWidget(fontSizeSlider, 1, Qt::AlignTop); - // Hide axis labels by explicitly setting one empty string as label list - m_graph->rowAxis()->setCategoryLabels(QStringList(QString())); - m_graph->columnAxis()->setCategoryLabels(QStringList(QString())); + //! [2] + GraphModifier *modifier = new GraphModifier(widgetgraph); + //! [2] - m_graph->activeDataProxy()->setItemLabelFormat(QStringLiteral("@valueLabel")); -#else //! [6] - - // Set selection mode to slice row - m_graph->setSelectionMode(QDataVis::SelectionModeSliceRow); - - // Set font - m_graph->setFont(QFont("Impact", 20)); - + QObject::connect(rotationSliderX, &QSlider::valueChanged, modifier, &GraphModifier::rotateX); + QObject::connect(rotationSliderY, &QSlider::valueChanged, modifier, &GraphModifier::rotateY); //! [6] -#endif - //! [7] + QObject::connect(labelButton, &QPushButton::clicked, modifier, + &GraphModifier::changeLabelStyle); + QObject::connect(cameraButton, &QPushButton::clicked, modifier, + &GraphModifier::changePresetCamera); - // Set theme - m_graph->setTheme(QDataVis::ThemeDigia); + QObject::connect(backgroundCheckBox, &QCheckBox::stateChanged, modifier, + &GraphModifier::setBackgroundEnabled); + QObject::connect(gridCheckBox, &QCheckBox::stateChanged, modifier, + &GraphModifier::setGridEnabled); + QObject::connect(smoothCheckBox, &QCheckBox::stateChanged, modifier, + &GraphModifier::setSmoothBars); - // Set preset camera position - m_graph->scene()->activeCamera()->setCameraPreset(QDataVis::CameraPresetFront); - //! [7] -} + QObject::connect(barStyleList, SIGNAL(currentIndexChanged(int)), modifier, + SLOT(changeStyle(int))); -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 -} + QObject::connect(selectionModeList, SIGNAL(currentIndexChanged(int)), modifier, + SLOT(changeSelectionMode(int))); -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.0, 1.0, 3.0, 0.2, 1.0, 5.0, 10.0}, // week 1 - {0.5, 1.0, 3.0, 1.0, 2.0, 2.0, 3.0}, // week 2 - {1.0, 1.0, 2.0, 1.0, 4.0, 4.0, 4.0}, // week 3 - {0.0, 1.0, 0.0, 0.0, 2.0, 2.0, 0.3}, // week 4 - {3.0, 3.0, 6.0, 2.0, 2.0, 1.0, 1.0}}; // week 5 - //! [9] + QObject::connect(themeList, SIGNAL(currentIndexChanged(int)), modifier, + SLOT(changeTheme(int))); - // 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()->setSegmentCount(5); - m_graph->valueAxis()->setLabelFormat("%.1f h"); - //! [10] + QObject::connect(shadowQuality, SIGNAL(currentIndexChanged(int)), modifier, + SLOT(changeShadowQuality(int))); - //! [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] + QObject::connect(modifier, &GraphModifier::shadowQualityChanged, shadowQuality, + &QComboBox::setCurrentIndex); + QObject::connect(widgetgraph, &Q3DBars::shadowQualityChanged, modifier, + &GraphModifier::shadowQualityUpdatedByVisual); - //! [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] -} + QObject::connect(fontSizeSlider, &QSlider::valueChanged, modifier, + &GraphModifier::changeFontSize); + QObject::connect(fontList, &QFontComboBox::currentFontChanged, modifier, + &GraphModifier::changeFont); -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, - ((qreal)i / (qreal)m_columnCount) / 2.0 + (qreal)(rand() % 30) / 100.0); - } - 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->setSelectedBarPos(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 - // in rows and columns, so create a mapping to utilize this. - QItemModelBarDataMapping *mapping = new QItemModelBarDataMapping; - mapping->setUseModelCategories(true); - QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(tableWidget->model(), mapping); - graph->setActiveDataProxy(proxy); - //! [2] - - //! [3] - GraphDataGenerator generator(graph, tableWidget); - QObject::connect(graph, &Q3DBars::selectedBarPosChanged, &generator, - &GraphDataGenerator::selectFromTable); - QObject::connect(tableWidget, &QTableWidget::currentCellChanged, &generator, - &GraphDataGenerator::selectedFromTable); //! [3] - - //! [4] - widget.show(); - generator.start(); + widget->show(); + modifier->start(); return app.exec(); - //! [4] + //! [3] } diff --git a/examples/rainfall/rainfall.pro b/examples/customproxy/customproxy.pro index 0a2e1498..2b764a41 100644 --- a/examples/rainfall/rainfall.pro +++ b/examples/customproxy/customproxy.pro @@ -16,8 +16,7 @@ HEADERS += \ INSTALLS += target -RESOURCES += \ - rainfall.qrc +RESOURCES += customproxy.qrc OTHER_FILES += data/raindata.txt \ doc/src/* \ diff --git a/examples/rainfall/rainfall.qrc b/examples/customproxy/customproxy.qrc index 53cd4915..53cd4915 100644 --- a/examples/rainfall/rainfall.qrc +++ b/examples/customproxy/customproxy.qrc diff --git a/examples/rainfall/data/raindata.txt b/examples/customproxy/data/raindata.txt index 531d66be..531d66be 100644 --- a/examples/rainfall/data/raindata.txt +++ b/examples/customproxy/data/raindata.txt diff --git a/examples/customproxy/doc/images/customproxy-example.png b/examples/customproxy/doc/images/customproxy-example.png Binary files differnew file mode 100644 index 00000000..6706ea1c --- /dev/null +++ b/examples/customproxy/doc/images/customproxy-example.png diff --git a/examples/rainfall/doc/src/rainfall.qdoc b/examples/customproxy/doc/src/customproxy.qdoc index cc59b238..8bb02105 100644 --- a/examples/rainfall/doc/src/rainfall.qdoc +++ b/examples/customproxy/doc/src/customproxy.qdoc @@ -17,14 +17,14 @@ ****************************************************************************/ /*! - \example rainfall - \title Rainfall Example + \example customproxy + \title Custom Proxy Example \ingroup qtdatavisualization_examples \brief Using Q3DBars with a custom proxy. - The rainfall example shows how to create a custom proxy to use with Q3DBars. + The custom proxy example shows how to create a custom proxy to use with Q3DBars. - \image rainfall-example.png + \image customproxy-example.png TODO */ diff --git a/examples/rainfall/main.cpp b/examples/customproxy/main.cpp index 54ea63e9..54ea63e9 100644 --- a/examples/rainfall/main.cpp +++ b/examples/customproxy/main.cpp diff --git a/examples/rainfall/rainfallgraph.cpp b/examples/customproxy/rainfallgraph.cpp index 41f72464..41f72464 100644 --- a/examples/rainfall/rainfallgraph.cpp +++ b/examples/customproxy/rainfallgraph.cpp diff --git a/examples/rainfall/rainfallgraph.h b/examples/customproxy/rainfallgraph.h index 6317ab71..6317ab71 100644 --- a/examples/rainfall/rainfallgraph.h +++ b/examples/customproxy/rainfallgraph.h diff --git a/examples/rainfall/variantbardatamapping.cpp b/examples/customproxy/variantbardatamapping.cpp index 0c2f146c..0c2f146c 100644 --- a/examples/rainfall/variantbardatamapping.cpp +++ b/examples/customproxy/variantbardatamapping.cpp diff --git a/examples/rainfall/variantbardatamapping.h b/examples/customproxy/variantbardatamapping.h index 0204ddc8..0204ddc8 100644 --- a/examples/rainfall/variantbardatamapping.h +++ b/examples/customproxy/variantbardatamapping.h diff --git a/examples/rainfall/variantbardataproxy.cpp b/examples/customproxy/variantbardataproxy.cpp index c907a1e3..c907a1e3 100644 --- a/examples/rainfall/variantbardataproxy.cpp +++ b/examples/customproxy/variantbardataproxy.cpp diff --git a/examples/rainfall/variantbardataproxy.h b/examples/customproxy/variantbardataproxy.h index b931aa5c..b931aa5c 100644 --- a/examples/rainfall/variantbardataproxy.h +++ b/examples/customproxy/variantbardataproxy.h diff --git a/examples/rainfall/variantdataset.cpp b/examples/customproxy/variantdataset.cpp index f73d83f8..f73d83f8 100644 --- a/examples/rainfall/variantdataset.cpp +++ b/examples/customproxy/variantdataset.cpp diff --git a/examples/rainfall/variantdataset.h b/examples/customproxy/variantdataset.h index 7906d4f5..7906d4f5 100644 --- a/examples/rainfall/variantdataset.h +++ b/examples/customproxy/variantdataset.h diff --git a/examples/examples.pro b/examples/examples.pro index e5001049..7d9f306a 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -4,8 +4,8 @@ SUBDIRS += qmlbars \ qmlsurface !android: { SUBDIRS += bars \ - rainfall \ - widget \ + customproxy \ + itemmodel \ scatter \ surface } diff --git a/examples/bars/doc/images/bars-example-2.png b/examples/itemmodel/doc/images/itemmodel-example-2.png Binary files differindex 2083a8e0..2083a8e0 100644 --- a/examples/bars/doc/images/bars-example-2.png +++ b/examples/itemmodel/doc/images/itemmodel-example-2.png diff --git a/examples/itemmodel/doc/images/itemmodel-example.png b/examples/itemmodel/doc/images/itemmodel-example.png Binary files differnew file mode 100644 index 00000000..a87f4bdf --- /dev/null +++ b/examples/itemmodel/doc/images/itemmodel-example.png diff --git a/examples/itemmodel/doc/src/itemmodel.qdoc b/examples/itemmodel/doc/src/itemmodel.qdoc new file mode 100644 index 00000000..f014bfea --- /dev/null +++ b/examples/itemmodel/doc/src/itemmodel.qdoc @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the 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 How to create an application with Q3DBars and widgets + \li How to use QItemModelBarDataMapping and QItemModelBarDataProxy to set data to the graph + \li How to use a table widget to modify the data in the graph + \endlist + + \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, 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 QItemModelBarDataMapping and QItemModelBarDataProxy and give them to the + graph: + + \snippet ../examples/itemmodel/main.cpp 2 + + Here we tell the mapping object to directly map model's rows and columns into 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 and the mapping object to the proxy. Finally we set the proxy as the active + data proxy for the graph. + + Next, let's create another class to handle the data addition and other interaction with the + graph. Let's call it GraphDataGenerator (See \l {Setting up the graph} and + \l {Adding data to the graph} for details) and connect some signals between Q3DBars, + 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 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. + + Then, we set the bar type to flat pyramids, overriding the default bar type. + We want to be able to select rows of data for a closer inspection, so we set the selection mode + to slice row. This means that whenever we select a bar in the graph, the whole row will be + displayed separately. + + Next line sets the font to \c Impact. If your system doesn't have it, it will be replaced by + system default. + + And finally, we set theme to \c Digia and camera position to \c {Preset Front}. 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 whole data timer implementation is not vital for the + application, so we won't take a closer look at it. It's just there to make the table 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 + + The other lines there are pretty self-explanatory except for the one with the segment count. + We're setting it to five as we want the value axis (the Y-axis) to show more values than just + the lowest and the highest. + + 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 QItemModelBarDataMapping and QItemModelBarDataProxy instances, and gave the proxy + the model of the table widget and the model mapping we just created. Then we set the proxy as + the active proxy for the graph. The proxy maps the rows and the columns in the model of the table + widget into rows and columns for itself using the model mapping, and the graph gets the data + to be displayed from its active 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 GraphDataGenerator. Signal + Q3DBars::selectedBarPosChanged() is emitted when a bar is selected from the graph. 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 graph: + + \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 active proxy with mapping between the data + in the table widget and itself. + + \image itemmodel-example.png + + \section1 Example contents +*/ diff --git a/examples/widget/widget.pro b/examples/itemmodel/itemmodel.pro index c9feb187..f319f690 100644 --- a/examples/widget/widget.pro +++ b/examples/itemmodel/itemmodel.pro @@ -2,13 +2,11 @@ error( "Couldn't find the examples.pri file!" ) } -SOURCES += main.cpp graphmodifier.cpp -HEADERS += graphmodifier.h - -QT += widgets +SOURCES += main.cpp INSTALLS += target +QT += widgets + OTHER_FILES += doc/src/* \ doc/images/* - diff --git a/examples/itemmodel/main.cpp b/examples/itemmodel/main.cpp new file mode 100644 index 00000000..6ab685ed --- /dev/null +++ b/examples/itemmodel/main.cpp @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the 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/q3dcategoryaxis.h> +#include <QtDataVisualization/qitemmodelbardataproxy.h> +#include <QtDataVisualization/q3dvalueaxis.h> +#include <QtDataVisualization/q3dscene.h> +#include <QtDataVisualization/q3dcamera.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.0); + m_graph->setBarSpacing(QSizeF(0.2, 0.2)); + + // Set bar type to flat pyramids + m_graph->setBarType(QDataVis::MeshStylePyramids, false); + + //! [5] + +#ifndef USE_STATIC_DATA + // Set up sample space; make it as deep as it's wide + m_graph->setDataWindow(m_rowCount, m_columnCount); + m_tableWidget->setColumnCount(m_columnCount); + + // Set selection mode to full + m_graph->setSelectionMode(QDataVis::SelectionModeItemRowAndColumn); + + // Hide axis labels by explicitly setting one empty string as label list + m_graph->rowAxis()->setCategoryLabels(QStringList(QString())); + m_graph->columnAxis()->setCategoryLabels(QStringList(QString())); + + m_graph->activeDataProxy()->setItemLabelFormat(QStringLiteral("@valueLabel")); +#else + //! [6] + + // Set selection mode to slice row + m_graph->setSelectionMode(QDataVis::SelectionModeSliceRow); + + // Set font + m_graph->setFont(QFont("Impact", 20)); + + //! [6] +#endif + + //! [7] + + // Set theme + m_graph->setTheme(QDataVis::ThemeDigia); + + // Set preset camera position + m_graph->scene()->activeCamera()->setCameraPreset(QDataVis::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.0, 1.0, 3.0, 0.2, 1.0, 5.0, 10.0}, // week 1 + {0.5, 1.0, 3.0, 1.0, 2.0, 2.0, 3.0}, // week 2 + {1.0, 1.0, 2.0, 1.0, 4.0, 4.0, 4.0}, // week 3 + {0.0, 1.0, 0.0, 0.0, 2.0, 2.0, 0.3}, // week 4 + {3.0, 3.0, 6.0, 2.0, 2.0, 1.0, 1.0}}; // 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()->setSegmentCount(5); + 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, + ((qreal)i / (qreal)m_columnCount) / 2.0 + (qreal)(rand() % 30) / 100.0); + } + 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->setSelectedBarPos(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 + // in rows and columns, so create a mapping to utilize this. + QItemModelBarDataMapping *mapping = new QItemModelBarDataMapping; + mapping->setUseModelCategories(true); + QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(tableWidget->model(), mapping); + graph->setActiveDataProxy(proxy); + //! [2] + + //! [3] + GraphDataGenerator generator(graph, tableWidget); + QObject::connect(graph, &Q3DBars::selectedBarPosChanged, &generator, + &GraphDataGenerator::selectFromTable); + QObject::connect(tableWidget, &QTableWidget::currentCellChanged, &generator, + &GraphDataGenerator::selectedFromTable); + //! [3] + + //! [4] + widget.show(); + generator.start(); + return app.exec(); + //! [4] +} diff --git a/examples/rainfall/doc/images/rainfall-example.png b/examples/rainfall/doc/images/rainfall-example.png Binary files differdeleted file mode 100644 index f4087927..00000000 --- a/examples/rainfall/doc/images/rainfall-example.png +++ /dev/null diff --git a/examples/widget/doc/images/widget-example.png b/examples/widget/doc/images/widget-example.png Binary files differdeleted file mode 100644 index c2d4d598..00000000 --- a/examples/widget/doc/images/widget-example.png +++ /dev/null diff --git a/examples/widget/doc/src/widget.qdoc b/examples/widget/doc/src/widget.qdoc deleted file mode 100644 index b67386c7..00000000 --- a/examples/widget/doc/src/widget.qdoc +++ /dev/null @@ -1,159 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the 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 widget - \title Widget Example - \ingroup qtdatavisualization_examples - \brief Using Q3DBars in a widget application. - - The widget 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 QBarDataProxy to set data to the graph - \li Adjust some graph properties using widget controls - \endlist - - It also demonstrates how having negative bar values affects the graph. - - \image widget-example.png - - \section1 Creating the application - - First, in main.cpp, we create a QApplication, instantiate Q3DBars and a window container - for it: - - \snippet ../examples/widget/main.cpp 0 - - The call to QWidget::createWindowContainer is required, as all data visualization types - (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 ../examples/widget/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 GraphModifier (See \l {Setting up the graph} and - \l {Adding data to the graph} for details): - - \snippet ../examples/widget/main.cpp 2 - - The application main is done and we can show the graph and start the event loop: - - \snippet ../examples/widget/main.cpp 3 - - \section1 Setting up the graph - - Let's set up the graph in the constructor of the GraphModifier class we instantiated in the - application main: - - \snippet ../examples/widget/graphmodifier.cpp 0 - - Let's take a closer look at parts of the code. - - First we're creating the axes and the proxy into member variables to support changing them - easily later on, if we want to: - - \snippet ../examples/widget/graphmodifier.cpp 1 - - Then we're setting some of the visual qualities for the graph: - - \snippet ../examples/widget/graphmodifier.cpp 2 - - We're also setting up the axes and adding them to the graph. Notice that we're not setting them - active yet: - - \snippet ../examples/widget/graphmodifier.cpp 3 - - And add the proxy. Note that we're not setting it active yet, but just adding it: - - \snippet ../examples/widget/graphmodifier.cpp 4 - - That concludes setting up the graph. - - \section1 Adding data to the graph - - At the end of the constructor there's a call: - - \code resetTemperatureData(); \endcode - - The method is used to add data to the proxy: - - \snippet ../examples/widget/graphmodifier.cpp 5 - - Now the data is in the proxy, but not in the graph. We have not set the proxy active yet. - - In application main, we called \c {modifier->start()} after constructing all the necessary - objects. This is what is done in it: - - \snippet ../examples/widget/graphmodifier.cpp 6 - - Finally we set the proxy and the axes active. Now our graph has the data and is ready to be - used. - - \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: - - \snippet ../examples/widget/main.cpp 4 - - We can use these to rotate the graph using slider widgets instead of just using the mouse or - touch. - - Let's add them to the vertical layout we created earlier: - - \snippet ../examples/widget/main.cpp 5 - - Then we'll connect them to methods in GraphModifier: - - \snippet ../examples/widget/main.cpp 6 - - Here are the methods in GraphModifier the signals were connected to: - - \snippet ../examples/widget/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 Bar style - \li Selection mode - \li Theme - \li Shadow quality - \li Font - \li Font size - \endlist - - \section1 Example contents - -*/ diff --git a/examples/widget/main.cpp b/examples/widget/main.cpp deleted file mode 100644 index 158244b4..00000000 --- a/examples/widget/main.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the 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 "graphmodifier.h" - -#include <QApplication> -#include <QWidget> -#include <QHBoxLayout> -#include <QVBoxLayout> -#include <QPushButton> -#include <QCheckBox> -#include <QSlider> -#include <QFontComboBox> -#include <QLabel> -#include <QScreen> -#include <QFontDatabase> - -int main(int argc, char **argv) -{ - //! [0] - QApplication app(argc, argv); - Q3DBars *widgetgraph = new Q3DBars(); - QWidget *container = QWidget::createWindowContainer(widgetgraph); - //! [0] - - 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); - - //! [1] - QWidget *widget = new QWidget; - QHBoxLayout *hLayout = new QHBoxLayout(widget); - QVBoxLayout *vLayout = new QVBoxLayout(); - hLayout->addWidget(container, 1); - hLayout->addLayout(vLayout); - //! [1] - - widget->setWindowTitle(QStringLiteral("Average temperatures in Oulu, Finland (2006-2012)")); - - QComboBox *themeList = new QComboBox(widget); - themeList->addItem(QStringLiteral("Qt")); - themeList->addItem(QStringLiteral("Primary Colors")); - themeList->addItem(QStringLiteral("Digia")); - themeList->addItem(QStringLiteral("Stone Moss")); - themeList->addItem(QStringLiteral("Army Blue")); - themeList->addItem(QStringLiteral("Retro")); - themeList->addItem(QStringLiteral("Ebony")); - themeList->addItem(QStringLiteral("Isabelle")); - themeList->setCurrentIndex(0); - - QPushButton *labelButton = new QPushButton(widget); - labelButton->setText(QStringLiteral("Change label style")); - - QCheckBox *smoothCheckBox = new QCheckBox(widget); - smoothCheckBox->setText(QStringLiteral("Smooth bars")); - smoothCheckBox->setChecked(false); - - QComboBox *barStyleList = new QComboBox(widget); - barStyleList->addItem(QStringLiteral("Bars")); - barStyleList->addItem(QStringLiteral("Pyramids")); - barStyleList->addItem(QStringLiteral("Cones")); - barStyleList->addItem(QStringLiteral("Cylinders")); - barStyleList->addItem(QStringLiteral("Beveled Bars")); - barStyleList->setCurrentIndex(4); - - QPushButton *cameraButton = new QPushButton(widget); - cameraButton->setText(QStringLiteral("Change camera preset")); - - QComboBox *selectionModeList = new QComboBox(widget); - selectionModeList->addItem(QStringLiteral("None")); - selectionModeList->addItem(QStringLiteral("Bar")); - selectionModeList->addItem(QStringLiteral("Bar and Row")); - selectionModeList->addItem(QStringLiteral("Bar and Column")); - selectionModeList->addItem(QStringLiteral("Bar, Row and Column")); - selectionModeList->addItem(QStringLiteral("Slice into Row")); - selectionModeList->addItem(QStringLiteral("Slice into Column")); - selectionModeList->setCurrentIndex(1); - - QCheckBox *backgroundCheckBox = new QCheckBox(widget); - backgroundCheckBox->setText(QStringLiteral("Show background")); - backgroundCheckBox->setChecked(false); - - QCheckBox *gridCheckBox = new QCheckBox(widget); - gridCheckBox->setText(QStringLiteral("Show grid")); - gridCheckBox->setChecked(true); - - //! [4] - QSlider *rotationSliderX = new QSlider(Qt::Horizontal, widget); - rotationSliderX->setTickInterval(30); - rotationSliderX->setTickPosition(QSlider::TicksBelow); - rotationSliderX->setMinimum(-180); - rotationSliderX->setValue(0); - rotationSliderX->setMaximum(180); - QSlider *rotationSliderY = new QSlider(Qt::Horizontal, widget); - rotationSliderY->setTickInterval(15); - rotationSliderY->setTickPosition(QSlider::TicksAbove); - rotationSliderY->setMinimum(-90); - rotationSliderY->setValue(0); - rotationSliderY->setMaximum(90); - //! [4] - - QSlider *fontSizeSlider = new QSlider(Qt::Horizontal, widget); - fontSizeSlider->setTickInterval(10); - fontSizeSlider->setTickPosition(QSlider::TicksBelow); - fontSizeSlider->setMinimum(1); - fontSizeSlider->setValue(30); - fontSizeSlider->setMaximum(100); - - QFontComboBox *fontList = new QFontComboBox(widget); - fontList->setCurrentFont(QFont("Times New Roman")); - - QComboBox *shadowQuality = new QComboBox(widget); - shadowQuality->addItem(QStringLiteral("None")); - shadowQuality->addItem(QStringLiteral("Low")); - shadowQuality->addItem(QStringLiteral("Medium")); - shadowQuality->addItem(QStringLiteral("High")); - shadowQuality->addItem(QStringLiteral("Low Soft")); - shadowQuality->addItem(QStringLiteral("Medium Soft")); - shadowQuality->addItem(QStringLiteral("High Soft")); - shadowQuality->setCurrentIndex(5); - - //! [5] - vLayout->addWidget(new QLabel(QStringLiteral("Rotate horizontally"))); - vLayout->addWidget(rotationSliderX, 0, Qt::AlignTop); - 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(backgroundCheckBox); - vLayout->addWidget(gridCheckBox); - vLayout->addWidget(smoothCheckBox, 0, Qt::AlignTop); - vLayout->addWidget(new QLabel(QStringLiteral("Change bar style"))); - vLayout->addWidget(barStyleList); - vLayout->addWidget(new QLabel(QStringLiteral("Change selection mode"))); - vLayout->addWidget(selectionModeList); - vLayout->addWidget(new QLabel(QStringLiteral("Change theme"))); - vLayout->addWidget(themeList); - vLayout->addWidget(new QLabel(QStringLiteral("Adjust shadow quality"))); - vLayout->addWidget(shadowQuality); - vLayout->addWidget(new QLabel(QStringLiteral("Change font"))); - vLayout->addWidget(fontList); - vLayout->addWidget(new QLabel(QStringLiteral("Adjust font size"))); - vLayout->addWidget(fontSizeSlider, 1, Qt::AlignTop); - - //! [2] - GraphModifier *modifier = new GraphModifier(widgetgraph); - //! [2] - - //! [6] - QObject::connect(rotationSliderX, &QSlider::valueChanged, modifier, &GraphModifier::rotateX); - QObject::connect(rotationSliderY, &QSlider::valueChanged, modifier, &GraphModifier::rotateY); - //! [6] - - QObject::connect(labelButton, &QPushButton::clicked, modifier, - &GraphModifier::changeLabelStyle); - QObject::connect(cameraButton, &QPushButton::clicked, modifier, - &GraphModifier::changePresetCamera); - - QObject::connect(backgroundCheckBox, &QCheckBox::stateChanged, modifier, - &GraphModifier::setBackgroundEnabled); - QObject::connect(gridCheckBox, &QCheckBox::stateChanged, modifier, - &GraphModifier::setGridEnabled); - QObject::connect(smoothCheckBox, &QCheckBox::stateChanged, modifier, - &GraphModifier::setSmoothBars); - - QObject::connect(barStyleList, SIGNAL(currentIndexChanged(int)), modifier, - SLOT(changeStyle(int))); - - QObject::connect(selectionModeList, SIGNAL(currentIndexChanged(int)), modifier, - SLOT(changeSelectionMode(int))); - - QObject::connect(themeList, SIGNAL(currentIndexChanged(int)), modifier, - SLOT(changeTheme(int))); - - QObject::connect(shadowQuality, SIGNAL(currentIndexChanged(int)), modifier, - SLOT(changeShadowQuality(int))); - - QObject::connect(modifier, &GraphModifier::shadowQualityChanged, shadowQuality, - &QComboBox::setCurrentIndex); - QObject::connect(widgetgraph, &Q3DBars::shadowQualityChanged, modifier, - &GraphModifier::shadowQualityUpdatedByVisual); - - QObject::connect(fontSizeSlider, &QSlider::valueChanged, modifier, - &GraphModifier::changeFontSize); - QObject::connect(fontList, &QFontComboBox::currentFontChanged, modifier, - &GraphModifier::changeFont); - - //! [3] - widget->show(); - modifier->start(); - return app.exec(); - //! [3] -} diff --git a/src/datavisualization/doc/src/qtdatavisualization.qdoc b/src/datavisualization/doc/src/qtdatavisualization.qdoc index 1f2474f7..45087e9d 100644 --- a/src/datavisualization/doc/src/qtdatavisualization.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization.qdoc @@ -143,9 +143,9 @@ QHeightMapSurfaceDataProxy is a specialized proxy for generating a surface graph from a heightmap image. See QHeightMapSurfaceDataProxy documentation for more information. - The \l{Rainfall Example}{Rainfall} example shows how a custom proxy can be created. It defines - a custom data set based on variant lists and an extension of the basic proxy to resolve that - data with an associated mapper. + The \l{Custom Proxy Example}{Custom Proxy} example shows how a custom proxy can be created. It + defines a custom data set based on variant lists and an extension of the basic proxy to resolve + that data with an associated mapper. \section1 Dealing with real-time data diff --git a/src/datavisualization/engine/q3dbars.cpp b/src/datavisualization/engine/q3dbars.cpp index 6af18b1f..0a543d54 100644 --- a/src/datavisualization/engine/q3dbars.cpp +++ b/src/datavisualization/engine/q3dbars.cpp @@ -88,8 +88,8 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * * The scene can be rotated, zoomed into, and a bar can be selected to view it's value, * but no other interaction is included in this minimal code example. You can learn more by - * familiarizing yourself with the examples provided, like the \l{Rainfall Example} or - * the \l{Widget Example}. + * familiarizing yourself with the examples provided, like the \l{Bars Example} or + * the \l{Custom Proxy Example}. * * \sa Q3DScatter, Q3DSurface, {Qt Data Visualization C++ Classes} */ |