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 "chart.h"
31#include "custominputhandler.h"
32#include <QtDataVisualization/qcategory3daxis.h>
33#include <QtDataVisualization/qvalue3daxis.h>
34#include <QtDataVisualization/qlogvalue3daxisformatter.h>
35#include <QtDataVisualization/qbardataproxy.h>
36#include <QtDataVisualization/q3dscene.h>
37#include <QtDataVisualization/q3dcamera.h>
38#include <QtDataVisualization/q3dtheme.h>
39#include <QtDataVisualization/q3dinputhandler.h>
40#include <QtDataVisualization/qcustom3ditem.h>
41#include <QtCore/QRandomGenerator>
42#include <QtCore/QElapsedTimer>
43#include <QtCore/qmath.h>
44
45using namespace QtDataVisualization;
46
47const QString celsiusString = QString(QChar(0xB0)) + "C";
48
49GraphModifier::GraphModifier(Q3DBars *barchart, QColorDialog *colorDialog)
50 : m_graph(barchart),
51 m_colorDialog(colorDialog),
52 m_columnCount(21),
53 m_rowCount(21),
54 m_xRotation(0.0f),
55 m_yRotation(0.0f),
56 m_static(true),
57 m_barSpacingX(0.1f),
58 m_barSpacingZ(0.1f),
59 m_fontSize(20),
60 m_segments(10),
61 m_subSegments(3),
62 m_minval(-16.0f),
63 m_maxval(20.0f),
64 m_selectedBar(-1, -1),
65 m_selectedSeries(0),
66 m_autoAdjustingAxis(new QValue3DAxis),
67 m_fixedRangeAxis(new QValue3DAxis),
68 m_temperatureAxis(new QValue3DAxis),
69 m_yearAxis(new QCategory3DAxis),
70 m_monthAxis(new QCategory3DAxis),
71 m_genericRowAxis(new QCategory3DAxis),
72 m_genericColumnAxis(new QCategory3DAxis),
73 m_temperatureData(new QBar3DSeries),
74 m_temperatureData2(new QBar3DSeries),
75 m_genericData(new QBar3DSeries),
76 m_dummyData(new QBar3DSeries),
77 m_dummyData2(new QBar3DSeries),
78 m_dummyData3(new QBar3DSeries),
79 m_dummyData4(new QBar3DSeries),
80 m_dummyData5(new QBar3DSeries),
81 m_currentAxis(m_fixedRangeAxis),
82 m_negativeValuesOn(false),
83 m_useNullInputHandler(false),
84 m_defaultInputHandler(0),
85 m_ownTheme(0),
86 m_builtinTheme(new Q3DTheme(Q3DTheme::ThemeStoneMoss)),
87 m_customInputHandler(new CustomInputHandler),
88 m_extraSeries(0)
89{
90 m_temperatureData->setObjectName("m_temperatureData");
91 m_temperatureData2->setObjectName("m_temperatureData2");
92 m_genericData->setObjectName("m_genericData");
93 m_dummyData->setObjectName("m_dummyData");
94 m_dummyData2->setObjectName("m_dummyData2");
95 m_dummyData3->setObjectName("m_dummyData3");
96 m_dummyData4->setObjectName("m_dummyData4");
97 m_dummyData5->setObjectName("m_dummyData5");
98
99 // Generate generic labels
100 QStringList genericColumnLabels;
101 for (int i = 0; i < 400; i++) {
102 if (i % 5)
103 genericColumnLabels << QString();
104 else
105 genericColumnLabels << QStringLiteral("Column %1").arg(a: i);
106 }
107
108 m_months << "January" << "February" << "March" << "April" << "May" << "June" << "July" << "August" << "September" << "October" << "November" << "December";
109 m_years << "2006" << "2007" << "2008" << "2009" << "2010" << "2011" << "2012";
110
111 QString labelFormat(QStringLiteral("%.3f"));
112 QString axisTitle("Generic Value");
113
114 m_autoAdjustingAxis->setLabelFormat(labelFormat);
115 m_autoAdjustingAxis->setTitle(axisTitle);
116 m_autoAdjustingAxis->setSegmentCount(m_segments * 2);
117 m_autoAdjustingAxis->setSubSegmentCount(1);
118 m_autoAdjustingAxis->setAutoAdjustRange(true);
119
120 m_fixedRangeAxis->setLabelFormat(labelFormat);
121 m_fixedRangeAxis->setTitle(axisTitle);
122 m_fixedRangeAxis->setSegmentCount(m_segments);
123 m_fixedRangeAxis->setSubSegmentCount(m_subSegments);
124 m_fixedRangeAxis->setRange(min: 0.0, max: 100.0);
125
126 m_genericRowAxis->setTitle("Generic Row");
127 m_genericRowAxis->setRange(min: 0, max: m_rowCount - 1);
128
129 m_genericColumnAxis->setTitle("Generic Column");
130 m_genericColumnAxis->setRange(min: 0, max: m_columnCount - 1);
131
132 m_temperatureAxis->setTitle("Average temperature");
133 m_temperatureAxis->setSegmentCount(m_segments);
134 m_temperatureAxis->setSubSegmentCount(m_subSegments);
135 m_temperatureAxis->setRange(min: m_minval, max: m_maxval);
136 m_temperatureAxis->setLabelFormat(QString(QStringLiteral("%d ") + celsiusString));
137
138 m_yearAxis->setTitle("Year");
139
140 m_monthAxis->setTitle("Month");
141
142 m_graph->addAxis(axis: m_autoAdjustingAxis);
143 m_graph->addAxis(axis: m_fixedRangeAxis);
144 m_graph->addAxis(axis: m_temperatureAxis);
145 m_graph->addAxis(axis: m_yearAxis);
146 m_graph->addAxis(axis: m_monthAxis);
147 m_graph->addAxis(axis: m_genericRowAxis);
148 m_graph->addAxis(axis: m_genericColumnAxis);
149
150 m_graph->setActiveTheme(m_builtinTheme);
151 m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftMedium);
152
153 m_temperatureData->setName("Oulu");
154 m_temperatureData2->setName("Helsinki");
155 m_genericData->setName("Generic series");
156 m_dummyData->setName("Dummy 1");
157 m_dummyData2->setName("Dummy 2");
158 m_dummyData3->setName("Dummy 3");
159 m_dummyData4->setName("Dummy 4");
160 m_dummyData5->setName("Dummy 5");
161
162 m_temperatureData->setItemLabelFormat(QStringLiteral("@seriesName: @valueTitle for @colLabel @rowLabel: @valueLabel ~ %.4f"));
163 m_temperatureData2->setItemLabelFormat(QStringLiteral("@seriesName: @valueTitle for @colLabel @rowLabel: @valueLabel"));
164 m_genericData->setItemLabelFormat(QStringLiteral("@seriesName: @valueTitle for (@rowIdx, @colIdx): @valueLabel"));
165
166 m_dummyData->setItemLabelFormat(QStringLiteral("@seriesName: @valueLabel"));
167 m_dummyData2->setItemLabelFormat(QStringLiteral("@seriesName: @valueLabel"));
168 m_dummyData3->setItemLabelFormat(QStringLiteral("@seriesName: @valueLabel"));
169 m_dummyData4->setItemLabelFormat(QStringLiteral("@seriesName: @valueLabel"));
170 m_dummyData5->setItemLabelFormat(QStringLiteral("@seriesName: @valueLabel"));
171
172 m_genericData->dataProxy()->setColumnLabels(genericColumnLabels);
173
174 m_temperatureData->setBaseColor(Qt::red);
175 m_temperatureData->setSingleHighlightColor(Qt::cyan);
176 m_temperatureData->setMultiHighlightColor(Qt::magenta);
177 m_temperatureData2->setBaseColor(Qt::yellow);
178 m_genericData->setBaseColor(Qt::blue);
179
180 QLinearGradient barGradient1(0, 0, 1, 100);
181 barGradient1.setColorAt(pos: 1.0, color: Qt::red);
182 barGradient1.setColorAt(pos: 0.75001, color: Qt::red);
183 barGradient1.setColorAt(pos: 0.75, color: Qt::magenta);
184 barGradient1.setColorAt(pos: 0.50001, color: Qt::magenta);
185 barGradient1.setColorAt(pos: 0.50, color: Qt::blue);
186 barGradient1.setColorAt(pos: 0.25001, color: Qt::blue);
187 barGradient1.setColorAt(pos: 0.25, color: Qt::black);
188 barGradient1.setColorAt(pos: 0.0, color: Qt::black);
189
190 QLinearGradient barGradient2(0, 0, 1, 100);
191 barGradient2.setColorAt(pos: 1.0, color: Qt::red);
192 barGradient2.setColorAt(pos: 0.75, color: Qt::magenta);
193 barGradient2.setColorAt(pos: 0.50, color: Qt::blue);
194 barGradient2.setColorAt(pos: 0.25, color: Qt::black);
195 barGradient2.setColorAt(pos: 0.0, color: Qt::black);
196
197 QLinearGradient singleHighlightGradient(0, 0, 1, 100);
198 singleHighlightGradient.setColorAt(pos: 1.0, color: Qt::white);
199 singleHighlightGradient.setColorAt(pos: 0.75, color: Qt::lightGray);
200 singleHighlightGradient.setColorAt(pos: 0.50, color: Qt::gray);
201 singleHighlightGradient.setColorAt(pos: 0.25, color: Qt::darkGray);
202 singleHighlightGradient.setColorAt(pos: 0.0, color: Qt::black);
203
204 QLinearGradient multiHighlightGradient(0, 0, 1, 100);
205 multiHighlightGradient.setColorAt(pos: 1.0, color: Qt::lightGray);
206 multiHighlightGradient.setColorAt(pos: 0.75, color: Qt::gray);
207 multiHighlightGradient.setColorAt(pos: 0.50, color: Qt::darkGray);
208 multiHighlightGradient.setColorAt(pos: 0.25, color: Qt::black);
209 multiHighlightGradient.setColorAt(pos: 0.0, color: Qt::black);
210
211 m_temperatureData->setBaseGradient(barGradient1);
212 m_temperatureData2->setBaseGradient(barGradient2);
213 m_temperatureData->setSingleHighlightGradient(singleHighlightGradient);
214 m_temperatureData->setMultiHighlightGradient(multiHighlightGradient);
215
216 m_graph->activeTheme()->setFont(QFont("Times Roman", 20));
217
218 // Release and store the default input handler.
219 m_defaultInputHandler = static_cast<Q3DInputHandler *>(m_graph->activeInputHandler());
220 m_graph->releaseInputHandler(inputHandler: m_defaultInputHandler);
221 m_graph->setActiveInputHandler(m_defaultInputHandler);
222
223 QObject::connect(sender: m_graph, signal: &Q3DBars::shadowQualityChanged, receiver: this,
224 slot: &GraphModifier::shadowQualityUpdatedByVisual);
225 QObject::connect(sender: m_temperatureData, signal: &QBar3DSeries::selectedBarChanged, receiver: this,
226 slot: &GraphModifier::handleSelectionChange);
227 QObject::connect(sender: m_temperatureData2, signal: &QBar3DSeries::selectedBarChanged, receiver: this,
228 slot: &GraphModifier::handleSelectionChange);
229 QObject::connect(sender: m_genericData, signal: &QBar3DSeries::selectedBarChanged, receiver: this,
230 slot: &GraphModifier::handleSelectionChange);
231
232 QObject::connect(sender: m_graph, signal: &Q3DBars::rowAxisChanged, receiver: this,
233 slot: &GraphModifier::handleRowAxisChanged);
234 QObject::connect(sender: m_graph, signal: &Q3DBars::columnAxisChanged, receiver: this,
235 slot: &GraphModifier::handleColumnAxisChanged);
236 QObject::connect(sender: m_graph, signal: &Q3DBars::valueAxisChanged, receiver: this,
237 slot: &GraphModifier::handleValueAxisChanged);
238 QObject::connect(sender: m_graph, signal: &Q3DBars::primarySeriesChanged, receiver: this,
239 slot: &GraphModifier::handlePrimarySeriesChanged);
240 QObject::connect(sender: m_temperatureAxis, signal: &QAbstract3DAxis::labelsChanged, receiver: this,
241 slot: &GraphModifier::handleValueAxisLabelsChanged);
242
243 QObject::connect(sender: &m_insertRemoveTimer, signal: &QTimer::timeout, receiver: this,
244 slot: &GraphModifier::insertRemoveTimerTimeout);
245
246 m_graph->addSeries(series: m_temperatureData);
247 m_graph->addSeries(series: m_temperatureData2);
248
249 QObject::connect(sender: &m_selectionTimer, signal: &QTimer::timeout, receiver: this,
250 slot: &GraphModifier::triggerSelection);
251 QObject::connect(sender: &m_rotationTimer, signal: &QTimer::timeout, receiver: this,
252 slot: &GraphModifier::triggerRotation);
253
254 QObject::connect(sender: m_graph, signal: &QAbstract3DGraph::currentFpsChanged, receiver: this,
255 slot: &GraphModifier::handleFpsChange);
256
257 resetTemperatureData();
258}
259
260GraphModifier::~GraphModifier()
261{
262 delete m_graph;
263 delete m_defaultInputHandler;
264}
265
266void GraphModifier::start()
267{
268 restart(dynamicData: false);
269}
270
271void GraphModifier::restart(bool dynamicData)
272{
273 m_static = !dynamicData;
274
275 if (m_static) {
276 m_graph->removeSeries(series: m_genericData);
277
278 m_graph->setTitle(QStringLiteral("Average temperatures in Oulu, Finland (2006-2012)"));
279
280 m_graph->setValueAxis(m_temperatureAxis);
281 m_graph->setRowAxis(m_yearAxis);
282 m_graph->setColumnAxis(m_monthAxis);
283
284 } else {
285 m_graph->addSeries(series: m_genericData);
286
287 m_graph->setTitle(QStringLiteral("Generic data"));
288
289 m_minval = m_fixedRangeAxis->min();
290 m_maxval = m_fixedRangeAxis->max();
291 m_graph->setValueAxis(m_currentAxis);
292 m_graph->setRowAxis(m_genericRowAxis);
293 m_graph->setColumnAxis(m_genericColumnAxis);
294 }
295}
296
297void GraphModifier::selectBar()
298{
299 QPoint targetBar(5, 5);
300 QPoint noSelection(-1, -1);
301 if (m_selectedBar != targetBar)
302 m_graph->seriesList().at(i: 0)->setSelectedBar(targetBar);
303 else
304 m_graph->seriesList().at(i: 0)->setSelectedBar(noSelection);
305}
306
307void GraphModifier::swapAxis()
308{
309 static int counter = 0;
310 int state = ++counter % 3;
311
312 if (state == 0) {
313 m_currentAxis = m_fixedRangeAxis;
314 qDebug() << "Fixed range axis";
315 } else if (state == 1) {
316 m_currentAxis = m_autoAdjustingAxis;
317 qDebug() << "Automatic range axis";
318 } else {
319 m_currentAxis = 0;
320 qDebug() << "default axis";
321 }
322
323 m_graph->setValueAxis(m_currentAxis);
324}
325
326void GraphModifier::releaseAxes()
327{
328 // Releases all axes we have created - results in default axes for all dimensions.
329 // Axes reset when the graph is switched as set*Axis calls are made, which
330 // implicitly add axes.
331 m_graph->releaseAxis(axis: m_autoAdjustingAxis);
332 m_graph->releaseAxis(axis: m_fixedRangeAxis);
333 m_graph->releaseAxis(axis: m_temperatureAxis);
334 m_graph->releaseAxis(axis: m_yearAxis);
335 m_graph->releaseAxis(axis: m_monthAxis);
336 m_graph->releaseAxis(axis: m_genericRowAxis);
337 m_graph->releaseAxis(axis: m_genericColumnAxis);
338}
339
340void GraphModifier::releaseSeries()
341{
342 foreach (QBar3DSeries *series, m_graph->seriesList())
343 m_graph->removeSeries(series);
344}
345
346void GraphModifier::flipViews()
347{
348 m_graph->scene()->setSecondarySubviewOnTop(!m_graph->scene()->isSecondarySubviewOnTop());
349 qDebug() << "secondary subview on top:" << m_graph->scene()->isSecondarySubviewOnTop();
350 qDebug() << "point (50, 50) in primary subview:" << m_graph->scene()->isPointInPrimarySubView(point: QPoint(50, 50));
351 qDebug() << "point (50, 50) in secondary subview:" << m_graph->scene()->isPointInSecondarySubView(point: QPoint(50, 50));
352}
353
354void GraphModifier::createMassiveArray()
355{
356 const int arrayDimension = 1000;
357 QElapsedTimer timer;
358 timer.start();
359
360 QStringList genericColumnLabels;
361 for (int i = 0; i < arrayDimension; i++) {
362 if (i % 5)
363 genericColumnLabels << QString();
364 else
365 genericColumnLabels << QStringLiteral("Column %1").arg(a: i);
366 }
367
368 QStringList genericRowLabels;
369 for (int i = 0; i < arrayDimension; i++) {
370 if (i % 5)
371 genericRowLabels << QString();
372 else
373 genericRowLabels << QStringLiteral("Row %1").arg(a: i);
374 }
375
376 QBarDataArray *dataArray = new QBarDataArray;
377 dataArray->reserve(alloc: arrayDimension);
378 for (int i = 0; i < arrayDimension; i++) {
379 QBarDataRow *dataRow = new QBarDataRow(arrayDimension);
380 for (int j = 0; j < arrayDimension; j++) {
381 if (!m_negativeValuesOn)
382 (*dataRow)[j].setValue((float(i % 300 + 1) / 300.0)
383 * QRandomGenerator::global()->bounded(highest: m_maxval));
384 else
385 (*dataRow)[j].setValue((float(i % 300 + 1) / 300.0)
386 * QRandomGenerator::global()->bounded(highest: m_maxval) + m_minval);
387 }
388 dataArray->append(t: dataRow);
389 }
390
391 m_genericData->dataProxy()->resetArray(newArray: dataArray, rowLabels: genericRowLabels, columnLabels: genericColumnLabels);
392
393 qDebug() << "Created Massive Array (" << arrayDimension << "), time:" << timer.elapsed();
394}
395
396void GraphModifier::resetTemperatureData()
397{
398 // Set up data
399 static const float temp[7][12] = {
400 {-6.7f, -11.7f, -9.7f, 3.3f, 9.2f, 14.0f, 16.3f, 17.8f, 10.2f, 2.1f, -2.6f, -0.3f}, // 2006
401 {-6.8f, -13.3f, 0.2f, 1.5f, 7.9f, 13.4f, 16.1f, 15.5f, 8.2f, 5.4f, -2.6f, -0.8f}, // 2007
402 {-4.2f, -4.0f, -4.6f, 1.9f, 7.3f, 12.5f, 15.0f, 12.8f, 7.6f, 5.1f, -0.9f, -1.3f}, // 2008
403 {-7.8f, -8.8f, -4.2f, 0.7f, 9.3f, 13.2f, 15.8f, 15.5f, 11.2f, 0.6f, 0.7f, -8.4f}, // 2009
404 {-14.4f, -12.1f, -7.0f, 2.3f, 11.0f, 12.6f, 18.8f, 13.8f, 9.4f, 3.9f, -5.6f, -13.0f}, // 2010
405 {-9.0f, -15.2f, -3.8f, 2.6f, 8.3f, 15.9f, 18.6f, 14.9f, 11.1f, 5.3f, 1.8f, -0.2f}, // 2011
406 {-8.7f, -11.3f, -2.3f, 0.4f, 7.5f, 12.2f, 16.4f, 14.1f, 9.2f, 3.1f, 0.3f, -12.1f} // 2012
407 };
408
409 // Create data rows
410 QBarDataArray *dataSet = new QBarDataArray;
411 QBarDataRow *dataRow;
412
413 dataSet->reserve(alloc: m_years.size());
414 for (int year = 0; year < m_years.size(); year++) {
415 dataRow = new QBarDataRow(m_months.size());
416 // Create data items
417 for (int month = 0; month < m_months.size(); month++) {
418 // Add data to rows
419 (*dataRow)[month].setValue(temp[year][month]);
420 }
421 // Add row to set
422 dataSet->append(t: dataRow);
423 }
424
425 QBarDataArray *dataSet2 = new QBarDataArray;
426
427 dataSet2->reserve(alloc: m_years.size());
428 for (int year = m_years.size() - 1; year >= 0; year--) {
429 dataRow = new QBarDataRow(m_months.size());
430 // Create data items
431 for (int month = m_months.size() - 1; month >= 0 ; month--) {
432 // Add data to rows
433 (*dataRow)[month].setValue(temp[year][month]);
434 }
435 // Add row to set
436 dataSet2->append(t: dataRow);
437 }
438
439 // Add data to chart (chart assumes ownership)
440 m_temperatureData->dataProxy()->resetArray(newArray: dataSet, rowLabels: m_years, columnLabels: m_months);
441 m_temperatureData2->dataProxy()->resetArray(newArray: dataSet2, rowLabels: m_years, columnLabels: m_months);
442}
443
444
445static int addCounter = 0;
446static int insertCounter = 0;
447static int changeCounter = 0;
448
449void GraphModifier::addRow()
450{
451 QBarDataRow *dataRow = new QBarDataRow(m_columnCount);
452 for (float i = 0; i < m_columnCount; i++) {
453 if (!m_negativeValuesOn)
454 (*dataRow)[i].setValue(((i + 1) / (float)m_columnCount)
455 * QRandomGenerator::global()->bounded(highest: m_maxval));
456 else
457 (*dataRow)[i].setValue(((i + 1) / (float)m_columnCount)
458 * QRandomGenerator::global()->bounded(highest: m_maxval)
459 - QRandomGenerator::global()->bounded(highest: m_minval));
460 }
461
462 // TODO Needs to be changed to account for data window offset once it is implemented.
463 QString label = QStringLiteral("Add %1").arg(a: addCounter++);
464 m_genericData->dataProxy()->addRow(row: dataRow, label);
465}
466
467void GraphModifier::addRows()
468{
469 QBarDataArray dataArray;
470 QStringList labels;
471 for (int i = 0; i < m_rowCount; i++) {
472 QBarDataRow *dataRow = new QBarDataRow(m_columnCount);
473 for (int j = 0; j < m_columnCount; j++)
474 (*dataRow)[j].setValue(float(j + i + m_genericData->dataProxy()->rowCount()) + m_minval);
475 dataArray.append(t: dataRow);
476 labels.append(QStringLiteral("Add %1").arg(a: addCounter++));
477 }
478
479 // TODO Needs to be changed to account for data window offset once it is implemented.
480 m_genericData->dataProxy()->addRows(rows: dataArray, labels);
481}
482
483void GraphModifier::insertRow()
484{
485 QBarDataRow *dataRow = new QBarDataRow(m_columnCount);
486 for (float i = 0; i < m_columnCount; i++)
487 (*dataRow)[i].setValue(((i + 1) / (float)m_columnCount)
488 * QRandomGenerator::global()->bounded(highest: m_maxval) + m_minval);
489
490 // TODO Needs to be changed to account for data window offset once it is implemented.
491 int row = qMax(a: m_selectedBar.x(), b: 0);
492 QString label = QStringLiteral("Insert %1").arg(a: insertCounter++);
493 m_genericData->dataProxy()->insertRow(rowIndex: row, row: dataRow, label);
494}
495
496void GraphModifier::insertRows()
497{
498 QElapsedTimer timer;
499 timer.start();
500 QBarDataArray dataArray;
501 QStringList labels;
502 for (int i = 0; i < m_rowCount; i++) {
503 QBarDataRow *dataRow = new QBarDataRow(m_columnCount);
504 for (int j = 0; j < m_columnCount; j++)
505 (*dataRow)[j].setValue(float(j + i + m_genericData->dataProxy()->rowCount()) + m_minval);
506 dataArray.append(t: dataRow);
507 labels.append(QStringLiteral("Insert %1").arg(a: insertCounter++));
508 }
509
510 // TODO Needs to be changed to account for data window offset once it is implemented.
511 int row = qMax(a: m_selectedBar.x(), b: 0);
512 m_genericData->dataProxy()->insertRows(rowIndex: row, rows: dataArray, labels);
513 qDebug() << "Inserted" << m_rowCount << "rows, time:" << timer.elapsed();
514}
515
516void GraphModifier::changeItem()
517{
518 // TODO Needs to be changed to account for data window offset once it is implemented.
519 int row = m_selectedBar.x();
520 int column = m_selectedBar.y();
521 if (row >= 0 && column >= 0) {
522 QBarDataItem item(float(QRandomGenerator::global()->bounded(highest: 100)));
523 m_genericData->dataProxy()->setItem(rowIndex: row, columnIndex: column, item);
524 }
525}
526
527void GraphModifier::changeRow()
528{
529 // TODO Needs to be changed to account for data window offset once it is implemented.
530 int row = m_selectedBar.x();
531 if (row >= 0) {
532 QBarDataRow *newRow = new QBarDataRow(m_genericData->dataProxy()->rowAt(rowIndex: row)->size());
533 for (int i = 0; i < newRow->size(); i++)
534 (*newRow)[i].setValue(QRandomGenerator::global()->bounded(highest: m_maxval) + m_minval);
535 QString label = QStringLiteral("Change %1").arg(a: changeCounter++);
536 m_genericData->dataProxy()->setRow(rowIndex: row, row: newRow, label);
537 }
538}
539
540void GraphModifier::changeRows()
541{
542 // TODO Needs to be changed to account for data window offset once it is implemented.
543 int row = m_selectedBar.x();
544 if (row >= 0) {
545 int startRow = qMax(a: row - 2, b: 0);
546 QBarDataArray newArray;
547 QStringList labels;
548 for (int i = startRow; i <= row; i++ ) {
549 QBarDataRow *newRow = new QBarDataRow(m_genericData->dataProxy()->rowAt(rowIndex: i)->size());
550 for (int j = 0; j < newRow->size(); j++)
551 (*newRow)[j].setValue(QRandomGenerator::global()->bounded(highest: m_maxval) + m_minval);
552 newArray.append(t: newRow);
553 labels.append(QStringLiteral("Change %1").arg(a: changeCounter++));
554 }
555 m_genericData->dataProxy()->setRows(rowIndex: startRow, rows: newArray, labels);
556 }
557}
558
559void GraphModifier::removeRow()
560{
561 // TODO Needs to be changed to account for data window offset once it is implemented.
562 int row = m_selectedBar.x();
563 if (row >= 0)
564 m_genericData->dataProxy()->removeRows(rowIndex: row, removeCount: 1);
565}
566
567void GraphModifier::removeRows()
568{
569 // TODO Needs to be changed to account for data window offset once it is implemented.
570 int row = m_selectedBar.x();
571 if (row >= 0) {
572 int startRow = qMax(a: row - 3, b: 0);
573 m_genericData->dataProxy()->removeRows(rowIndex: startRow, removeCount: 3);
574 }
575}
576
577void GraphModifier::changeStyle()
578{
579 static int model = 0;
580 switch (model) {
581 case 0:
582 m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshCylinder);
583 m_graph->seriesList().at(i: 0)->setMeshSmooth(false);
584 break;
585 case 1:
586 m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshCylinder);
587 m_graph->seriesList().at(i: 0)->setMeshSmooth(true);
588 break;
589 case 2:
590 m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshCone);
591 m_graph->seriesList().at(i: 0)->setMeshSmooth(false);
592 break;
593 case 3:
594 m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshCone);
595 m_graph->seriesList().at(i: 0)->setMeshSmooth(true);
596 break;
597 case 4:
598 m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshBar);
599 m_graph->seriesList().at(i: 0)->setMeshSmooth(false);
600 break;
601 case 5:
602 m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshBar);
603 m_graph->seriesList().at(i: 0)->setMeshSmooth(true);
604 break;
605 case 6:
606 m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshPyramid);
607 m_graph->seriesList().at(i: 0)->setMeshSmooth(false);
608 break;
609 case 7:
610 m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshPyramid);
611 m_graph->seriesList().at(i: 0)->setMeshSmooth(true);
612 break;
613 case 8:
614 m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshBevelBar);
615 m_graph->seriesList().at(i: 0)->setMeshSmooth(false);
616 break;
617 case 9:
618 m_graph->seriesList().at(i: 0)->setMesh(QAbstract3DSeries::MeshBevelBar);
619 m_graph->seriesList().at(i: 0)->setMeshSmooth(true);
620 break;
621 }
622 model++;
623 if (model > 9)
624 model = 0;
625}
626
627void GraphModifier::changePresetCamera()
628{
629 static int preset = Q3DCamera::CameraPresetFrontLow;
630
631 m_graph->scene()->activeCamera()->setCameraPreset((Q3DCamera::CameraPreset)preset);
632
633 if (++preset > Q3DCamera::CameraPresetDirectlyBelow)
634 preset = Q3DCamera::CameraPresetFrontLow;
635}
636
637void GraphModifier::changeTheme()
638{
639 static int theme = Q3DTheme::ThemeQt;
640
641 Q3DTheme *currentTheme = m_graph->activeTheme();
642 m_builtinTheme->setType(Q3DTheme::Theme(theme));
643 if (currentTheme == m_ownTheme)
644 m_graph->setActiveTheme(m_builtinTheme);
645
646 switch (theme) {
647 case Q3DTheme::ThemeQt:
648 qDebug() << __FUNCTION__ << "ThemeQt";
649 break;
650 case Q3DTheme::ThemePrimaryColors:
651 qDebug() << __FUNCTION__ << "ThemePrimaryColors";
652 break;
653 case Q3DTheme::ThemeDigia:
654 qDebug() << __FUNCTION__ << "ThemeDigia";
655 break;
656 case Q3DTheme::ThemeStoneMoss:
657 qDebug() << __FUNCTION__ << "ThemeStoneMoss";
658 break;
659 case Q3DTheme::ThemeArmyBlue:
660 qDebug() << __FUNCTION__ << "ThemeArmyBlue";
661 break;
662 case Q3DTheme::ThemeRetro:
663 qDebug() << __FUNCTION__ << "ThemeRetro";
664 break;
665 case Q3DTheme::ThemeEbony:
666 qDebug() << __FUNCTION__ << "ThemeEbony";
667 break;
668 case Q3DTheme::ThemeIsabelle:
669 qDebug() << __FUNCTION__ << "ThemeIsabelle";
670 break;
671 default:
672 qDebug() << __FUNCTION__ << "Unknown theme";
673 break;
674 }
675
676 if (++theme > Q3DTheme::ThemeIsabelle)
677 theme = Q3DTheme::ThemeQt;
678}
679
680void GraphModifier::changeLabelStyle()
681{
682 m_graph->activeTheme()->setLabelBackgroundEnabled(!m_graph->activeTheme()->isLabelBackgroundEnabled());
683}
684
685void GraphModifier::changeSelectionMode()
686{
687 static int selectionMode = m_graph->selectionMode();
688
689 if (++selectionMode > (QAbstract3DGraph::SelectionItemAndColumn | QAbstract3DGraph::SelectionSlice | QAbstract3DGraph::SelectionMultiSeries))
690 selectionMode = QAbstract3DGraph::SelectionNone;
691
692 m_graph->setSelectionMode((QAbstract3DGraph::SelectionFlag)selectionMode);
693}
694
695void GraphModifier::changeFont(const QFont &font)
696{
697 QFont newFont = font;
698 newFont.setPointSize(m_fontSize);
699 m_graph->activeTheme()->setFont(newFont);
700}
701
702void GraphModifier::changeFontSize(int fontsize)
703{
704 m_fontSize = fontsize;
705 QFont font = m_graph->activeTheme()->font();
706 font.setPointSize(m_fontSize);
707 m_graph->activeTheme()->setFont(font);
708}
709
710void GraphModifier::shadowQualityUpdatedByVisual(QAbstract3DGraph::ShadowQuality sq)
711{
712 int quality = int(sq);
713 // Updates the UI component to show correct shadow quality
714 emit shadowQualityChanged(quality);
715}
716
717void GraphModifier::handleSelectionChange(const QPoint &position)
718{
719 m_selectedBar = position;
720 int index = 0;
721 foreach (QBar3DSeries *series, m_graph->seriesList()) {
722 if (series == sender()) {
723 if (series->selectedBar() != QBar3DSeries::invalidSelectionPosition())
724 m_selectedSeries = series;
725 break;
726 }
727 index++;
728 }
729
730 if (m_selectedSeries->selectedBar() == QBar3DSeries::invalidSelectionPosition())
731 m_selectedSeries = 0;
732
733 qDebug() << "Selected bar position:" << position << "series:" << index;
734}
735
736void GraphModifier::setUseNullInputHandler(bool useNull)
737{
738 qDebug() << "setUseNullInputHandler" << useNull;
739 if (m_useNullInputHandler == useNull)
740 return;
741
742 m_useNullInputHandler = useNull;
743
744 if (useNull)
745 m_graph->setActiveInputHandler(0);
746 else
747 m_graph->setActiveInputHandler(m_defaultInputHandler);
748}
749
750void GraphModifier::handleRowAxisChanged(QCategory3DAxis *axis)
751{
752 qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->rowAxis());
753}
754
755void GraphModifier::handleColumnAxisChanged(QCategory3DAxis *axis)
756{
757 qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->columnAxis());
758}
759
760void GraphModifier::handleValueAxisChanged(QValue3DAxis *axis)
761{
762 qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->valueAxis());
763}
764
765void GraphModifier::handlePrimarySeriesChanged(QBar3DSeries *series)
766{
767 qDebug() << __FUNCTION__ << series;
768}
769
770void GraphModifier::changeShadowQuality(int quality)
771{
772 QAbstract3DGraph::ShadowQuality sq = QAbstract3DGraph::ShadowQuality(quality);
773 m_graph->setShadowQuality(sq);
774 emit shadowQualityChanged(quality);
775}
776
777void GraphModifier::showFiveSeries()
778{
779 releaseSeries();
780 releaseAxes();
781 m_graph->setSelectionMode(QAbstract3DGraph::SelectionItemRowAndColumn | QAbstract3DGraph::SelectionMultiSeries);
782
783 m_dummyData->dataProxy()->resetArray(newArray: makeDummyData(), rowLabels: QStringList(), columnLabels: QStringList());
784 m_dummyData2->dataProxy()->resetArray(newArray: makeDummyData(), rowLabels: QStringList(), columnLabels: QStringList());
785 m_dummyData3->dataProxy()->resetArray(newArray: makeDummyData(), rowLabels: QStringList(), columnLabels: QStringList());
786 m_dummyData4->dataProxy()->resetArray(newArray: makeDummyData(), rowLabels: QStringList(), columnLabels: QStringList());
787 m_dummyData5->dataProxy()->resetArray(newArray: makeDummyData(), rowLabels: QStringList(), columnLabels: QStringList());
788
789 m_graph->addSeries(series: m_dummyData);
790 m_graph->addSeries(series: m_dummyData2);
791 m_graph->addSeries(series: m_dummyData3);
792 m_graph->addSeries(series: m_dummyData4);
793
794 // Toggle between four and five series
795 static int count = 0;
796 if (++count % 2)
797 m_graph->addSeries(series: m_dummyData5);
798}
799
800QBarDataArray *GraphModifier::makeDummyData()
801{
802 // Set up data
803 static const float temp[4][4] = {
804 {10.0f, 5.0f, 10.0f, 5.0f},
805 {5.0f, 10.0f, 5.0f, 10.0f},
806 {10.0f, 5.0f, 10.0f, 5.0f},
807 {5.0f, 10.0f, 5.0f, 10.0f}
808 };
809
810 // Create data rows
811 QBarDataArray *dataSet = new QBarDataArray;
812 QBarDataRow *dataRow;
813
814 dataSet->reserve(alloc: 4);
815 for (int i = 0; i < 4; i++) {
816 dataRow = new QBarDataRow(4);
817 // Create data items
818 for (int j = 0; j < 4; j++) {
819 // Add data to rows
820 (*dataRow)[j].setValue(temp[i][j]);
821 }
822 // Add row to set
823 dataSet->append(t: dataRow);
824 }
825 return dataSet;
826}
827
828// Executes one step of the primary series test
829void GraphModifier::primarySeriesTest()
830{
831 static int nextStep = 0;
832
833 QStringList testLabels;
834 QStringList testLabels2;
835 QStringList testLabels3;
836 QStringList testLabels5;
837 testLabels << "1" << "2" << "3" << "4";
838 testLabels2 << "11" << "22" << "33" << "44";
839 testLabels3 << "111" << "222" << "333" << "444";
840 testLabels5 << "11111" << "22222" << "33333" << "44444";
841
842 switch (nextStep++) {
843 case 0: {
844 qDebug() << "Step 0 - Init:";
845 m_graph->addSeries(series: m_dummyData); // Add one series to enforce release in releaseProxies()
846 releaseSeries();
847 releaseAxes();
848 m_dummyData->dataProxy()->resetArray(newArray: makeDummyData(),
849 rowLabels: testLabels,
850 columnLabels: QStringList() << "A" << "B" << "C" << "D");
851 m_dummyData2->dataProxy()->resetArray(newArray: makeDummyData(),
852 rowLabels: testLabels2,
853 columnLabels: QStringList() << "AA" << "BB" << "CC" << "DD");
854 m_dummyData3->dataProxy()->resetArray(newArray: makeDummyData(),
855 rowLabels: testLabels3,
856 columnLabels: QStringList() << "AAA" << "BBB" << "CCC" << "DDD");
857 m_dummyData4->dataProxy()->resetArray(newArray: makeDummyData(),
858 rowLabels: QStringList() << "1111" << "2222" << "3333" << "4444",
859 columnLabels: QStringList() << "AAAA" << "BBBB" << "CCCC" << "DDDD");
860 m_dummyData5->dataProxy()->resetArray(newArray: makeDummyData(),
861 rowLabels: testLabels5,
862 columnLabels: QStringList() << "AAAAA" << "BBBBB" << "CCCCC" << "DDDDD");
863
864 m_graph->addSeries(series: m_dummyData);
865 m_graph->addSeries(series: m_dummyData2);
866 m_graph->addSeries(series: m_dummyData3);
867
868 m_dummyData->setBaseColor(Qt::black);
869 m_dummyData2->setBaseColor(Qt::white);
870 m_dummyData3->setBaseColor(Qt::red);
871 m_dummyData4->setBaseColor(Qt::blue);
872 m_dummyData5->setBaseColor(Qt::green);
873
874 if (m_graph->primarySeries() == m_dummyData)
875 if (m_graph->rowAxis()->labels() == testLabels)
876 qDebug() << "--> SUCCESS";
877 else
878 qDebug() << "--> FAIL!!! Row labels incorrect: " << m_graph->rowAxis()->labels();
879 else
880 qDebug() << "--> FAIL!!! Primary should be m_dummyData, actual: " << m_graph->primarySeries();
881 break;
882 }
883 case 1: {
884 qDebug() << "Step 1 - Set another series as primary:";
885 m_graph->setPrimarySeries(m_dummyData3);
886 if (m_graph->primarySeries() == m_dummyData3) {
887 if (m_graph->rowAxis()->labels() == testLabels3)
888 qDebug() << "--> SUCCESS";
889 else
890 qDebug() << "--> FAIL!!! Row labels incorrect: " << m_graph->rowAxis()->labels();
891 } else {
892 qDebug() << "--> FAIL!!! Primary should be m_dummyData3, actual: " << m_graph->primarySeries();
893 }
894 break;
895 }
896 case 2: {
897 qDebug() << "Step 2 - Add new series:";
898 m_graph->addSeries(series: m_dummyData4);
899 if (m_graph->primarySeries() == m_dummyData3)
900 if (m_graph->rowAxis()->labels() == testLabels3)
901 qDebug() << "--> SUCCESS";
902 else
903 qDebug() << "--> FAIL!!! Row labels incorrect: " << m_graph->rowAxis()->labels();
904 else
905 qDebug() << "--> FAIL!!! Primary should be m_dummyData3, actual: " << m_graph->primarySeries();
906 break;
907 }
908 case 3: {
909 qDebug() << "Step 3 - Reset primary series:";
910 m_graph->setPrimarySeries(0);
911 if (m_graph->primarySeries() == m_dummyData)
912 if (m_graph->rowAxis()->labels() == testLabels)
913 qDebug() << "--> SUCCESS";
914 else
915 qDebug() << "--> FAIL!!! Row labels incorrect: " << m_graph->rowAxis()->labels();
916 else
917 qDebug() << "--> FAIL!!! Primary should be m_dummyData, actual: " << m_graph->primarySeries();
918 break;
919 }
920 case 4: {
921 qDebug() << "Step 4 - Set new series at primary:";
922 m_graph->setPrimarySeries(m_dummyData5);
923 if (m_graph->primarySeries() == m_dummyData5)
924 if (m_graph->rowAxis()->labels() == testLabels5)
925 qDebug() << "--> SUCCESS";
926 else
927 qDebug() << "--> FAIL!!! Row labels incorrect: " << m_graph->rowAxis()->labels();
928 else
929 qDebug() << "--> FAIL!!! Primary should be m_dummyData5, actual: " << m_graph->primarySeries();
930 break;
931 }
932 case 5: {
933 qDebug() << "Step 5 - Remove nonexistent series:";
934 m_graph->removeSeries(series: 0);
935 if (m_graph->primarySeries() == m_dummyData5)
936 if (m_graph->rowAxis()->labels() == testLabels5)
937 qDebug() << "--> SUCCESS";
938 else
939 qDebug() << "--> FAIL!!! Row labels incorrect: " << m_graph->rowAxis()->labels();
940 else
941 qDebug() << "--> FAIL!!! Primary should be m_dummyData5, actual: " << m_graph->primarySeries();
942 break;
943 }
944 case 6: {
945 qDebug() << "Step 6 - Remove non-primary series:";
946 m_graph->removeSeries(series: m_dummyData);
947 if (m_graph->primarySeries() == m_dummyData5)
948 if (m_graph->rowAxis()->labels() == testLabels5)
949 qDebug() << "--> SUCCESS";
950 else
951 qDebug() << "--> FAIL!!! Row labels incorrect: " << m_graph->rowAxis()->labels();
952 else
953 qDebug() << "--> FAIL!!! Primary should be m_dummyData5, actual: " << m_graph->primarySeries();
954 break;
955 }
956 case 7: {
957 qDebug() << "Step 7 - Remove primary series:";
958 m_graph->removeSeries(series: m_dummyData5);
959 if (m_graph->primarySeries() == m_dummyData2) // first series removed, second should be first now
960 if (m_graph->rowAxis()->labels() == testLabels2)
961 qDebug() << "--> SUCCESS";
962 else
963 qDebug() << "--> FAIL!!! Row labels incorrect: " << m_graph->rowAxis()->labels();
964 else
965 qDebug() << "--> FAIL!!! Primary should be m_dummyData3, actual: " << m_graph->primarySeries();
966 break;
967 }
968 case 8: {
969 qDebug() << "Step 8 - move a series (m_dummyData2) forward to a different position";
970 m_graph->insertSeries(index: 3, series: m_dummyData2);
971 if (m_graph->primarySeries() == m_dummyData2)
972 if (m_graph->seriesList().at(i: 2) == m_dummyData2) // moving series forward, index decrements
973 qDebug() << "--> SUCCESS";
974 else
975 qDebug() << "--> FAIL!!! Moved to incorrect index, index 2 has:" << m_graph->seriesList().at(i: 2);
976 else
977 qDebug() << "--> FAIL!!! Primary should be m_dummyData3, actual: " << m_graph->primarySeries();
978 break;
979 }
980 case 9: {
981 qDebug() << "Step 9 - move a series (m_dummyData4) backward to a different position";
982 m_graph->insertSeries(index: 0, series: m_dummyData4);
983 if (m_graph->primarySeries() == m_dummyData2)
984 if (m_graph->seriesList().at(i: 0) == m_dummyData4)
985 qDebug() << "--> SUCCESS";
986 else
987 qDebug() << "--> FAIL!!! Moved to incorrect index, index 0 has:" << m_graph->seriesList().at(i: 0);
988 else
989 qDebug() << "--> FAIL!!! Primary should be m_dummyData3, actual: " << m_graph->primarySeries();
990 break;
991 }
992 case 10: {
993 qDebug() << "Step 10 - Insert a series (m_dummyData) series to position 2";
994 m_graph->insertSeries(index: 2, series: m_dummyData);
995 if (m_graph->primarySeries() == m_dummyData2)
996 if (m_graph->seriesList().at(i: 2) == m_dummyData)
997 qDebug() << "--> SUCCESS";
998 else
999 qDebug() << "--> FAIL!!! Moved to incorrect index, index 2 has:" << m_graph->seriesList().at(i: 2);
1000 else
1001 qDebug() << "--> FAIL!!! Primary should be m_dummyData3, actual: " << m_graph->primarySeries();
1002 break;
1003 }
1004 case 11: {
1005 qDebug() << "Step 11 - Remove everything";
1006 m_graph->removeSeries(series: m_dummyData);
1007 m_graph->removeSeries(series: m_dummyData2);
1008 m_graph->removeSeries(series: m_dummyData3);
1009 m_graph->removeSeries(series: m_dummyData4);
1010 m_graph->removeSeries(series: m_dummyData5);
1011 if (m_graph->primarySeries() == 0)
1012 if (m_graph->rowAxis()->labels() == QStringList())
1013 qDebug() << "--> SUCCESS";
1014 else
1015 qDebug() << "--> FAIL!!! Row labels incorrect: " << m_graph->rowAxis()->labels();
1016 else
1017 qDebug() << "--> FAIL!!! Primary should be null, actual: " << m_graph->primarySeries();
1018 break;
1019 }
1020 default:
1021 qDebug() << "-- Restarting test sequence --";
1022 nextStep = 0;
1023 break;
1024 }
1025}
1026
1027void GraphModifier::insertRemoveTestToggle()
1028{
1029 if (m_insertRemoveTimer.isActive()) {
1030 m_insertRemoveTimer.stop();
1031 m_selectionTimer.stop();
1032 m_graph->removeSeries(series: m_dummyData);
1033 m_graph->removeSeries(series: m_dummyData2);
1034 releaseSeries();
1035 releaseAxes();
1036 m_graph->setActiveInputHandler(m_defaultInputHandler);
1037 } else {
1038 releaseSeries();
1039 releaseAxes();
1040 m_graph->rowAxis()->setRange(min: 0, max: 32);
1041 m_graph->columnAxis()->setRange(min: 0, max: 10);
1042 m_graph->setActiveInputHandler(m_customInputHandler);
1043 m_graph->addSeries(series: m_dummyData);
1044 m_graph->addSeries(series: m_dummyData2);
1045 m_insertRemoveStep = 0;
1046 m_insertRemoveTimer.start(msec: 100);
1047 m_selectionTimer.start(msec: 10);
1048 }
1049}
1050
1051void GraphModifier::toggleRotation()
1052{
1053 if (m_rotationTimer.isActive())
1054 m_rotationTimer.stop();
1055 else
1056 m_rotationTimer.start(msec: 20);
1057}
1058
1059void GraphModifier::useLogAxis()
1060{
1061 static int counter = -1;
1062 static QLogValue3DAxisFormatter *logFormatter = 0;
1063 static float minRange = 1.0f;
1064 counter++;
1065
1066 switch (counter) {
1067 case 0: {
1068 qDebug() << "Case" << counter << ": Default log axis";
1069 logFormatter = new QLogValue3DAxisFormatter;
1070 m_graph->valueAxis()->setFormatter(logFormatter);
1071 m_graph->valueAxis()->setRange(min: minRange, max: 1200.0f);
1072 m_graph->valueAxis()->setLabelFormat(QStringLiteral("%.3f"));
1073 break;
1074 }
1075 case 1: {
1076 qDebug() << "Case" << counter << ": Hide max label";
1077 logFormatter->setShowEdgeLabels(false);
1078 break;
1079 }
1080 case 2: {
1081 qDebug() << "Case" << counter << ": Try to hide subgrid unsuccessfully";
1082 m_graph->valueAxis()->setSubSegmentCount(1);
1083 break;
1084 }
1085 case 3: {
1086 qDebug() << "Case" << counter << ": Hide subgrid property";
1087 logFormatter->setAutoSubGrid(false);
1088 m_graph->valueAxis()->setSubSegmentCount(1);
1089 break;
1090 }
1091 case 4: {
1092 qDebug() << "Case" << counter << ": Different base: 2";
1093 logFormatter->setBase(2.0f);
1094 logFormatter->setAutoSubGrid(true);
1095 break;
1096 }
1097 case 5: {
1098 qDebug() << "Case" << counter << ": Different base: 16";
1099 logFormatter->setBase(16.0f);
1100 break;
1101 }
1102 case 6: {
1103 qDebug() << "Case" << counter << ": Invalid bases";
1104 logFormatter->setBase(-1.0f);
1105 logFormatter->setBase(1.0f);
1106 break;
1107 }
1108 case 7: {
1109 qDebug() << "Case" << counter << ": Zero base";
1110 logFormatter->setBase(0.0f);
1111 break;
1112 }
1113 case 8: {
1114 qDebug() << "Case" << counter << ": Explicit ranges and segments";
1115 int segmentCount = 6;
1116 int base = 4;
1117 m_graph->valueAxis()->setSegmentCount(segmentCount);
1118 m_graph->valueAxis()->setSubSegmentCount(base - 1);
1119 m_graph->valueAxis()->setRange(min: 1.0f / float(base * base), max: qPow(x: base, y: segmentCount - 2));
1120 break;
1121 }
1122 case 9: {
1123 qDebug() << "Case" << counter << ": Negative range";
1124 m_graph->valueAxis()->setRange(min: -20.0f, max: 50.0f);
1125 break;
1126 }
1127 case 10: {
1128 qDebug() << "Case" << counter << ": Non-integer base";
1129 logFormatter->setBase(3.3f);
1130 logFormatter->setAutoSubGrid(true);
1131 break;
1132 }
1133 default:
1134 qDebug() << "Resetting logaxis test";
1135 minRange++;
1136 counter = -1;
1137 break;
1138 }
1139}
1140
1141void GraphModifier::changeValueAxisFormat(const QString & text)
1142{
1143 m_graph->valueAxis()->setLabelFormat(text);
1144}
1145
1146void GraphModifier::changeLogBase(const QString &text)
1147{
1148 QLogValue3DAxisFormatter *formatter =
1149 qobject_cast<QLogValue3DAxisFormatter *>(object: m_graph->valueAxis()->formatter());
1150 if (formatter)
1151 formatter->setBase(qreal(text.toDouble()));
1152}
1153
1154void GraphModifier::addRemoveSeries()
1155{
1156 static int counter = 0;
1157
1158 switch (counter) {
1159 case 0: {
1160 qDebug() << __FUNCTION__ << counter << "New series";
1161 m_extraSeries = new QBar3DSeries;
1162 m_graph->addSeries(series: m_extraSeries);
1163 QObject::connect(sender: m_extraSeries, signal: &QBar3DSeries::selectedBarChanged, receiver: this,
1164 slot: &GraphModifier::handleSelectionChange);
1165 }
1166 break;
1167 case 1: {
1168 qDebug() << __FUNCTION__ << counter << "Add data to series";
1169 QBarDataArray *array = new QBarDataArray;
1170 array->reserve(alloc: 5);
1171 for (int i = 0; i < 5; i++) {
1172 array->append(t: new QBarDataRow(10));
1173 for (int j = 0; j < 10; j++)
1174 (*array->at(i))[j].setValue(i * j);
1175 }
1176 m_extraSeries->dataProxy()->resetArray(newArray: array);
1177 }
1178 break;
1179 case 2: {
1180 qDebug() << __FUNCTION__ << counter << "Hide series";
1181 m_extraSeries->setVisible(false);
1182 }
1183 break;
1184 case 3: {
1185 qDebug() << __FUNCTION__ << counter << "Modify data when hidden";
1186 QBarDataArray array;
1187 array.reserve(alloc: 5);
1188 for (int i = 0; i < 5; i++) {
1189 array.append(t: new QBarDataRow(10));
1190 for (int j = 0; j < 10; j++)
1191 (*array.at(i))[j].setValue(2 * i * j);
1192 }
1193 m_extraSeries->dataProxy()->addRows(rows: array);
1194 }
1195 break;
1196 case 4: {
1197 qDebug() << __FUNCTION__ << counter << "Show series again";
1198 m_extraSeries->setVisible(true);
1199 }
1200 break;
1201 case 5: {
1202 qDebug() << __FUNCTION__ << counter << "Remove series";
1203 m_graph->removeSeries(series: m_extraSeries);
1204 delete m_extraSeries;
1205 m_extraSeries = 0;
1206 }
1207 break;
1208 default:
1209 qDebug() << __FUNCTION__ << "Resetting test";
1210 counter = -1;
1211 }
1212 counter++;
1213}
1214
1215void GraphModifier::testItemAndRowChanges()
1216{
1217 static int counter = 0;
1218 const int rowCount = 12;
1219 const int colCount = 10;
1220 const float flatValue = 10.0f;
1221 static QBar3DSeries *series0 = 0;
1222 static QBar3DSeries *series1 = 0;
1223 static QBar3DSeries *series2 = 0;
1224 QBarDataItem item25;
1225 QBarDataItem item50;
1226 QBarDataItem item75;
1227 item25.setValue(25);
1228 item50.setValue(50);
1229 item75.setValue(75);
1230
1231 switch (counter) {
1232 case 0: {
1233 qDebug() << __FUNCTION__ << counter << "Setup test";
1234 releaseSeries();
1235 releaseAxes();
1236 delete series0;
1237 delete series1;
1238 delete series2;
1239 series0 = new QBar3DSeries;
1240 series1 = new QBar3DSeries;
1241 series2 = new QBar3DSeries;
1242 populateFlatSeries(series: series0, rows: rowCount, columns: colCount, value: flatValue);
1243 populateFlatSeries(series: series1, rows: rowCount, columns: colCount, value: flatValue);
1244 populateFlatSeries(series: series2, rows: rowCount, columns: colCount, value: flatValue);
1245 m_graph->rowAxis()->setRange(min: 4.0f, max: 8.0f);
1246 m_graph->columnAxis()->setRange(min: 3.0f, max: 6.0f);
1247 m_graph->valueAxis()->setRange(min: 0.0f, max: 100.0f);
1248 m_graph->addSeries(series: series0);
1249 m_graph->addSeries(series: series1);
1250 m_graph->addSeries(series: series2);
1251 //counter = 11; // skip single item tests
1252 }
1253 break;
1254 case 1: {
1255 qDebug() << __FUNCTION__ << counter << "Change single item, unselected";
1256 series0->dataProxy()->setItem(rowIndex: 4, columnIndex: 3, item: item50);
1257 }
1258 break;
1259 case 2: {
1260 qDebug() << __FUNCTION__ << counter << "Change single item, selected";
1261 series1->setSelectedBar(QPoint(4, 5));
1262 series1->dataProxy()->setItem(rowIndex: 4, columnIndex: 5, item: item25);
1263 }
1264 break;
1265 case 3: {
1266 qDebug() << __FUNCTION__ << counter << "Change item outside visible area";
1267 series1->dataProxy()->setItem(rowIndex: 0, columnIndex: 3, item: item25);
1268 }
1269 break;
1270 case 4: {
1271 qDebug() << __FUNCTION__ << counter << "Change single item from two series, unselected";
1272 series0->dataProxy()->setItem(rowIndex: 5, columnIndex: 3, item: item25);
1273 series1->dataProxy()->setItem(rowIndex: 5, columnIndex: 3, item: item75);
1274 }
1275 break;
1276 case 5: {
1277 qDebug() << __FUNCTION__ << counter << "Change single item from two series, one selected";
1278 series0->dataProxy()->setItem(rowIndex: 5, columnIndex: 4, item: item25);
1279 series1->dataProxy()->setItem(rowIndex: 4, columnIndex: 5, item: item75);
1280 }
1281 break;
1282 case 6: {
1283 qDebug() << __FUNCTION__ << counter << "Change single item from two series, one outside range";
1284 series0->dataProxy()->setItem(rowIndex: 1, columnIndex: 2, item: item25);
1285 series1->dataProxy()->setItem(rowIndex: 6, columnIndex: 6, item: item75);
1286 }
1287 break;
1288 case 7: {
1289 qDebug() << __FUNCTION__ << counter << "Change single item from two series, both outside range";
1290 series0->dataProxy()->setItem(rowIndex: 1, columnIndex: 2, item: item25);
1291 series1->dataProxy()->setItem(rowIndex: 8, columnIndex: 8, item: item75);
1292 }
1293 break;
1294 case 8: {
1295 qDebug() << __FUNCTION__ << counter << "Change item to same value";
1296 series1->dataProxy()->setItem(rowIndex: 6, columnIndex: 6, item: item75);
1297 }
1298 break;
1299 case 9: {
1300 qDebug() << __FUNCTION__ << counter << "Change 3 items on each series";
1301 series0->dataProxy()->setItem(rowIndex: 7, columnIndex: 3, item: item25);
1302 series0->dataProxy()->setItem(rowIndex: 7, columnIndex: 4, item: item50);
1303 series0->dataProxy()->setItem(rowIndex: 7, columnIndex: 5, item: item75);
1304 series1->dataProxy()->setItem(rowIndex: 6, columnIndex: 3, item: item25);
1305 series1->dataProxy()->setItem(rowIndex: 6, columnIndex: 4, item: item50);
1306 series1->dataProxy()->setItem(rowIndex: 6, columnIndex: 5, item: item75);
1307 }
1308 break;
1309 case 10: {
1310 qDebug() << __FUNCTION__ << counter << "Level the field single item at a time";
1311 QBarDataItem item;
1312 item.setValue(15.0f);
1313 for (int i = 0; i < rowCount; i++) {
1314 for (int j = 0; j < colCount; j++) {
1315 series0->dataProxy()->setItem(rowIndex: i, columnIndex: j, item);
1316 series1->dataProxy()->setItem(rowIndex: i, columnIndex: j, item);
1317 series2->dataProxy()->setItem(rowIndex: i, columnIndex: j, item);
1318 }
1319 }
1320 }
1321 break;
1322 case 11: {
1323 qDebug() << __FUNCTION__ << counter << "Change same items multiple times";
1324 series0->dataProxy()->setItem(rowIndex: 7, columnIndex: 3, item: item25);
1325 series1->dataProxy()->setItem(rowIndex: 7, columnIndex: 3, item: item25);
1326 series0->dataProxy()->setItem(rowIndex: 7, columnIndex: 3, item: item50);
1327 series1->dataProxy()->setItem(rowIndex: 7, columnIndex: 3, item: item50);
1328 series0->dataProxy()->setItem(rowIndex: 7, columnIndex: 3, item: item75);
1329 series1->dataProxy()->setItem(rowIndex: 7, columnIndex: 3, item: item75);
1330 }
1331 break;
1332 case 12: {
1333 qDebug() << __FUNCTION__ << counter << "Change row";
1334 series0->dataProxy()->setRow(rowIndex: 5, row: createFlatRow(columns: colCount, value: 50.0f));
1335 }
1336 break;
1337 case 13: {
1338 qDebug() << __FUNCTION__ << counter << "Change row with selected item";
1339 series1->setSelectedBar(QPoint(6, 6));
1340 series1->dataProxy()->setRow(rowIndex: 6, row: createFlatRow(columns: colCount, value: 40.0f));
1341 }
1342 break;
1343 case 14: {
1344 qDebug() << __FUNCTION__ << counter << "Change hidden row";
1345 series1->dataProxy()->setRow(rowIndex: 9, row: createFlatRow(columns: colCount, value: 50.0f));
1346 }
1347 break;
1348 case 15: {
1349 qDebug() << __FUNCTION__ << counter << "Change multiple rows singly";
1350 series0->dataProxy()->setRow(rowIndex: 6, row: createFlatRow(columns: colCount, value: 70.0f));
1351 series1->dataProxy()->setRow(rowIndex: 6, row: createFlatRow(columns: colCount, value: 80.0f));
1352 series2->dataProxy()->setRow(rowIndex: 6, row: createFlatRow(columns: colCount, value: 90.0f));
1353 }
1354 break;
1355 case 16: {
1356 qDebug() << __FUNCTION__ << counter << "Change multiple rows many at a time";
1357 QBarDataArray newRows;
1358 newRows.reserve(alloc: 4);
1359 newRows.append(t: createFlatRow(columns: colCount, value: 26.0f));
1360 newRows.append(t: createFlatRow(columns: colCount, value: 30.0f));
1361 newRows.append(t: createFlatRow(columns: colCount, value: 34.0f));
1362 newRows.append(t: createFlatRow(columns: colCount, value: 38.0f));
1363 series0->dataProxy()->setRows(rowIndex: 2, rows: newRows);
1364 newRows[0] = createFlatRow(columns: colCount, value: 26.0f);
1365 newRows[1] = createFlatRow(columns: colCount, value: 30.0f);
1366 newRows[2] = createFlatRow(columns: colCount, value: 34.0f);
1367 newRows[3] = createFlatRow(columns: colCount, value: 38.0f);
1368 series1->dataProxy()->setRows(rowIndex: 3, rows: newRows);
1369 newRows[0] = createFlatRow(columns: colCount, value: 26.0f);
1370 newRows[1] = createFlatRow(columns: colCount, value: 30.0f);
1371 newRows[2] = createFlatRow(columns: colCount, value: 34.0f);
1372 newRows[3] = createFlatRow(columns: colCount, value: 38.0f);
1373 series2->dataProxy()->setRows(rowIndex: 4, rows: newRows);
1374 }
1375 break;
1376 case 17: {
1377 qDebug() << __FUNCTION__ << counter << "Change same rows multiple times";
1378 QBarDataArray newRows;
1379 newRows.reserve(alloc: 4);
1380 newRows.append(t: createFlatRow(columns: colCount, value: 65.0f));
1381 newRows.append(t: createFlatRow(columns: colCount, value: 65.0f));
1382 newRows.append(t: createFlatRow(columns: colCount, value: 65.0f));
1383 newRows.append(t: createFlatRow(columns: colCount, value: 65.0f));
1384 series0->dataProxy()->setRows(rowIndex: 4, rows: newRows);
1385 newRows[0] = createFlatRow(columns: colCount, value: 65.0f);
1386 newRows[1] = createFlatRow(columns: colCount, value: 65.0f);
1387 newRows[2] = createFlatRow(columns: colCount, value: 65.0f);
1388 newRows[3] = createFlatRow(columns: colCount, value: 65.0f);
1389 series1->dataProxy()->setRows(rowIndex: 4, rows: newRows);
1390 newRows[0] = createFlatRow(columns: colCount, value: 65.0f);
1391 newRows[1] = createFlatRow(columns: colCount, value: 65.0f);
1392 newRows[2] = createFlatRow(columns: colCount, value: 65.0f);
1393 newRows[3] = createFlatRow(columns: colCount, value: 65.0f);
1394 series2->dataProxy()->setRows(rowIndex: 4, rows: newRows);
1395 series0->dataProxy()->setRow(rowIndex: 6, row: createFlatRow(columns: colCount, value: 20.0f));
1396 series1->dataProxy()->setRow(rowIndex: 6, row: createFlatRow(columns: colCount, value: 20.0f));
1397 series2->dataProxy()->setRow(rowIndex: 6, row: createFlatRow(columns: colCount, value: 20.0f));
1398 series0->dataProxy()->setRow(rowIndex: 6, row: createFlatRow(columns: colCount, value: 90.0f));
1399 series1->dataProxy()->setRow(rowIndex: 6, row: createFlatRow(columns: colCount, value: 90.0f));
1400 series2->dataProxy()->setRow(rowIndex: 6, row: createFlatRow(columns: colCount, value: 90.0f));
1401 }
1402 break;
1403 case 18: {
1404 qDebug() << __FUNCTION__ << counter << "Change row to different length";
1405 series0->dataProxy()->setRow(rowIndex: 4, row: createFlatRow(columns: 5, value: 20.0f));
1406 series1->dataProxy()->setRow(rowIndex: 4, row: createFlatRow(columns: 0, value: 20.0f));
1407 series2->dataProxy()->setRow(rowIndex: 4, row: 0);
1408 }
1409 break;
1410 case 19: {
1411 qDebug() << __FUNCTION__ << counter << "Change selected row shorter so that selected item is no longer valid";
1412 series1->dataProxy()->setRow(rowIndex: 6, row: createFlatRow(columns: 6, value: 20.0f));
1413 }
1414 break;
1415 default:
1416 qDebug() << __FUNCTION__ << "Resetting test";
1417 counter = -1;
1418 }
1419 counter++;
1420}
1421
1422void GraphModifier::reverseValueAxis(int enabled)
1423{
1424 m_graph->valueAxis()->setReversed(enabled);
1425}
1426
1427void GraphModifier::setInputHandlerRotationEnabled(int enabled)
1428{
1429 m_defaultInputHandler->setRotationEnabled(enabled);
1430}
1431
1432void GraphModifier::setInputHandlerZoomEnabled(int enabled)
1433{
1434 m_defaultInputHandler->setZoomEnabled(enabled);
1435}
1436
1437void GraphModifier::setInputHandlerSelectionEnabled(int enabled)
1438{
1439 m_defaultInputHandler->setSelectionEnabled(enabled);
1440}
1441
1442void GraphModifier::setInputHandlerZoomAtTargetEnabled(int enabled)
1443{
1444 m_defaultInputHandler->setZoomAtTargetEnabled(enabled);
1445}
1446
1447void GraphModifier::changeValueAxisSegments(int value)
1448{
1449 qDebug() << __FUNCTION__ << value;
1450 m_segments = value;
1451 m_graph->valueAxis()->setSegmentCount(m_segments);
1452}
1453
1454void GraphModifier::insertRemoveTimerTimeout()
1455{
1456 if (m_insertRemoveStep < 32) {
1457 for (int k = 0; k < 1; k++) {
1458 QBarDataRow *dataRow = new QBarDataRow(10);
1459 for (float i = 0; i < 10; i++)
1460 (*dataRow)[i].setValue(((i + 1) / 10.0f) * (float)(QRandomGenerator::global()->bounded(highest: 100)));
1461
1462 QString label = QStringLiteral("Insert %1").arg(a: insertCounter++);
1463 m_dummyData->dataProxy()->insertRow(rowIndex: 0, row: dataRow, label);
1464 }
1465 } else {
1466 for (int k = 0; k < 1; k++)
1467 m_dummyData->dataProxy()->removeRows(rowIndex: 0, removeCount: 1);
1468 }
1469
1470 if (m_insertRemoveStep < 16 || (m_insertRemoveStep > 31 && m_insertRemoveStep < 48)) {
1471 for (int k = 0; k < 2; k++) {
1472 QBarDataRow *dataRow = new QBarDataRow(10);
1473 for (float i = 0; i < 10; i++)
1474 (*dataRow)[i].setValue(((i + 1) / 10.0f) * (float)(QRandomGenerator::global()->bounded(highest: 100)));
1475
1476 QString label = QStringLiteral("Insert %1").arg(a: insertCounter++);
1477 m_dummyData2->dataProxy()->insertRow(rowIndex: 0, row: dataRow, label);
1478 }
1479 } else {
1480 for (int k = 0; k < 2; k++)
1481 m_dummyData2->dataProxy()->removeRows(rowIndex: 0, removeCount: 1);
1482 }
1483
1484 if (m_insertRemoveStep++ > 63)
1485 m_insertRemoveStep = 0;
1486}
1487
1488void GraphModifier::triggerSelection()
1489{
1490 m_graph->scene()->setSelectionQueryPosition(m_customInputHandler->inputPosition());
1491}
1492
1493void GraphModifier::triggerRotation()
1494{
1495 if (m_selectedSeries) {
1496 QPoint selectedBar = m_selectedSeries->selectedBar();
1497 if (selectedBar != QBar3DSeries::invalidSelectionPosition()) {
1498 QBarDataItem item(*(m_selectedSeries->dataProxy()->itemAt(rowIndex: selectedBar.x(), columnIndex: selectedBar.y())));
1499 item.setRotation(item.rotation() + 1.0f);
1500 m_selectedSeries->dataProxy()->setItem(rowIndex: selectedBar.x(), columnIndex: selectedBar.y(), item);
1501 }
1502 } else {
1503 // Rotate the first series instead
1504 static float seriesAngle = 0.0f;
1505 if (m_graph->seriesList().size())
1506 m_graph->seriesList().at(i: 0)->setMeshAngle(seriesAngle++);
1507 }
1508}
1509
1510void GraphModifier::handleValueAxisLabelsChanged()
1511{
1512 qDebug() << __FUNCTION__;
1513}
1514
1515void GraphModifier::handleFpsChange(qreal fps)
1516{
1517 static const QString fpsPrefix(QStringLiteral("FPS: "));
1518 m_fpsLabel->setText(fpsPrefix + QString::number(qRound(d: fps)));
1519}
1520
1521void GraphModifier::setCameraTargetX(int value)
1522{
1523 // Value is (-100, 100), normalize
1524 m_cameraTarget.setX(float(value) / 100.0f);
1525 m_graph->scene()->activeCamera()->setTarget(m_cameraTarget);
1526 qDebug() << "m_cameraTarget:" << m_cameraTarget;
1527}
1528
1529void GraphModifier::setCameraTargetY(int value)
1530{
1531 // Value is (-100, 100), normalize
1532 m_cameraTarget.setY(float(value) / 100.0f);
1533 m_graph->scene()->activeCamera()->setTarget(m_cameraTarget);
1534 qDebug() << "m_cameraTarget:" << m_cameraTarget;
1535}
1536
1537void GraphModifier::setCameraTargetZ(int value)
1538{
1539 // Value is (-100, 100), normalize
1540 m_cameraTarget.setZ(float(value) / 100.0f);
1541 m_graph->scene()->activeCamera()->setTarget(m_cameraTarget);
1542 qDebug() << "m_cameraTarget:" << m_cameraTarget;
1543}
1544
1545void GraphModifier::setFloorLevel(int value)
1546{
1547 m_graph->setFloorLevel(float(value));
1548 qDebug() << "Floor level:" << value;
1549}
1550
1551void GraphModifier::setGraphMargin(int value)
1552{
1553 m_graph->setMargin(qreal(value) / 100.0);
1554 qDebug() << "Setting margin:" << m_graph->margin() << value;
1555}
1556
1557void GraphModifier::populateFlatSeries(QBar3DSeries *series, int rows, int columns, float value)
1558{
1559 QBarDataArray *dataArray = new QBarDataArray;
1560 dataArray->reserve(alloc: rows);
1561 for (int i = 0; i < rows; i++) {
1562 QBarDataRow *dataRow = new QBarDataRow(columns);
1563 for (int j = 0; j < columns; j++)
1564 (*dataRow)[j].setValue(value);
1565 dataArray->append(t: dataRow);
1566 }
1567 QStringList axisLabels;
1568 int count = qMax(a: rows, b: columns);
1569 for (int i = 0; i < count; i++)
1570 axisLabels << QString::number(i);
1571
1572 series->dataProxy()->resetArray(newArray: dataArray, rowLabels: axisLabels, columnLabels: axisLabels);
1573}
1574
1575QBarDataRow *GraphModifier::createFlatRow(int columns, float value)
1576{
1577 QBarDataRow *dataRow = new QBarDataRow(columns);
1578 for (int j = 0; j < columns; j++)
1579 (*dataRow)[j].setValue(value);
1580 return dataRow;
1581}
1582
1583void GraphModifier::setBackgroundEnabled(int enabled)
1584{
1585 m_graph->activeTheme()->setBackgroundEnabled(bool(enabled));
1586}
1587
1588void GraphModifier::setGridEnabled(int enabled)
1589{
1590 m_graph->activeTheme()->setGridEnabled(bool(enabled));
1591}
1592
1593void GraphModifier::rotateX(int rotation)
1594{
1595 m_xRotation = rotation;
1596 m_graph->scene()->activeCamera()->setCameraPosition(horizontal: m_xRotation, vertical: m_yRotation);
1597}
1598
1599void GraphModifier::rotateY(int rotation)
1600{
1601 m_yRotation = rotation;
1602 m_graph->scene()->activeCamera()->setCameraPosition(horizontal: m_xRotation, vertical: m_yRotation);
1603}
1604
1605void GraphModifier::setFpsMeasurement(bool enable)
1606{
1607 m_graph->setMeasureFps(enable);
1608}
1609
1610void GraphModifier::setSpecsRatio(int barwidth)
1611{
1612 m_graph->setBarThickness((float)barwidth / 30.0f);
1613}
1614
1615void GraphModifier::setSpacingSpecsX(int spacing)
1616{
1617 m_barSpacingX = (float)spacing / 100.0f;
1618 m_graph->setBarSpacing(QSizeF(m_barSpacingX, m_barSpacingZ));
1619}
1620
1621void GraphModifier::setSpacingSpecsZ(int spacing)
1622{
1623 m_barSpacingZ = (float)spacing / 100.0f;
1624 m_graph->setBarSpacing(QSizeF(m_barSpacingX, m_barSpacingZ));
1625}
1626
1627void GraphModifier::setSampleCountX(int samples)
1628{
1629 m_columnCount = samples;
1630 m_genericColumnAxis->setRange(min: m_genericRowAxis->min(), max: m_genericRowAxis->min() + samples - 1);
1631}
1632
1633void GraphModifier::setSampleCountZ(int samples)
1634{
1635 m_rowCount = samples;
1636 m_genericRowAxis->setRange(min: m_genericColumnAxis->min(), max: m_genericColumnAxis->min() + samples - 1);
1637}
1638
1639void GraphModifier::setMinX(int min)
1640{
1641 m_genericRowAxis->setRange(min, max: min + m_rowCount - 1);
1642}
1643
1644void GraphModifier::setMinZ(int min)
1645{
1646 m_genericColumnAxis->setRange(min, max: min + m_rowCount - 1);
1647}
1648
1649void GraphModifier::setMinY(int min)
1650{
1651 m_fixedRangeAxis->setMin(min);
1652 m_negativeValuesOn = (min < 0) ? true : false;
1653 m_minval = min;
1654}
1655
1656void GraphModifier::setMaxY(int max)
1657{
1658 m_fixedRangeAxis->setMax(max);
1659 m_maxval = max;
1660}
1661
1662void GraphModifier::changeColorStyle()
1663{
1664 int style = m_graph->activeTheme()->colorStyle();
1665
1666 if (++style > Q3DTheme::ColorStyleRangeGradient)
1667 style = Q3DTheme::ColorStyleUniform;
1668
1669 m_graph->activeTheme()->setColorStyle(Q3DTheme::ColorStyle(style));
1670}
1671
1672void GraphModifier::useOwnTheme()
1673{
1674 // Own theme is persistent, any changes to it via UI will be remembered
1675 if (!m_ownTheme) {
1676 m_ownTheme = new Q3DTheme();
1677 m_ownTheme->setBackgroundEnabled(true);
1678 m_ownTheme->setGridEnabled(true);
1679 m_ownTheme->setAmbientLightStrength(0.3f);
1680 m_ownTheme->setBackgroundColor(QColor(QRgb(0x99ca53)));
1681 QList<QColor> colors;
1682 colors.append(t: QColor(QRgb(0x209fdf)));
1683 m_ownTheme->setBaseColors(colors);
1684 m_ownTheme->setColorStyle(Q3DTheme::ColorStyleUniform);
1685 m_ownTheme->setGridLineColor(QColor(QRgb(0x99ca53)));
1686 m_ownTheme->setHighlightLightStrength(7.0f);
1687 m_ownTheme->setLabelBackgroundEnabled(true);
1688 m_ownTheme->setLabelBorderEnabled(true);
1689 m_ownTheme->setLightColor(Qt::white);
1690 m_ownTheme->setLightStrength(6.0f);
1691 m_ownTheme->setMultiHighlightColor(QColor(QRgb(0x6d5fd5)));
1692 m_ownTheme->setSingleHighlightColor(QColor(QRgb(0xf6a625)));
1693 m_ownTheme->setLabelBackgroundColor(QColor(0xf6, 0xa6, 0x25, 0xa0));
1694 m_ownTheme->setLabelTextColor(QColor(QRgb(0x404044)));
1695 m_ownTheme->setWindowColor(QColor(QRgb(0xffffff)));
1696 }
1697
1698 m_graph->setActiveTheme(m_ownTheme);
1699
1700 m_colorDialog->open();
1701}
1702
1703void GraphModifier::changeBaseColor(const QColor &color)
1704{
1705 qDebug() << "base color changed to" << color;
1706 QList<QColor> colors;
1707 colors.append(t: color);
1708 m_graph->activeTheme()->setBaseColors(colors);
1709}
1710
1711void GraphModifier::setGradient()
1712{
1713 QLinearGradient barGradient(0, 0, 1, 100);
1714 barGradient.setColorAt(pos: 1.0, color: Qt::lightGray);
1715 barGradient.setColorAt(pos: 0.75001, color: Qt::lightGray);
1716 barGradient.setColorAt(pos: 0.75, color: Qt::blue);
1717 barGradient.setColorAt(pos: 0.50001, color: Qt::blue);
1718 barGradient.setColorAt(pos: 0.50, color: Qt::red);
1719 barGradient.setColorAt(pos: 0.25001, color: Qt::red);
1720 barGradient.setColorAt(pos: 0.25, color: Qt::yellow);
1721 barGradient.setColorAt(pos: 0.0, color: Qt::yellow);
1722
1723 QLinearGradient singleHighlightGradient(0, 0, 1, 100);
1724 singleHighlightGradient.setColorAt(pos: 1.0, color: Qt::white);
1725 singleHighlightGradient.setColorAt(pos: 0.75, color: Qt::lightGray);
1726 singleHighlightGradient.setColorAt(pos: 0.50, color: Qt::gray);
1727 singleHighlightGradient.setColorAt(pos: 0.25, color: Qt::darkGray);
1728 singleHighlightGradient.setColorAt(pos: 0.0, color: Qt::black);
1729
1730 QLinearGradient multiHighlightGradient(0, 0, 1, 100);
1731 multiHighlightGradient.setColorAt(pos: 1.0, color: Qt::black);
1732 multiHighlightGradient.setColorAt(pos: 0.75, color: Qt::darkBlue);
1733 multiHighlightGradient.setColorAt(pos: 0.50, color: Qt::darkRed);
1734 multiHighlightGradient.setColorAt(pos: 0.25, color: Qt::darkYellow);
1735 multiHighlightGradient.setColorAt(pos: 0.0, color: Qt::darkGray);
1736
1737 QList<QLinearGradient> barGradients;
1738 barGradients.append(t: barGradient);
1739 m_graph->activeTheme()->setBaseGradients(barGradients);
1740 m_graph->activeTheme()->setSingleHighlightGradient(singleHighlightGradient);
1741 m_graph->activeTheme()->setMultiHighlightGradient(multiHighlightGradient);
1742
1743 m_graph->activeTheme()->setColorStyle(Q3DTheme::ColorStyleObjectGradient);
1744}
1745
1746void GraphModifier::toggleMultiseriesScaling()
1747{
1748 m_graph->setMultiSeriesUniform(!m_graph->isMultiSeriesUniform());
1749}
1750
1751void GraphModifier::setReflection(bool enabled)
1752{
1753 m_graph->setReflection(enabled);
1754}
1755
1756void GraphModifier::setReflectivity(int value)
1757{
1758 qreal reflectivity = (qreal)value / 100.0;
1759 m_graph->setReflectivity(reflectivity);
1760}
1761
1762void GraphModifier::toggleCustomItem()
1763{
1764 static int counter = 0;
1765 int state = ++counter % 3;
1766
1767 QVector3D positionOne = QVector3D(6.0f, -15.0f, 3.0f);
1768 QVector3D positionTwo = QVector3D(2.0f, 18.0f, 3.0f);
1769
1770 if (state == 0) {
1771 m_graph->removeCustomItemAt(position: positionTwo);
1772 } else if (state == 1) {
1773 QCustom3DItem *item = new QCustom3DItem();
1774 item->setMeshFile(":/shuttle.obj");
1775 item->setPosition(positionOne);
1776 item->setScaling(QVector3D(0.1f, 0.1f, 0.1f));
1777 item->setRotation(QQuaternion::fromAxisAndAngle(x: 0.0f, y: 1.0f, z: 0.0f, angle: QRandomGenerator::global()->generate()));
1778 item->setTextureImage(QImage(":/shuttle.png"));
1779 m_graph->addCustomItem(item);
1780 } else {
1781 m_graph->removeCustomItemAt(position: positionOne);
1782 QCustom3DItem *item = new QCustom3DItem();
1783 item->setMeshFile(":/shuttle.obj");
1784 item->setPosition(positionTwo);
1785 item->setScaling(QVector3D(0.1f, 0.1f, 0.1f));
1786 item->setRotation(QQuaternion::fromAxisAndAngle(x: 0.0f, y: 1.0f, z: 0.0f, angle: QRandomGenerator::global()->generate()));
1787 item->setTextureImage(QImage(":/shuttle.png"));
1788 m_graph->addCustomItem(item);
1789 }
1790}
1791

source code of qtdatavis3d/tests/manual/barstest/chart.cpp