##// END OF EJS Templates
Fix crash with boxplottertester brush...
Titta Heikkala -
r2635:d3155254bba4
parent child
Show More
@@ -1,484 +1,487
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Enterprise Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Enterprise licenses may use this file in
11 11 ** accordance with the Qt Enterprise License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "mainwidget.h"
22 22 #include "customtablemodel.h"
23 23 #include "pentool.h"
24 24 #include <QVBoxPlotModelMapper>
25 25 #include <QTableView>
26 26 #include <QHeaderView>
27 27 #include <QChartView>
28 28 #include <QBoxPlotSeries>
29 29 #include <QBoxSet>
30 30 #include <QLegend>
31 31 #include <QBarCategoryAxis>
32 32 #include <QBrush>
33 33 #include <QColor>
34 34 #include <QPushButton>
35 35 #include <QComboBox>
36 36 #include <QSpinBox>
37 37 #include <QCheckBox>
38 38 #include <QGridLayout>
39 39 #include <QHBoxLayout>
40 40 #include <QLabel>
41 41 #include <QSpacerItem>
42 42 #include <QMessageBox>
43 43 #include <cmath>
44 44 #include <QDebug>
45 45 #include <QStandardItemModel>
46 46 #include <QBarCategoryAxis>
47 47 #include <QLogValueAxis>
48 48
49 49 QTCOMMERCIALCHART_USE_NAMESPACE
50 50
51 51 static const QString allCategories[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
52 52 static const int maxCategories = 12;
53 53
54 54 MainWidget::MainWidget(QWidget *parent) :
55 55 QWidget(parent),
56 56 m_chart(0),
57 57 m_axis(0),
58 58 m_rowPos(0),
59 59 m_seriesCount(0)
60 60 {
61 61 m_chart = new QChart();
62 62
63 63 m_penTool = new PenTool("Whiskers pen", this);
64 64
65 65 // Grid layout for the controls for configuring the chart widget
66 66 QGridLayout *grid = new QGridLayout();
67 67
68 68 // Create add a series button
69 69 QPushButton *addSeriesButton = new QPushButton("Add a series");
70 70 connect(addSeriesButton, SIGNAL(clicked()), this, SLOT(addSeries()));
71 71 grid->addWidget(addSeriesButton, m_rowPos++, 1);
72 72
73 73 // Create remove a series button
74 74 QPushButton *removeSeriesButton = new QPushButton("Remove a series");
75 75 connect(removeSeriesButton, SIGNAL(clicked()), this, SLOT(removeSeries()));
76 76 grid->addWidget(removeSeriesButton, m_rowPos++, 1);
77 77
78 78 // Create add a single box button
79 79 QPushButton *addBoxButton = new QPushButton("Add a box");
80 80 connect(addBoxButton, SIGNAL(clicked()), this, SLOT(addBox()));
81 81 grid->addWidget(addBoxButton, m_rowPos++, 1);
82 82
83 83 // Create insert a box button
84 84 QPushButton *insertBoxButton = new QPushButton("Insert a box");
85 85 connect(insertBoxButton, SIGNAL(clicked()), this, SLOT(insertBox()));
86 86 grid->addWidget(insertBoxButton, m_rowPos++, 1);
87 87
88 88 // Create add a single box button
89 89 QPushButton *removeBoxButton = new QPushButton("Remove a box");
90 90 connect(removeBoxButton, SIGNAL(clicked()), this, SLOT(removeBox()));
91 91 grid->addWidget(removeBoxButton, m_rowPos++, 1);
92 92
93 93 // Create clear button
94 94 QPushButton *clearButton = new QPushButton("Clear");
95 95 connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
96 96 grid->addWidget(clearButton, m_rowPos++, 1);
97 97
98 98 // Create clear button
99 99 QPushButton *clearBoxButton = new QPushButton("ClearBox");
100 100 connect(clearBoxButton, SIGNAL(clicked()), this, SLOT(clearBox()));
101 101 grid->addWidget(clearBoxButton, m_rowPos++, 1);
102 102
103 103 // Create set brush button
104 104 QPushButton *setBrushButton = new QPushButton("Set brush");
105 105 connect(setBrushButton, SIGNAL(clicked()), this, SLOT(setBrush()));
106 106 grid->addWidget(setBrushButton, m_rowPos++, 1);
107 107
108 108 // Create set whiskers pen button
109 109 QPushButton *setWhiskersButton = new QPushButton("Whiskers pen");
110 110 connect(setWhiskersButton, SIGNAL(clicked()), m_penTool, SLOT(show()));
111 111 connect(m_penTool, SIGNAL(changed()), this, SLOT(changePen()));
112 112 grid->addWidget(setWhiskersButton, m_rowPos++, 1);
113 113
114 114 // Box width setting
115 115 m_boxWidthSB = new QDoubleSpinBox();
116 116 m_boxWidthSB->setMinimum(-1.0);
117 117 m_boxWidthSB->setMaximum(2.0);
118 118 m_boxWidthSB->setSingleStep(0.1);
119 119 m_boxWidthSB->setValue(0.5);
120 120 grid->addWidget(new QLabel("Box width:"), m_rowPos, 0);
121 121 grid->addWidget(m_boxWidthSB, m_rowPos++, 1);
122 122 connect(m_boxWidthSB, SIGNAL(valueChanged(double)), this, SLOT(setBoxWidth(double)));
123 123
124 124 initThemeCombo(grid);
125 125 initCheckboxes(grid);
126 126
127 127 m_model = new CustomTableModel();
128 128 QTableView *tableView = new QTableView;
129 129 tableView->setModel(m_model);
130 130 tableView->setMaximumWidth(200);
131 131 grid->addWidget(tableView, m_rowPos++, 0, 3, 2, Qt::AlignLeft);
132 132 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
133 133 tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
134 134 tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
135 135 #else
136 136 tableView->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
137 137 tableView->verticalHeader()->setResizeMode(QHeaderView::Stretch);
138 138 #endif
139 139
140 140 // add row with empty label to make all the other rows static
141 141 grid->addWidget(new QLabel(""), grid->rowCount(), 0);
142 142 grid->setRowStretch(grid->rowCount() - 1, 1);
143 143
144 144 // Create chart view with the chart
145 145 m_chartView = new QChartView(m_chart, this);
146 146
147 147 // As a default antialiasing is off
148 148 m_chartView->setRenderHint(QPainter::Antialiasing, false);
149 149
150 150 // Another grid layout as a main layout
151 151 QGridLayout *mainLayout = new QGridLayout();
152 152 mainLayout->addLayout(grid, 0, 0);
153 153 mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
154 154 setLayout(mainLayout);
155 155
156 156 legendToggled(false);
157 157 animationToggled(false);
158 158 }
159 159
160 160 // Combo box for selecting theme
161 161 void MainWidget::initThemeCombo(QGridLayout *grid)
162 162 {
163 163 QComboBox *chartTheme = new QComboBox();
164 164 chartTheme->addItem("Default");
165 165 chartTheme->addItem("Light");
166 166 chartTheme->addItem("Blue Cerulean");
167 167 chartTheme->addItem("Dark");
168 168 chartTheme->addItem("Brown Sand");
169 169 chartTheme->addItem("Blue NCS");
170 170 chartTheme->addItem("High Contrast");
171 171 chartTheme->addItem("Blue Icy");
172 172 chartTheme->addItem("Qt");
173 173 connect(chartTheme, SIGNAL(currentIndexChanged(int)),
174 174 this, SLOT(changeChartTheme(int)));
175 175 grid->addWidget(new QLabel("Chart theme:"), m_rowPos, 0);
176 176 grid->addWidget(chartTheme, m_rowPos++, 1);
177 177 }
178 178
179 179 // Different check boxes for customizing chart
180 180 void MainWidget::initCheckboxes(QGridLayout *grid)
181 181 {
182 182 QCheckBox *animationCheckBox = new QCheckBox("Animation");
183 183 connect(animationCheckBox, SIGNAL(toggled(bool)), this, SLOT(animationToggled(bool)));
184 184 animationCheckBox->setChecked(false);
185 185 grid->addWidget(animationCheckBox, m_rowPos++, 0);
186 186
187 187 QCheckBox *legendCheckBox = new QCheckBox("Legend");
188 188 connect(legendCheckBox, SIGNAL(toggled(bool)), this, SLOT(legendToggled(bool)));
189 189 legendCheckBox->setChecked(false);
190 190 grid->addWidget(legendCheckBox, m_rowPos++, 0);
191 191
192 192 QCheckBox *titleCheckBox = new QCheckBox("Title");
193 193 connect(titleCheckBox, SIGNAL(toggled(bool)), this, SLOT(titleToggled(bool)));
194 194 titleCheckBox->setChecked(false);
195 195 grid->addWidget(titleCheckBox, m_rowPos++, 0);
196 196
197 197 QCheckBox *antialiasingCheckBox = new QCheckBox("Antialiasing");
198 198 connect(antialiasingCheckBox, SIGNAL(toggled(bool)), this, SLOT(antialiasingToggled(bool)));
199 199 antialiasingCheckBox->setChecked(false);
200 200 grid->addWidget(antialiasingCheckBox, m_rowPos++, 0);
201 201
202 202 QCheckBox *modelMapperCheckBox = new QCheckBox("Use model mapper");
203 203 connect(modelMapperCheckBox, SIGNAL(toggled(bool)), this, SLOT(modelMapperToggled(bool)));
204 204 modelMapperCheckBox->setChecked(false);
205 205 grid->addWidget(modelMapperCheckBox, m_rowPos++, 0);
206 206
207 207 m_boxOutlined = new QCheckBox("Box outlined");
208 208 connect(m_boxOutlined, SIGNAL(toggled(bool)), this, SLOT(boxOutlineToggled(bool)));
209 209 m_boxOutlined->setChecked(true);
210 210 grid->addWidget(m_boxOutlined, m_rowPos++, 0);
211 211 }
212 212
213 213 void MainWidget::updateAxis(int categoryCount)
214 214 {
215 215 if (!m_axis) {
216 216 m_chart->createDefaultAxes();
217 217 m_axis = new QBarCategoryAxis();
218 218 }
219 219 QStringList categories;
220 220 for (int i = 0; i < categoryCount; i++)
221 221 categories << allCategories[i];
222 222 m_axis->setCategories(categories);
223 223 }
224 224
225 225 void MainWidget::addSeries()
226 226 {
227 227 qDebug() << "BoxPlotTester::MainWidget::addSeries()";
228 228
229 229 if (m_seriesCount > 9)
230 230 return;
231 231
232 232 // Initial data
233 233 QBoxSet *set0 = new QBoxSet();
234 234 QBoxSet *set1 = new QBoxSet();
235 235 QBoxSet *set2 = new QBoxSet();
236 236 QBoxSet *set3 = new QBoxSet();
237 237 QBoxSet *set4 = new QBoxSet();
238 238 QBoxSet *set5 = new QBoxSet();
239 239
240 240 // low bot med top upp
241 241 *set0 << -1 << 2 << 4 << 13 << 15;
242 242 *set1 << 5 << 6 << 7.5 << 8 << 12;
243 243 *set2 << 3 << 5 << 5.7 << 8 << 9;
244 244 *set3 << 5 << 6 << 6.8 << 7 << 8;
245 245 *set4 << 4 << 5 << 5.2 << 6 << 7;
246 246 *set5 << 4 << 7 << 8.2 << 9 << 10;
247 247
248 248 m_series[m_seriesCount] = new QBoxPlotSeries();
249 249 m_series[m_seriesCount]->append(set0);
250 250 m_series[m_seriesCount]->append(set1);
251 251 m_series[m_seriesCount]->append(set2);
252 252 m_series[m_seriesCount]->append(set3);
253 253 m_series[m_seriesCount]->append(set4);
254 254 m_series[m_seriesCount]->append(set5);
255 255 m_series[m_seriesCount]->setName("Box & Whiskers");
256 256
257 257 connect(m_series[m_seriesCount], SIGNAL(clicked(QBoxSet*)), this, SLOT(boxClicked(QBoxSet*)));
258 258 connect(m_series[m_seriesCount], SIGNAL(hovered(bool, QBoxSet*)), this, SLOT(boxHovered(bool, QBoxSet*)));
259 259 connect(set1, SIGNAL(clicked()), this, SLOT(singleBoxClicked()));
260 260 connect(set2, SIGNAL(hovered(bool)), this, SLOT(singleBoxHovered(bool)));
261 261
262 262 m_series[m_seriesCount]->setBoxOutlineVisible(m_boxOutlined->checkState());
263 263 m_series[m_seriesCount]->setBoxWidth(m_boxWidthSB->value());
264 264
265 265 m_chart->addSeries(m_series[m_seriesCount]);
266 266
267 267 updateAxis(m_series[0]->count());
268 268 m_chart->setAxisX(m_axis, m_series[m_seriesCount]);
269 269
270 270 m_seriesCount++;
271 271 }
272 272
273 273 void MainWidget::removeSeries()
274 274 {
275 275 qDebug() << "BoxPlotTester::MainWidget::removeSeries()";
276 276
277 277 if (m_seriesCount > 0) {
278 278 m_seriesCount--;
279 279 m_chart->removeSeries(m_series[m_seriesCount]);
280 280 delete m_series[m_seriesCount];
281 281 m_series[m_seriesCount] = 0;
282 282 } else {
283 283 qDebug() << "Create a series first";
284 284 }
285 285 }
286 286
287 287 void MainWidget::addBox()
288 288 {
289 289 qDebug() << "BoxPlotTester::MainWidget::addBox()";
290 290
291 291 if (m_seriesCount > 0 && m_series[0]->count() < maxCategories) {
292 292 QBoxSet *newSet = new QBoxSet();
293 293 newSet->setValue(QBoxSet::LowerExtreme, 5.0);
294 294 newSet->setValue(QBoxSet::LowerQuartile, 6.0);
295 295 newSet->setValue(QBoxSet::Median, 6.8);
296 296 newSet->setValue(QBoxSet::UpperQuartile, 7.0);
297 297 newSet->setValue(QBoxSet::UpperExtreme, 8.0);
298 298
299 299 updateAxis(m_series[0]->count() + 1);
300 300
301 301 m_series[0]->append(newSet);
302 302 }
303 303 }
304 304
305 305 void MainWidget::insertBox()
306 306 {
307 307 qDebug() << "BoxPlotTester::MainWidget::insertBox()";
308 308
309 309 if (m_seriesCount > 0 && m_series[0]->count() < maxCategories) {
310 310 updateAxis(m_series[0]->count() + 1);
311 311 for (int i = 0; i < m_seriesCount; i++) {
312 312 QBoxSet *newSet = new QBoxSet();
313 313 *newSet << 2 << 6 << 6.8 << 7 << 10;
314 314 m_series[i]->insert(1, newSet);
315 315 }
316 316 }
317 317 }
318 318
319 319 void MainWidget::removeBox()
320 320 {
321 321 qDebug() << "BoxPlotTester::MainWidget::removeBox";
322 322
323 323 if (m_seriesCount > 0) {
324 324 for (int i = 0; i < m_seriesCount; i++) {
325 325 qDebug() << "m_series[i]->count() = " << m_series[i]->count();
326 326 if (m_series[i]->count()) {
327 327 QList<QBoxSet *> sets = m_series[i]->boxSets();
328 328 m_series[i]->remove(sets.at(m_series[i]->count() - 1));
329 329 }
330 330 }
331 331
332 332 updateAxis(m_series[0]->count());
333 333 } else {
334 334 qDebug() << "Create a series first";
335 335 }
336 336 }
337 337
338 338 void MainWidget::clear()
339 339 {
340 340 qDebug() << "BoxPlotTester::MainWidget::clear";
341 341
342 342 if (m_seriesCount > 0)
343 343 m_series[0]->clear();
344 344 else
345 345 qDebug() << "Create a series first";
346 346 }
347 347
348 348 void MainWidget::clearBox()
349 349 {
350 350 qDebug() << "BoxPlotTester::MainWidget::clearBox";
351 351
352 352 if (m_seriesCount > 0) {
353 353 QList<QBoxSet *> sets = m_series[0]->boxSets();
354 354 if (sets.count() > 1)
355 355 sets.at(1)->clear();
356 356 else
357 357 qDebug() << "Create a series with at least two items first";
358 358 } else {
359 359 qDebug() << "Create a series first";
360 360 }
361 361 }
362 362
363 363 void MainWidget::setBrush()
364 364 {
365 365 qDebug() << "BoxPlotTester::MainWidget::setBrush";
366 366
367 367 if (m_seriesCount > 0) {
368 368 QList<QBoxSet *> sets = m_series[0]->boxSets();
369 sets.at(1)->setBrush(QBrush(QColor(Qt::yellow)));
369 if (sets.count() > 1)
370 sets.at(1)->setBrush(QBrush(QColor(Qt::yellow)));
371 else
372 qDebug() << "Create a series with at least two items first";
370 373 } else {
371 374 qDebug() << "Create a series first";
372 375 }
373 376 }
374 377
375 378 void MainWidget::animationToggled(bool enabled)
376 379 {
377 380 qDebug() << "BoxPlotTester::Animation toggled to " << enabled;
378 381 if (enabled)
379 382 m_chart->setAnimationOptions(QChart::SeriesAnimations);
380 383 else
381 384 m_chart->setAnimationOptions(QChart::NoAnimation);
382 385 }
383 386
384 387 void MainWidget::legendToggled(bool enabled)
385 388 {
386 389 qDebug() << "BoxPlotTester::Legend toggled to " << enabled;
387 390 m_chart->legend()->setVisible(enabled);
388 391 if (enabled)
389 392 m_chart->legend()->setAlignment(Qt::AlignBottom);
390 393 }
391 394
392 395 void MainWidget::titleToggled(bool enabled)
393 396 {
394 397 qDebug() << "BoxPlotTester::Title toggled to " << enabled;
395 398 if (enabled)
396 399 m_chart->setTitle("Simple boxplotchart example");
397 400 else
398 401 m_chart->setTitle("");
399 402 }
400 403
401 404 void MainWidget::antialiasingToggled(bool enabled)
402 405 {
403 406 qDebug() << "BoxPlotTester::antialiasingToggled toggled to " << enabled;
404 407 m_chartView->setRenderHint(QPainter::Antialiasing, enabled);
405 408 }
406 409
407 410 void MainWidget::boxOutlineToggled(bool visible)
408 411 {
409 412 qDebug() << "BoxPlotTester::boxOutlineToggled toggled to " << visible;
410 413 for (int i = 0; i < m_seriesCount; i++)
411 414 m_series[i]->setBoxOutlineVisible(visible);
412 415 }
413 416
414 417 void MainWidget::modelMapperToggled(bool enabled)
415 418 {
416 419 if (enabled) {
417 420 m_series[m_seriesCount] = new QBoxPlotSeries();
418 421
419 422 int first = 0;
420 423 int count = 5;
421 424 QVBoxPlotModelMapper *mapper = new QVBoxPlotModelMapper(this);
422 425 mapper->setFirstBoxSetColumn(0);
423 426 mapper->setLastBoxSetColumn(5);
424 427 mapper->setFirstRow(first);
425 428 mapper->setRowCount(count);
426 429 mapper->setSeries(m_series[m_seriesCount]);
427 430 mapper->setModel(m_model);
428 431 m_chart->addSeries(m_series[m_seriesCount]);
429 432
430 433 m_seriesCount++;
431 434 } else {
432 435 removeSeries();
433 436 }
434 437 }
435 438
436 439 void MainWidget::changeChartTheme(int themeIndex)
437 440 {
438 441 qDebug() << "BoxPlotTester::changeChartTheme: " << themeIndex;
439 442 if (themeIndex == 0)
440 443 m_chart->setTheme(QChart::ChartThemeLight);
441 444 else
442 445 m_chart->setTheme((QChart::ChartTheme) (themeIndex - 1));
443 446 }
444 447
445 448 void MainWidget::boxClicked(QBoxSet *set)
446 449 {
447 450 qDebug() << "boxClicked, median = " << set->at(QBoxSet::Median);
448 451 }
449 452
450 453 void MainWidget::boxHovered(bool state, QBoxSet *set)
451 454 {
452 455 if (state)
453 456 qDebug() << "box median " << set->at(QBoxSet::Median) << " hover started";
454 457 else
455 458 qDebug() << "box median " << set->at(QBoxSet::Median) << " hover ended";
456 459 }
457 460
458 461 void MainWidget::singleBoxClicked()
459 462 {
460 463 qDebug() << "singleBoxClicked";
461 464 }
462 465
463 466 void MainWidget::singleBoxHovered(bool state)
464 467 {
465 468 if (state)
466 469 qDebug() << "single box hover started";
467 470 else
468 471 qDebug() << "single box hover ended";
469 472 }
470 473
471 474 void MainWidget::changePen()
472 475 {
473 476 qDebug() << "changePen() = " << m_penTool->pen();
474 477 for (int i = 0; i < m_seriesCount; i++)
475 478 m_series[i]->setPen(m_penTool->pen());
476 479 }
477 480
478 481 void MainWidget::setBoxWidth(double width)
479 482 {
480 483 qDebug() << "setBoxWidth to " << width;
481 484
482 485 for (int i = 0; i < m_seriesCount; i++)
483 486 m_series[i]->setBoxWidth(qreal(width));
484 487 }
General Comments 0
You need to be logged in to leave comments. Login now