1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Data Visualization module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include <QtDataVisualization/q3dbars.h>
31#include <QtDataVisualization/qcategory3daxis.h>
32#include <QtDataVisualization/qitemmodelbardataproxy.h>
33#include <QtDataVisualization/qvalue3daxis.h>
34#include <QtDataVisualization/q3dscene.h>
35#include <QtDataVisualization/q3dcamera.h>
36#include <QtDataVisualization/qbar3dseries.h>
37#include <QtDataVisualization/q3dtheme.h>
38
39#include <QtWidgets/QApplication>
40#include <QtWidgets/QVBoxLayout>
41#include <QtWidgets/QTableWidget>
42#include <QtGui/QScreen>
43#include <QtCore/QRandomGenerator>
44#include <QtCore/QTimer>
45#include <QtGui/QFont>
46#include <QtCore/QDebug>
47#include <QtWidgets/QHeaderView>
48#include <QtWidgets/QMessageBox>
49
50#define USE_STATIC_DATA
51
52using namespace QtDataVisualization;
53
54class GraphDataGenerator : public QObject
55{
56public:
57 explicit GraphDataGenerator(Q3DBars *bargraph, QTableWidget *tableWidget);
58 ~GraphDataGenerator();
59
60 void setupModel();
61 void addRow();
62 void changeStyle();
63 void changePresetCamera();
64 void changeTheme();
65 void start();
66 void selectFromTable(const QPoint &selection);
67 void selectedFromTable(int currentRow, int currentColumn, int previousRow, int previousColumn);
68 void fixTableSize();
69
70private:
71 Q3DBars *m_graph;
72 QTimer *m_dataTimer;
73 int m_columnCount;
74 int m_rowCount;
75 QTableWidget *m_tableWidget; // not owned
76};
77
78GraphDataGenerator::GraphDataGenerator(Q3DBars *bargraph, QTableWidget *tableWidget)
79 : m_graph(bargraph),
80 m_dataTimer(0),
81 m_columnCount(100),
82 m_rowCount(50),
83 m_tableWidget(tableWidget)
84{
85 //! [5]
86 // Set up bar specifications; make the bars as wide as they are deep,
87 // and add a small space between them
88 m_graph->setBarThickness(1.0f);
89 m_graph->setBarSpacing(QSizeF(0.2, 0.2));
90
91 //! [5]
92#ifndef USE_STATIC_DATA
93 // Set up sample space; make it as deep as it's wide
94 m_graph->rowAxis()->setRange(0, m_rowCount);
95 m_graph->columnAxis()->setRange(0, m_columnCount);
96 m_tableWidget->setColumnCount(m_columnCount);
97
98 // Set selection mode to full
99 m_graph->setSelectionMode(QAbstract3DGraph::SelectionItemRowAndColumn);
100
101 // Hide axis labels by explicitly setting one empty string as label list
102 m_graph->rowAxis()->setLabels(QStringList(QString()));
103 m_graph->columnAxis()->setLabels(QStringList(QString()));
104
105 m_graph->seriesList().at(0)->setItemLabelFormat(QStringLiteral("@valueLabel"));
106#else
107 //! [6]
108 // Set selection mode to slice row
109 m_graph->setSelectionMode(QAbstract3DGraph::SelectionItemAndRow | QAbstract3DGraph::SelectionSlice);
110
111 //! [6]
112#endif
113
114 //! [7]
115 // Set theme
116 m_graph->activeTheme()->setType(Q3DTheme::ThemeDigia);
117
118 // Set font
119 m_graph->activeTheme()->setFont(QFont("Impact", 20));
120
121 // Set preset camera position
122 m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
123 //! [7]
124}
125
126GraphDataGenerator::~GraphDataGenerator()
127{
128 if (m_dataTimer) {
129 m_dataTimer->stop();
130 delete m_dataTimer;
131 }
132 delete m_graph;
133}
134
135void GraphDataGenerator::start()
136{
137#ifndef USE_STATIC_DATA
138 m_dataTimer = new QTimer();
139 m_dataTimer->setTimerType(Qt::CoarseTimer);
140 QObject::connect(m_dataTimer, &QTimer::timeout, this, &GraphDataGenerator::addRow);
141 m_dataTimer->start(0);
142 m_tableWidget->setFixedWidth(m_graph->width());
143#else
144 //! [8]
145 setupModel();
146
147 // Table needs to be shown before the size of its headers can be accurately obtained,
148 // so we postpone it a bit
149 m_dataTimer = new QTimer();
150 m_dataTimer->setSingleShot(true);
151 QObject::connect(sender: m_dataTimer, signal: &QTimer::timeout, receiver: this, slot: &GraphDataGenerator::fixTableSize);
152 m_dataTimer->start(msec: 0);
153 //! [8]
154#endif
155}
156
157void GraphDataGenerator::setupModel()
158{
159 //! [9]
160 // Set up row and column names
161 QStringList days;
162 days << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday" << "Saturday" << "Sunday";
163 QStringList weeks;
164 weeks << "week 1" << "week 2" << "week 3" << "week 4" << "week 5";
165
166 // Set up data Mon Tue Wed Thu Fri Sat Sun
167 float hours[5][7] = {{2.0f, 1.0f, 3.0f, 0.2f, 1.0f, 5.0f, 10.0f}, // week 1
168 {0.5f, 1.0f, 3.0f, 1.0f, 2.0f, 2.0f, 3.0f}, // week 2
169 {1.0f, 1.0f, 2.0f, 1.0f, 4.0f, 4.0f, 4.0f}, // week 3
170 {0.0f, 1.0f, 0.0f, 0.0f, 2.0f, 2.0f, 0.3f}, // week 4
171 {3.0f, 3.0f, 6.0f, 2.0f, 2.0f, 1.0f, 1.0f}}; // week 5
172 //! [9]
173
174 // Add labels
175 //! [10]
176 m_graph->rowAxis()->setTitle("Week of year");
177 m_graph->rowAxis()->setTitleVisible(true);
178 m_graph->columnAxis()->setTitle("Day of week");
179 m_graph->columnAxis()->setTitleVisible(true);
180 m_graph->valueAxis()->setTitle("Hours spent on the Internet");
181 m_graph->valueAxis()->setTitleVisible(true);
182 m_graph->valueAxis()->setLabelFormat("%.1f h");
183 //! [10]
184
185 //! [11]
186 m_tableWidget->setRowCount(5);
187 m_tableWidget->setColumnCount(7);
188 m_tableWidget->setHorizontalHeaderLabels(days);
189 m_tableWidget->setVerticalHeaderLabels(weeks);
190 m_tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
191 m_tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
192 m_tableWidget->setCurrentCell(row: -1, column: -1);
193 m_tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
194 //! [11]
195
196 //! [12]
197 for (int week = 0; week < weeks.size(); week++) {
198 for (int day = 0; day < days.size(); day++) {
199 QModelIndex index = m_tableWidget->model()->index(row: week, column: day);
200 m_tableWidget->model()->setData(index, value: hours[week][day]);
201 }
202 }
203 //! [12]
204}
205
206void GraphDataGenerator::addRow()
207{
208 m_tableWidget->model()->insertRow(arow: 0);
209 if (m_tableWidget->model()->rowCount() > m_rowCount)
210 m_tableWidget->model()->removeRow(arow: m_rowCount);
211 for (int i = 0; i < m_columnCount; i++) {
212 QModelIndex index = m_tableWidget->model()->index(row: 0, column: i);
213 m_tableWidget->model()->setData(index,
214 value: ((float)i / (float)m_columnCount) / 2.0f +
215 (float)(QRandomGenerator::global()->bounded(highest: 30)) / 100.0f);
216 }
217 m_tableWidget->resizeColumnsToContents();
218}
219
220//! [13]
221void GraphDataGenerator::selectFromTable(const QPoint &selection)
222{
223 m_tableWidget->setFocus();
224 m_tableWidget->setCurrentCell(row: selection.x(), column: selection.y());
225}
226//! [13]
227
228//! [14]
229void GraphDataGenerator::selectedFromTable(int currentRow, int currentColumn,
230 int previousRow, int previousColumn)
231{
232 Q_UNUSED(previousRow)
233 Q_UNUSED(previousColumn)
234 m_graph->seriesList().at(i: 0)->setSelectedBar(QPoint(currentRow, currentColumn));
235}
236//! [14]
237
238void GraphDataGenerator::fixTableSize()
239{
240 int width = m_tableWidget->horizontalHeader()->length();
241 width += m_tableWidget->verticalHeader()->width();
242 m_tableWidget->setFixedWidth(width + 2);
243 int height = m_tableWidget->verticalHeader()->length();
244 height += m_tableWidget->horizontalHeader()->height();
245 m_tableWidget->setFixedHeight(height + 2);
246}
247
248int main(int argc, char **argv)
249{
250 //! [0]
251 QApplication app(argc, argv);
252 Q3DBars *graph = new Q3DBars();
253 QWidget *container = QWidget::createWindowContainer(window: graph);
254 //! [0]
255
256 if (!graph->hasContext()) {
257 QMessageBox msgBox;
258 msgBox.setText("Couldn't initialize the OpenGL context.");
259 msgBox.exec();
260 return -1;
261 }
262
263 QSize screenSize = graph->screen()->size();
264 container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 2));
265 container->setMaximumSize(screenSize);
266 container->setSizePolicy(hor: QSizePolicy::Expanding, ver: QSizePolicy::Expanding);
267 container->setFocusPolicy(Qt::StrongFocus);
268
269 //! [1]
270 QWidget widget;
271 QVBoxLayout *layout = new QVBoxLayout(&widget);
272 QTableWidget *tableWidget = new QTableWidget(&widget);
273 layout->addWidget(container, stretch: 1);
274 layout->addWidget(tableWidget, stretch: 1, alignment: Qt::AlignHCenter);
275 //! [1]
276
277 tableWidget->setSizePolicy(hor: QSizePolicy::Expanding, ver: QSizePolicy::Fixed);
278 tableWidget->setAlternatingRowColors(true);
279 widget.setWindowTitle(QStringLiteral("Hours spent on the Internet"));
280
281 //! [2]
282 // Since we are dealing with QTableWidget, the model will already have data sorted properly
283 // into rows and columns, so we simply set useModelCategories property to true to utilize this.
284 QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(tableWidget->model());
285 proxy->setUseModelCategories(true);
286 QBar3DSeries *series = new QBar3DSeries(proxy);
287 series->setMesh(QAbstract3DSeries::MeshPyramid);
288 graph->addSeries(series);
289 //! [2]
290
291 //! [3]
292 GraphDataGenerator generator(graph, tableWidget);
293 QObject::connect(sender: series, signal: &QBar3DSeries::selectedBarChanged, receiver: &generator,
294 slot: &GraphDataGenerator::selectFromTable);
295 QObject::connect(sender: tableWidget, signal: &QTableWidget::currentCellChanged, receiver: &generator,
296 slot: &GraphDataGenerator::selectedFromTable);
297 //! [3]
298
299 //! [4]
300 widget.show();
301 generator.start();
302 return app.exec();
303 //! [4]
304}
305

source code of qtdatavis3d/examples/datavisualization/itemmodel/main.cpp