1 | // Copyright (C) 2016 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses |
5 | |
6 | #include <QtCharts/QBoxPlotSeries> |
7 | #include <private/qboxplotseries_p.h> |
8 | #include <QtCharts/QBoxPlotLegendMarker> |
9 | #include <QtCharts/QBarCategoryAxis> |
10 | #include <private/boxplotchartitem_p.h> |
11 | #include <private/chartdataset_p.h> |
12 | #include <private/charttheme_p.h> |
13 | #include <QtCharts/QValueAxis> |
14 | #include <private/charttheme_p.h> |
15 | #include <private/boxplotanimation_p.h> |
16 | #include <private/qchart_p.h> |
17 | #include <QtCharts/QBoxSet> |
18 | #include <private/qboxset_p.h> |
19 | |
20 | QT_BEGIN_NAMESPACE |
21 | |
22 | /*! |
23 | \class QBoxPlotSeries |
24 | \inmodule QtCharts |
25 | \brief The QBoxPlotSeries class presents data in box-and-whiskers charts. |
26 | |
27 | A box plot series acts as a container for box-and-whiskers items. Items from multiple series |
28 | are grouped into categories according to their index value. |
29 | |
30 | The QBarCategoryAxis class is used to add the categories to the chart's axis. Category labels |
31 | have to be unique. If the same category label is defined for several box-and-whiskers items, |
32 | only the first one is drawn. |
33 | |
34 | See the \l {Charts with Widgets Gallery} to learn how to create a |
35 | box-and-whiskers chart. |
36 | \image examples_boxplotchart.png |
37 | |
38 | \sa QBoxSet, QBarCategoryAxis |
39 | */ |
40 | /*! |
41 | \fn QBoxPlotSeries::boxsetsAdded(const QList<QBoxSet *> &sets) |
42 | This signal is emitted when the list of box-and-whiskers items specified by \a sets |
43 | is added to the series. |
44 | */ |
45 | /*! |
46 | \fn QBoxPlotSeries::boxsetsRemoved(const QList<QBoxSet *> &sets) |
47 | This signal is emitted when the list of box-and-whiskers items specified by \a sets |
48 | is removed from the series. |
49 | */ |
50 | /*! |
51 | \fn QBoxPlotSeries::clicked(QBoxSet *boxset) |
52 | This signal is emitted when the user clicks the box-and-whiskers item specified by |
53 | \a boxset in the chart. |
54 | */ |
55 | /*! |
56 | \fn QBoxPlotSeries::pressed(QBoxSet *boxset) |
57 | This signal is emitted when the user clicks the box-and-whiskers item specified by |
58 | \a boxset in the chart and holds down the mouse button. |
59 | */ |
60 | /*! |
61 | \fn QBoxPlotSeries::released(QBoxSet *boxset) |
62 | This signal is emitted when the user releases the mouse press on the box-and-whiskers |
63 | item specified by \a boxset in the chart. |
64 | */ |
65 | /*! |
66 | \fn QBoxPlotSeries::doubleClicked(QBoxSet *boxset) |
67 | This signal is emitted when the user double-clicks the box-and-whiskers item specified by |
68 | \a boxset in the chart. |
69 | */ |
70 | /*! |
71 | \fn QBoxPlotSeries::hovered(bool status, QBoxSet *boxset) |
72 | This signal is emitted when a mouse is hovered over the box-and-whiskers item specified by |
73 | \a boxset in the chart. When the mouse moves over the item, \a status turns \c true, and |
74 | when the mouse moves away again, it turns \c false. |
75 | */ |
76 | /*! |
77 | \fn QBoxPlotSeries::countChanged() |
78 | This signal is emitted when the number of box-and-whiskers items in the series changes. |
79 | */ |
80 | /*! |
81 | \property QBoxPlotSeries::boxOutlineVisible |
82 | \brief The visibility of the box outline. |
83 | */ |
84 | /*! |
85 | \property QBoxPlotSeries::boxWidth |
86 | \brief The width of the box-and-whiskers item. The value indicates the relative |
87 | width of the item within its category. The value can be between 0.0 and 1.0. Negative values |
88 | are replaced with 0.0 and values greater than 1.0 are replaced with 1.0. |
89 | */ |
90 | /*! |
91 | \property QBoxPlotSeries::pen |
92 | \brief The pen used to draw the lines of the box-and-whiskers items. |
93 | */ |
94 | /*! |
95 | \property QBoxPlotSeries::brush |
96 | \brief The brush used to fill the boxes of the box-and-whiskers items. |
97 | */ |
98 | /*! |
99 | \property QBoxPlotSeries::count |
100 | \brief The number of box-and-whiskers items in a box plot series. |
101 | */ |
102 | |
103 | /*! |
104 | \fn void QBoxPlotSeries::boxOutlineVisibilityChanged() |
105 | This signal is emitted when the box outline visibility changes. |
106 | */ |
107 | |
108 | /*! |
109 | \fn void QBoxPlotSeries::boxWidthChanged() |
110 | This signal is emitted when the width of the box-and-whiskers item changes. |
111 | */ |
112 | /*! |
113 | \fn void QBoxPlotSeries::penChanged() |
114 | This signal is emitted when the pen used to draw the lines of the box-and-whiskers |
115 | items changes. |
116 | */ |
117 | /*! |
118 | \fn void QBoxPlotSeries::brushChanged() |
119 | This signal is emitted when the brush used to fill the boxes of the box-and-whiskers |
120 | items changes. |
121 | */ |
122 | /*! |
123 | \fn virtual SeriesType QBoxPlotSeries::type() const |
124 | Returns the type of the series. |
125 | \sa QAbstractSeries, SeriesType |
126 | */ |
127 | |
128 | /*! |
129 | Constructs an empty box plot series that is a QObject and a child of \a parent. |
130 | */ |
131 | QBoxPlotSeries::QBoxPlotSeries(QObject *parent) |
132 | : QAbstractSeries(*new QBoxPlotSeriesPrivate(this), parent) |
133 | { |
134 | } |
135 | |
136 | /*! |
137 | Removes the series from the chart. |
138 | */ |
139 | QBoxPlotSeries::~QBoxPlotSeries() |
140 | { |
141 | Q_D(QBoxPlotSeries); |
142 | if (d->m_chart) |
143 | d->m_chart->removeSeries(series: this); |
144 | } |
145 | |
146 | /*! |
147 | Adds a single box-and-whiskers item specified by \a set to the series and takes ownership of |
148 | it. If the item is null or it already belongs to the series, it will not be appended. |
149 | Returns \c true if appending succeeded. |
150 | */ |
151 | bool QBoxPlotSeries::append(QBoxSet *set) |
152 | { |
153 | Q_D(QBoxPlotSeries); |
154 | |
155 | bool success = d->append(set); |
156 | if (success) { |
157 | QList<QBoxSet *> sets; |
158 | sets.append(t: set); |
159 | set->setParent(this); |
160 | emit boxsetsAdded(sets); |
161 | emit countChanged(); |
162 | } |
163 | return success; |
164 | } |
165 | |
166 | /*! |
167 | Removes the box-and-whiskers item specified by \a set from the series and permanently |
168 | deletes it if the removal succeeds. Returns \c true if the item was removed. |
169 | */ |
170 | bool QBoxPlotSeries::remove(QBoxSet *set) |
171 | { |
172 | Q_D(QBoxPlotSeries); |
173 | bool success = d->remove(set); |
174 | if (success) { |
175 | QList<QBoxSet *> sets; |
176 | sets.append(t: set); |
177 | set->setParent(0); |
178 | emit boxsetsRemoved(sets); |
179 | emit countChanged(); |
180 | delete set; |
181 | set = 0; |
182 | } |
183 | return success; |
184 | } |
185 | |
186 | /*! |
187 | Takes the box-and-whiskers item specified by \a set from the series. Does not delete the |
188 | item. |
189 | |
190 | \note The series remains the item's parent object. You must set the parent object to take |
191 | full ownership. |
192 | |
193 | Returns \c true if the take operation succeeds. |
194 | |
195 | */ |
196 | bool QBoxPlotSeries::take(QBoxSet *set) |
197 | { |
198 | Q_D(QBoxPlotSeries); |
199 | |
200 | bool success = d->remove(set); |
201 | if (success) { |
202 | QList<QBoxSet *> sets; |
203 | sets.append(t: set); |
204 | emit boxsetsRemoved(sets); |
205 | emit countChanged(); |
206 | } |
207 | return success; |
208 | } |
209 | |
210 | /*! |
211 | Adds a list of box-and-whiskers items specified by \a sets to the series and takes ownership of |
212 | them. If the list is null or the items already belong to the series, it will not be appended. |
213 | Returns \c true if appending succeeded. |
214 | */ |
215 | bool QBoxPlotSeries::append(const QList<QBoxSet *> &sets) |
216 | { |
217 | Q_D(QBoxPlotSeries); |
218 | bool success = d->append(sets); |
219 | if (success) { |
220 | emit boxsetsAdded(sets); |
221 | emit countChanged(); |
222 | } |
223 | return success; |
224 | } |
225 | |
226 | /*! |
227 | Inserts a box-and-whiskers item specified by \a set to a series at the position specified by |
228 | \a index and takes ownership of the item. If the item is null or already belongs to the series, |
229 | it will not be appended. Returns \c true if inserting succeeds. |
230 | */ |
231 | bool QBoxPlotSeries::insert(int index, QBoxSet *set) |
232 | { |
233 | Q_D(QBoxPlotSeries); |
234 | bool success = d->insert(index, set); |
235 | if (success) { |
236 | QList<QBoxSet *> sets; |
237 | sets.append(t: set); |
238 | emit boxsetsAdded(sets); |
239 | emit countChanged(); |
240 | } |
241 | return success; |
242 | } |
243 | |
244 | /*! |
245 | Removes all box-and-whiskers items from the series and permanently deletes them. |
246 | */ |
247 | void QBoxPlotSeries::clear() |
248 | { |
249 | Q_D(QBoxPlotSeries); |
250 | QList<QBoxSet *> sets = boxSets(); |
251 | bool success = d->remove(sets); |
252 | if (success) { |
253 | emit boxsetsRemoved(sets); |
254 | emit countChanged(); |
255 | foreach (QBoxSet *set, sets) |
256 | delete set; |
257 | } |
258 | } |
259 | |
260 | /*! |
261 | Returns the number of box-and-whiskers items in a box plot series. |
262 | */ |
263 | int QBoxPlotSeries::count() const |
264 | { |
265 | Q_D(const QBoxPlotSeries); |
266 | return d->m_boxSets.size(); |
267 | } |
268 | |
269 | /*! |
270 | Returns a list of box-and-whiskers items in a box plot series. Keeps the ownership of the items. |
271 | */ |
272 | QList<QBoxSet *> QBoxPlotSeries::boxSets() const |
273 | { |
274 | Q_D(const QBoxPlotSeries); |
275 | return d->m_boxSets; |
276 | } |
277 | |
278 | /* |
279 | Returns QAbstractSeries::SeriesTypeBoxPlot. |
280 | */ |
281 | QAbstractSeries::SeriesType QBoxPlotSeries::type() const |
282 | { |
283 | return QAbstractSeries::SeriesTypeBoxPlot; |
284 | } |
285 | |
286 | void QBoxPlotSeries::setBoxOutlineVisible(bool visible) |
287 | { |
288 | Q_D(QBoxPlotSeries); |
289 | |
290 | if (d->m_boxOutlineVisible != visible) { |
291 | d->m_boxOutlineVisible = visible; |
292 | emit d->updated(); |
293 | emit boxOutlineVisibilityChanged(); |
294 | } |
295 | } |
296 | |
297 | bool QBoxPlotSeries::boxOutlineVisible() |
298 | { |
299 | Q_D(QBoxPlotSeries); |
300 | |
301 | return d->m_boxOutlineVisible; |
302 | } |
303 | |
304 | void QBoxPlotSeries::setBoxWidth(qreal width) |
305 | { |
306 | Q_D(QBoxPlotSeries); |
307 | |
308 | if (width != d->m_boxWidth) { |
309 | if (width < 0.0) |
310 | width = 0.0; |
311 | if (width > 1.0) |
312 | width = 1.0; |
313 | d->m_boxWidth = width; |
314 | emit d->updatedLayout(); |
315 | emit boxWidthChanged(); |
316 | } |
317 | } |
318 | |
319 | qreal QBoxPlotSeries::boxWidth() |
320 | { |
321 | Q_D(QBoxPlotSeries); |
322 | |
323 | return d->m_boxWidth; |
324 | } |
325 | |
326 | void QBoxPlotSeries::setBrush(const QBrush &brush) |
327 | { |
328 | Q_D(QBoxPlotSeries); |
329 | |
330 | if (d->m_brush != brush) { |
331 | d->m_brush = brush; |
332 | emit d->updated(); |
333 | emit brushChanged(); |
334 | } |
335 | } |
336 | |
337 | QBrush QBoxPlotSeries::brush() const |
338 | { |
339 | Q_D(const QBoxPlotSeries); |
340 | |
341 | return d->m_brush; |
342 | } |
343 | |
344 | void QBoxPlotSeries::setPen(const QPen &pen) |
345 | { |
346 | Q_D(QBoxPlotSeries); |
347 | |
348 | if (d->m_pen != pen) { |
349 | d->m_pen = pen; |
350 | emit d->updated(); |
351 | emit penChanged(); |
352 | } |
353 | } |
354 | |
355 | QPen QBoxPlotSeries::pen() const |
356 | { |
357 | Q_D(const QBoxPlotSeries); |
358 | |
359 | return d->m_pen; |
360 | } |
361 | |
362 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
363 | |
364 | QBoxPlotSeriesPrivate::QBoxPlotSeriesPrivate(QBoxPlotSeries *q) |
365 | : QAbstractSeriesPrivate(q), |
366 | m_pen(QChartPrivate::defaultPen()), |
367 | m_brush(QChartPrivate::defaultBrush()), |
368 | m_boxOutlineVisible(true), |
369 | m_boxWidth(0.5) |
370 | { |
371 | } |
372 | |
373 | QBoxPlotSeriesPrivate::~QBoxPlotSeriesPrivate() |
374 | { |
375 | disconnect(sender: this, signal: 0, receiver: 0, member: 0); |
376 | } |
377 | |
378 | void QBoxPlotSeriesPrivate::initializeDomain() |
379 | { |
380 | qreal minX(domain()->minX()); |
381 | qreal minY(domain()->minY()); |
382 | qreal maxX(domain()->maxX()); |
383 | qreal maxY(domain()->maxY()); |
384 | |
385 | qreal x = m_boxSets.size(); |
386 | minX = qMin(a: minX, b: qreal(-0.5)); |
387 | minY = qMin(a: minY, b: min()); |
388 | maxX = qMax(a: maxX, b: x - qreal(0.5)); |
389 | maxY = qMax(a: maxY, b: max()); |
390 | |
391 | domain()->setRange(minX, maxX, minY, maxY); |
392 | } |
393 | |
394 | void QBoxPlotSeriesPrivate::initializeAxes() |
395 | { |
396 | foreach (QAbstractAxis* axis, m_axes) { |
397 | if (axis->type() == QAbstractAxis::AxisTypeBarCategory) { |
398 | if (axis->orientation() == Qt::Horizontal) |
399 | populateCategories(axis: qobject_cast<QBarCategoryAxis *>(object: axis)); |
400 | } |
401 | } |
402 | } |
403 | |
404 | QAbstractAxis::AxisType QBoxPlotSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const |
405 | { |
406 | if (orientation == Qt::Horizontal) |
407 | return QAbstractAxis::AxisTypeBarCategory; |
408 | |
409 | return QAbstractAxis::AxisTypeValue; |
410 | } |
411 | |
412 | QAbstractAxis* QBoxPlotSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const |
413 | { |
414 | if (defaultAxisType(orientation) == QAbstractAxis::AxisTypeBarCategory) |
415 | return new QBarCategoryAxis; |
416 | else |
417 | return new QValueAxis; |
418 | } |
419 | |
420 | void QBoxPlotSeriesPrivate::populateCategories(QBarCategoryAxis *axis) |
421 | { |
422 | QStringList categories; |
423 | if (axis->categories().isEmpty()) { |
424 | for (int i(1); i < m_boxSets.size() + 1; i++) { |
425 | QBoxSet *set = m_boxSets.at(i: i - 1); |
426 | if (set->label().isEmpty()) |
427 | categories << presenter()->numberToString(value: i); |
428 | else |
429 | categories << set->label(); |
430 | } |
431 | axis->append(categories); |
432 | } |
433 | } |
434 | |
435 | void QBoxPlotSeriesPrivate::initializeGraphics(QGraphicsItem *parent) |
436 | { |
437 | Q_Q(QBoxPlotSeries); |
438 | |
439 | BoxPlotChartItem *boxPlot = new BoxPlotChartItem(q, parent); |
440 | m_item.reset(p: boxPlot); |
441 | QAbstractSeriesPrivate::initializeGraphics(parent); |
442 | |
443 | if (m_chart) { |
444 | connect(sender: m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), receiver: this, SLOT(handleSeriesChange(QAbstractSeries*))); |
445 | connect(sender: m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), receiver: this, SLOT(handleSeriesRemove(QAbstractSeries*))); |
446 | |
447 | QList<QAbstractSeries *> serieses = m_chart->series(); |
448 | |
449 | // Tries to find this series from the Chart's list of series and deduce the index |
450 | int index = 0; |
451 | foreach (QAbstractSeries *s, serieses) { |
452 | if (s->type() == QAbstractSeries::SeriesTypeBoxPlot) { |
453 | if (q == static_cast<QBoxPlotSeries *>(s)) { |
454 | boxPlot->m_seriesIndex = index; |
455 | m_index = index; |
456 | } |
457 | index++; |
458 | } |
459 | } |
460 | boxPlot->m_seriesCount = index; |
461 | } |
462 | |
463 | // Make BoxPlotChartItem to instantiate box & whisker items |
464 | boxPlot->handleDataStructureChanged(); |
465 | } |
466 | |
467 | void QBoxPlotSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced) |
468 | { |
469 | Q_Q(QBoxPlotSeries); |
470 | |
471 | const QList<QGradient> gradients = theme->seriesGradients(); |
472 | |
473 | if (forced || QChartPrivate::defaultBrush() == m_brush) { |
474 | QColor brushColor = ChartThemeManager::colorAt(gradient: gradients.at(i: index % gradients.size()), pos: 0.5); |
475 | q->setBrush(brushColor); |
476 | } |
477 | |
478 | if (forced || QChartPrivate::defaultPen() == m_pen) { |
479 | QPen pen = theme->outlinePen(); |
480 | pen.setCosmetic(true); |
481 | q->setPen(pen); |
482 | } |
483 | } |
484 | |
485 | void QBoxPlotSeriesPrivate::initializeAnimations(QChart::AnimationOptions options, int duration, |
486 | QEasingCurve &curve) |
487 | { |
488 | BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.get()); |
489 | Q_ASSERT(item); |
490 | if (item->animation()) |
491 | item->animation()->stopAndDestroyLater(); |
492 | |
493 | if (options.testFlag(flag: QChart::SeriesAnimations)) |
494 | m_animation = new BoxPlotAnimation(item, duration, curve); |
495 | else |
496 | m_animation = 0; |
497 | item->setAnimation(m_animation); |
498 | |
499 | QAbstractSeriesPrivate::initializeAnimations(options, duration, curve); |
500 | |
501 | // Make BoxPlotChartItem to instantiate box & whisker items |
502 | item->handleDataStructureChanged(); |
503 | } |
504 | |
505 | QList<QLegendMarker*> QBoxPlotSeriesPrivate::createLegendMarkers(QLegend *legend) |
506 | { |
507 | Q_Q(QBoxPlotSeries); |
508 | QList<QLegendMarker *> list; |
509 | return list << new QBoxPlotLegendMarker(q, legend); |
510 | } |
511 | |
512 | void QBoxPlotSeriesPrivate::handleSeriesRemove(QAbstractSeries *series) |
513 | { |
514 | Q_Q(QBoxPlotSeries); |
515 | |
516 | QBoxPlotSeries *removedSeries = static_cast<QBoxPlotSeries *>(series); |
517 | |
518 | if (q == removedSeries) { |
519 | if (m_animation) |
520 | m_animation->stopAll(); |
521 | QObject::disconnect(sender: m_chart->d_ptr->m_dataset, signal: 0, receiver: this, member: 0); |
522 | } |
523 | |
524 | // Test if series removed is me, then don't do anything |
525 | if (q != removedSeries) { |
526 | BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.get()); |
527 | if (item) { |
528 | item->m_seriesCount = item->m_seriesCount - 1; |
529 | if (removedSeries->d_func()->m_index < m_index) { |
530 | m_index--; |
531 | item->m_seriesIndex = m_index; |
532 | } |
533 | |
534 | item->handleDataStructureChanged(); |
535 | } |
536 | } |
537 | } |
538 | |
539 | void QBoxPlotSeriesPrivate::handleSeriesChange(QAbstractSeries *series) |
540 | { |
541 | Q_UNUSED(series); |
542 | |
543 | Q_Q(QBoxPlotSeries); |
544 | |
545 | BoxPlotChartItem *boxPlot = static_cast<BoxPlotChartItem *>(m_item.get()); |
546 | |
547 | if (m_chart) { |
548 | QList<QAbstractSeries *> serieses = m_chart->series(); |
549 | |
550 | // Tries to find this series from the Chart's list of series and deduce the index |
551 | int index = 0; |
552 | foreach (QAbstractSeries *s, serieses) { |
553 | if (s->type() == QAbstractSeries::SeriesTypeBoxPlot) { |
554 | if (q == static_cast<QBoxPlotSeries *>(s)) { |
555 | boxPlot->m_seriesIndex = index; |
556 | m_index = index; |
557 | } |
558 | index++; |
559 | } |
560 | } |
561 | boxPlot->m_seriesCount = index; |
562 | } |
563 | |
564 | boxPlot->handleDataStructureChanged(); |
565 | } |
566 | |
567 | bool QBoxPlotSeriesPrivate::append(QBoxSet *set) |
568 | { |
569 | if (m_boxSets.contains(t: set) || (set == 0) || set->d_ptr->m_series) |
570 | return false; // Fail if set is already in list or set is null. |
571 | |
572 | m_boxSets.append(t: set); |
573 | QObject::connect(sender: set->d_ptr.data(), SIGNAL(updatedLayout()), receiver: this, SIGNAL(updatedLayout())); |
574 | QObject::connect(sender: set->d_ptr.data(), SIGNAL(updatedBox()), receiver: this, SIGNAL(updatedBoxes())); |
575 | QObject::connect(sender: set->d_ptr.data(), SIGNAL(restructuredBox()), receiver: this, SIGNAL(restructuredBoxes())); |
576 | set->d_ptr->m_series = this; |
577 | |
578 | emit restructuredBoxes(); // this notifies boxplotchartitem |
579 | return true; |
580 | } |
581 | |
582 | bool QBoxPlotSeriesPrivate::remove(QBoxSet *set) |
583 | { |
584 | if (!m_boxSets.contains(t: set)) |
585 | return false; // Fail if set is not in list |
586 | |
587 | set->d_ptr->m_series = 0; |
588 | m_boxSets.removeOne(t: set); |
589 | QObject::disconnect(sender: set->d_ptr.data(), SIGNAL(updatedLayout()), receiver: this, SIGNAL(updatedLayout())); |
590 | QObject::disconnect(sender: set->d_ptr.data(), SIGNAL(updatedBox()), receiver: this, SIGNAL(updatedBoxes())); |
591 | QObject::disconnect(sender: set->d_ptr.data(), SIGNAL(restructuredBox()), receiver: this, SIGNAL(restructuredBoxes())); |
592 | |
593 | emit restructuredBoxes(); // this notifies boxplotchartitem |
594 | return true; |
595 | } |
596 | |
597 | bool QBoxPlotSeriesPrivate::append(const QList<QBoxSet *> &sets) |
598 | { |
599 | for (auto *set : sets) { |
600 | if ((set == 0) || m_boxSets.contains(t: set) || set->d_ptr->m_series) |
601 | return false; // Fail if any of the sets is null or is already appended. |
602 | if (sets.count(t: set) != 1) |
603 | return false; // Also fail if same set is more than once in given list. |
604 | } |
605 | |
606 | for (auto *set : sets) { |
607 | m_boxSets.append(t: set); |
608 | QObject::connect(sender: set->d_ptr.data(), SIGNAL(updatedLayout()), receiver: this, SIGNAL(updatedLayout())); |
609 | QObject::connect(sender: set->d_ptr.data(), SIGNAL(updatedBox()), receiver: this, SIGNAL(updatedBoxes())); |
610 | QObject::connect(sender: set->d_ptr.data(), SIGNAL(restructuredBox()), receiver: this, SIGNAL(restructuredBoxes())); |
611 | set->d_ptr->m_series = this; |
612 | } |
613 | |
614 | emit restructuredBoxes(); // this notifies boxplotchartitem |
615 | return true; |
616 | } |
617 | |
618 | bool QBoxPlotSeriesPrivate::remove(const QList<QBoxSet *> &sets) |
619 | { |
620 | if (sets.size() == 0) |
621 | return false; |
622 | |
623 | for (auto *set : sets) { |
624 | if ((set == 0) || (!m_boxSets.contains(t: set))) |
625 | return false; // Fail if any of the sets is null or is not in series |
626 | if (sets.count(t: set) != 1) |
627 | return false; // Also fail if same set is more than once in given list. |
628 | } |
629 | |
630 | for (auto *set : sets) { |
631 | set->d_ptr->m_series = 0; |
632 | m_boxSets.removeOne(t: set); |
633 | QObject::disconnect(sender: set->d_ptr.data(), SIGNAL(updatedLayout()), receiver: this, SIGNAL(updatedLayout())); |
634 | QObject::disconnect(sender: set->d_ptr.data(), SIGNAL(updatedBox()), receiver: this, SIGNAL(updatedBoxes())); |
635 | QObject::disconnect(sender: set->d_ptr.data(), SIGNAL(restructuredBox()), receiver: this, SIGNAL(restructuredBoxes())); |
636 | } |
637 | |
638 | emit restructuredBoxes(); // this notifies boxplotchartitem |
639 | |
640 | return true; |
641 | } |
642 | |
643 | bool QBoxPlotSeriesPrivate::insert(int index, QBoxSet *set) |
644 | { |
645 | if ((m_boxSets.contains(t: set)) || (set == 0) || set->d_ptr->m_series) |
646 | return false; // Fail if set is already in list or set is null. |
647 | |
648 | m_boxSets.insert(i: index, t: set); |
649 | set->d_ptr->m_series = this; |
650 | QObject::connect(sender: set->d_ptr.data(), SIGNAL(updatedLayout()), receiver: this, SIGNAL(updatedLayout())); |
651 | QObject::connect(sender: set->d_ptr.data(), SIGNAL(updatedBox()), receiver: this, SIGNAL(updatedBoxes())); |
652 | QObject::connect(sender: set->d_ptr.data(), SIGNAL(restructuredBox()), receiver: this, SIGNAL(restructuredBoxes())); |
653 | |
654 | emit restructuredBoxes(); // this notifies boxplotchartitem |
655 | return true; |
656 | } |
657 | |
658 | QBoxSet *QBoxPlotSeriesPrivate::boxSetAt(int index) |
659 | { |
660 | return m_boxSets.at(i: index); |
661 | } |
662 | |
663 | qreal QBoxPlotSeriesPrivate::min() |
664 | { |
665 | if (m_boxSets.size() <= 0) |
666 | return 0; |
667 | |
668 | qreal min = m_boxSets.at(i: 0)->at(index: 0); |
669 | |
670 | foreach (QBoxSet *set, m_boxSets) { |
671 | for (int i = 0; i < 5; i++) { |
672 | if (set->at(index: i) < min) |
673 | min = set->at(index: i); |
674 | } |
675 | } |
676 | |
677 | return min; |
678 | } |
679 | |
680 | qreal QBoxPlotSeriesPrivate::max() |
681 | { |
682 | if (m_boxSets.size() <= 0) |
683 | return 0; |
684 | |
685 | qreal max = m_boxSets.at(i: 0)->at(index: 0); |
686 | |
687 | foreach (QBoxSet *set, m_boxSets) { |
688 | for (int i = 0; i < 5; i++) { |
689 | if (set->at(index: i) > max) |
690 | max = set->at(index: i); |
691 | } |
692 | } |
693 | |
694 | return max; |
695 | } |
696 | |
697 | QT_END_NAMESPACE |
698 | |
699 | #include "moc_qboxplotseries.cpp" |
700 | #include "moc_qboxplotseries_p.cpp" |
701 |
Definitions
- QBoxPlotSeries
- ~QBoxPlotSeries
- append
- remove
- take
- append
- insert
- clear
- count
- boxSets
- type
- setBoxOutlineVisible
- boxOutlineVisible
- setBoxWidth
- boxWidth
- setBrush
- brush
- setPen
- pen
- QBoxPlotSeriesPrivate
- ~QBoxPlotSeriesPrivate
- initializeDomain
- initializeAxes
- defaultAxisType
- createDefaultAxis
- populateCategories
- initializeGraphics
- initializeTheme
- initializeAnimations
- createLegendMarkers
- handleSeriesRemove
- handleSeriesChange
- append
- remove
- append
- remove
- insert
- boxSetAt
- min
Start learning QML with our Intro Training
Find out more