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 "declarativebarseries_p.h"
7#include "declarativeboxplotseries_p.h"
8#include <QtCharts/QBoxSet>
9#include <QtCharts/QHBoxPlotModelMapper>
10#include <QtCharts/QVBoxPlotModelMapper>
11
12QT_BEGIN_NAMESPACE
13
14/*!
15 \qmltype BoxSet
16 \nativetype QBoxSet
17 \inqmlmodule QtCharts
18
19 \brief Represents one item in a box-and-whiskers chart.
20
21 A box-and-whiskers item is a graphical representation of a range and three median values
22 that is constructed from five different values. There are two ways to specify the values.
23 The first one is by using a constructor or the append() method. The values have to be
24 specified in the following order: lower extreme, lower quartile, median, upper quartile,
25 and upper extreme.
26
27 The second way is to create an empty BoxSet instance and specify the values using the
28 setValue() method.
29
30 \sa BoxPlotSeries
31*/
32
33/*!
34 \qmlproperty list BoxSet::values
35 The values of the box-and-whiskers item. The following enumerations can be
36 used as indexes when accessing the list of values:
37
38 \value BoxSet.LowerExtreme The smallest value of the box-and-whiskers item.
39 \value BoxSet.LowerQuartile The median value of the lower half of the box-and-whiskers item.
40 \value BoxSet.Median The median value of the box-and-whiskers item.
41 \value BoxSet.UpperQuartile The median value of the upper half of the box-and-whiskers item.
42 \value BoxSet.UpperExtreme The largest value of the box-and-whiskers item.
43
44 \sa at(), setValue()
45*/
46/*!
47 \qmlproperty string BoxSet::label
48 The label of the category of the box-and-whiskers item.
49*/
50/*!
51 \qmlproperty int BoxSet::count
52 The number of values of the box-and-whiskers item.
53*/
54
55/*!
56 \qmlproperty string BoxSet::brushFilename
57 The name of the file used as a brush for the box-and-whiskers item.
58*/
59
60/*!
61 \qmlmethod void BoxSet::at(int index)
62 Returns the value in the position specified by \a index.
63*/
64/*!
65 \qmlmethod void BoxSet::append(qreal value)
66 Appends the new value specified by \a value to the end of the box-and-whiskers item.
67*/
68/*!
69 \qmlmethod void BoxSet::clear()
70 Sets all the values of the box-and-whiskers item to 0.
71*/
72/*!
73 \qmlmethod void BoxSet::setValue(int index, qreal value)
74 Sets the value specified by \a value in the position specified by \a index.
75*/
76/*!
77 \qmlsignal BoxSet::clicked()
78 This signal is emitted when the user clicks a box-and-whiskers item in the chart.
79
80 The corresponding signal handler is \c onClicked().
81*/
82/*!
83 \qmlsignal BoxSet::pressed()
84 This signal is emitted when the user clicks a box-and-whiskers item in the chart
85 and holds down the mouse button.
86
87 The corresponding signal handler is \c onPressed.
88*/
89/*!
90 \qmlsignal BoxSet::released()
91 This signal is emitted when the user releases the mouse press on a box-and-whiskers item.
92
93 The corresponding signal handler is \c onReleased().
94*/
95/*!
96 \qmlsignal BoxSet::doubleClicked()
97 This signal is emitted when the user double-clicks a box-and-whiskers item.
98
99 The corresponding signal handler is \c onDoubleClicked().
100*/
101/*!
102 \qmlsignal BoxSet::hovered(bool status)
103 This signal is emitted when a mouse is hovered over a box-and-whiskers item in a chart.
104 When the mouse moves over the item, \a status turns \c true, and when the mouse moves
105 away again, it turns \c false.
106
107 The corresponding signal handler is \c onHovered().
108*/
109/*!
110 \qmlsignal BoxSet::valuesChanged()
111 This signal is emitted when multiple values of the box-and-whiskers item change.
112
113 The corresponding signal handler is \c onValuesChanged().
114*/
115/*!
116 \qmlsignal BoxSet::valueChanged(int index)
117 This signal is emitted when the value of the box-and-whiskers item specified by \a index
118 changes.
119
120 The corresponding signal handler is \c onValueChanged().
121*/
122/*!
123 \qmlsignal BoxSet::cleared()
124 This signal is emitted when all the values of the box-and-whiskers item are set to 0.
125
126 The corresponding signal handler is \c onCleared().
127*/
128
129/*!
130 \qmltype BoxPlotSeries
131 \nativetype QBoxPlotSeries
132 \inqmlmodule QtCharts
133
134 \inherits AbstractSeries
135
136 \brief Presents data in box-and-whiskers charts.
137
138 A box plot series acts as a container for box-and-whiskers items. Items from multiple series
139 are grouped into categories according to their index value.
140
141 The BarCategoryAxis class is used to add the categories to the chart's axis. Category labels
142 have to be unique. If the same category label is defined for several box-and-whiskers items,
143 only the first one is drawn.
144
145 The following QML code snippet shows how to create a simple box-and-whiskers chart:
146 \code
147 import QtQuick 2.0
148 import QtCharts 2.0
149
150 ChartView {
151 title: "Box Plot series"
152 width: 400
153 height: 300
154 theme: ChartView.ChartThemeBrownSand
155 legend.alignment: Qt.AlignBottom
156
157 BoxPlotSeries {
158 id: plotSeries
159 name: "Income"
160 BoxSet { label: "Jan"; values: [3, 4, 5.1, 6.2, 8.5] }
161 BoxSet { label: "Feb"; values: [5, 6, 7.5, 8.6, 11.8] }
162 BoxSet { label: "Mar"; values: [3.2, 5, 5.7, 8, 9.2] }
163 BoxSet { label: "Apr"; values: [3.8, 5, 6.4, 7, 8] }
164 BoxSet { label: "May"; values: [4, 5, 5.2, 6, 7] }
165 }
166 }
167 \endcode
168
169 \beginfloatleft
170 \image examples_qmlboxplot.png
171 \endfloat
172 \clearfloat
173
174 \sa BoxSet, BarCategoryAxis
175*/
176
177/*!
178 \qmlmethod BoxPlotSeries::at(int index)
179 Returns the box-and-whiskers item in the position specified by \a index.
180*/
181
182/*!
183 \qmlmethod BoxPlotSeries::append(string label, VariantList values)
184 Appends a new box-and-whiskers item with the label specified by \a label and the values
185 specified by \a values to the series.
186 */
187/*!
188 \qmlmethod BoxPlotSeries::append(BoxSet box)
189 Appends the box-and-whiskers item specified by \a box to the series.
190*/
191/*!
192 \qmlmethod BoxPlotSeries::insert(int index, string label, VariantList values)
193 Inserts a new box-and-whiskers item with the label specified by \a label and the values
194 specified by \a values to the series at the position specified by \a index.
195*/
196/*!
197 \qmlmethod BoxPlotSeries::remove(QBoxSet boxset)
198 Removes the box-and-whiskers item specified by \a boxset from the series.
199*/
200/*!
201 \qmlmethod BoxPlotSeries::clear()
202 Removes all box-and-whiskers items from the series and permanently deletes them.
203*/
204/*!
205 \qmlsignal BoxPlotSeries::clicked(BoxSet boxset);
206 This signal is emitted when the user clicks the box-and-whiskers item specified by
207 \a boxset in the chart.
208
209 The corresponding signal handler is \c onClicked().
210*/
211/*!
212 \qmlsignal BoxPlotSeries::hovered(bool status, BoxSet boxset);
213 This signal is emitted when a mouse is hovered over the box-and-whiskers item specified by
214 \a boxset in the chart. When the mouse moves over the item, \a status turns \c true, and
215 when the mouse moves away again, it turns \c false.
216
217 The corresponding signal handler is \c onHovered().
218*/
219/*!
220 \qmlsignal BoxPlotSeries::pressed(BoxSet boxset)
221 This signal is emitted when the user presses the \a boxset on the chart.
222
223 The corresponding signal handler is \c onPressed.
224*/
225/*!
226 \qmlsignal BoxPlotSeries::released(BoxSet boxset)
227 This signal is emitted when the user releases the mouse press on the box-and-whiskers
228 item specified by \a boxset in the chart.
229
230 The corresponding signal handler is \c onReleased().
231*/
232/*!
233 \qmlsignal BoxPlotSeries::doubleClicked(BoxSet boxset)
234 This signal is emitted when the user double-clicks the box-and-whiskers item specified by
235 \a boxset in the chart.
236
237 The corresponding signal handler is \c onDoubleClicked().
238*/
239/*!
240 \qmlsignal BoxPlotSeries::boxsetsAdded(list sets)
241 This signal is emitted when the box-and-whiskers items specified by \a sets
242 are added to the series.
243
244 The corresponding signal handler is \c onBoxsetsAdded().
245*/
246/*!
247 \qmlsignal BoxPlotSeries::boxsetsRemoved(list sets)
248 This signal is emitted when the box-and-whiskers items specified by \a sets
249 are removed from the series.
250
251 The corresponding signal handler is \c onBoxsetsRemoved().
252 */
253/*!
254 \qmlproperty AbstractAxis BoxPlotSeries::axisX
255 The x-axis used for the series. If you leave both axisX and axisXTop undefined, a
256 BarCategoryAxis is created for the series.
257 \sa axisXTop
258*/
259/*!
260 \qmlproperty AbstractAxis BoxPlotSeries::axisY
261 The y-axis used for the series. If you leave both axisY and axisYRight undefined, a
262 ValueAxis is created for the series.
263 \sa axisYRight
264*/
265/*!
266 \qmlproperty AbstractAxis BoxPlotSeries::axisXTop
267 The x-axis used for the series, drawn on top of the chart view.
268
269 \note You can only provide either axisX or axisXTop, but not both.
270 \sa axisX
271
272 \sa axisX
273*/
274/*!
275 \qmlproperty AbstractAxis BoxPlotSeries::axisYRight
276 The y-axis used for the series, drawn to the right on the chart view.
277
278 \note You can only provide either axisY or axisYRight, but not both.
279 \sa axisY
280*/
281/*!
282 \qmlproperty bool BoxPlotSeries::boxOutlineVisible
283 The visibility of the box outline.
284*/
285/*!
286 \qmlproperty real BoxPlotSeries::boxWidth
287 \brief The width of the box-and-whiskers item. The value indicates the relative
288 width of the item within its category. The value can be between 0.0 and 1.0. Negative values
289 are replaced with 0.0 and values greater than 1.0 are replaced with 1.0.
290*/
291
292/*!
293 \qmlproperty string BoxPlotSeries::brushFilename
294 The name of the file used as a brush for the series.
295*/
296
297/*!
298 \qmlproperty int BoxPlotSeries::count
299 The number of box-and-whiskers items in a box plot series.
300*/
301
302
303DeclarativeBoxSet::DeclarativeBoxSet(const QString label, QObject *parent)
304 : QBoxSet(label, parent)
305{
306 connect(sender: this, SIGNAL(valuesChanged()), receiver: this, SIGNAL(changedValues()));
307 connect(sender: this, SIGNAL(valueChanged(int)), receiver: this, SIGNAL(changedValue(int)));
308 connect(sender: this, SIGNAL(brushChanged()), receiver: this, SLOT(handleBrushChanged()));
309}
310
311QVariantList DeclarativeBoxSet::values()
312{
313 QVariantList values;
314 for (int i(0); i < 5; i++)
315 values.append(t: QVariant(QBoxSet::at(index: i)));
316 return values;
317}
318
319void DeclarativeBoxSet::setValues(QVariantList values)
320{
321 for (int i(0); i < values.size(); i++) {
322 if (values.at(i).canConvert<double>())
323 QBoxSet::append(value: values[i].toDouble());
324 }
325}
326
327QString DeclarativeBoxSet::brushFilename() const
328{
329 return m_brushFilename;
330}
331
332void DeclarativeBoxSet::setBrushFilename(const QString &brushFilename)
333{
334 QImage brushImage(brushFilename);
335 if (QBoxSet::brush().textureImage() != brushImage) {
336 QBrush brush = QBoxSet::brush();
337 brush.setTextureImage(brushImage);
338 QBoxSet::setBrush(brush);
339 m_brushFilename = brushFilename;
340 m_brushImage = brushImage;
341 emit brushFilenameChanged(brushFilename);
342 }
343}
344
345void DeclarativeBoxSet::handleBrushChanged()
346{
347 // If the texture image of the brush has changed along the brush
348 // the brush file name needs to be cleared.
349 if (!m_brushFilename.isEmpty() && QBoxSet::brush().textureImage() != m_brushImage) {
350 m_brushFilename.clear();
351 emit brushFilenameChanged(brushFilename: QString());
352 }
353}
354
355// =====================================================
356
357DeclarativeBoxPlotSeries::DeclarativeBoxPlotSeries(QQuickItem *parent) :
358 QBoxPlotSeries(parent),
359 m_axes(new DeclarativeAxes(this))
360{
361 connect(sender: m_axes, SIGNAL(axisXChanged(QAbstractAxis*)), receiver: this, SIGNAL(axisXChanged(QAbstractAxis*)));
362 connect(sender: m_axes, SIGNAL(axisYChanged(QAbstractAxis*)), receiver: this, SIGNAL(axisYChanged(QAbstractAxis*)));
363 connect(sender: m_axes, SIGNAL(axisXTopChanged(QAbstractAxis*)), receiver: this, SIGNAL(axisXTopChanged(QAbstractAxis*)));
364 connect(sender: m_axes, SIGNAL(axisYRightChanged(QAbstractAxis*)), receiver: this, SIGNAL(axisYRightChanged(QAbstractAxis*)));
365 connect(sender: this, SIGNAL(hovered(bool, QBoxSet*)), receiver: this, SLOT(onHovered(bool, QBoxSet*)));
366 connect(sender: this, SIGNAL(clicked(QBoxSet*)), receiver: this, SLOT(onClicked(QBoxSet*)));
367 connect(sender: this, SIGNAL(brushChanged()), receiver: this, SLOT(handleBrushChanged()));
368 connect(sender: this, SIGNAL(pressed(QBoxSet*)), receiver: this, SLOT(onPressed(QBoxSet*)));
369 connect(sender: this, SIGNAL(released(QBoxSet*)), receiver: this, SLOT(onReleased(QBoxSet*)));
370 connect(sender: this, SIGNAL(doubleClicked(QBoxSet*)), receiver: this, SLOT(onDoubleClicked(QBoxSet*)));
371}
372
373void DeclarativeBoxPlotSeries::classBegin()
374{
375}
376
377void DeclarativeBoxPlotSeries::componentComplete()
378{
379 foreach (QObject *child, children()) {
380 if (qobject_cast<DeclarativeBoxSet *>(object: child)) {
381 QBoxPlotSeries::append(box: qobject_cast<DeclarativeBoxSet *>(object: child));
382 } else if (qobject_cast<QVBoxPlotModelMapper *>(object: child)) {
383 QVBoxPlotModelMapper *mapper = qobject_cast<QVBoxPlotModelMapper *>(object: child);
384 mapper->setSeries(this);
385 } else if (QHBoxPlotModelMapper *mapper = qobject_cast<QHBoxPlotModelMapper *>(object: child)) {
386 mapper->setSeries(this);
387 }
388 }
389}
390
391QQmlListProperty<QObject> DeclarativeBoxPlotSeries::seriesChildren()
392{
393 return QQmlListProperty<QObject>(this, 0, &DeclarativeBoxPlotSeries::appendSeriesChildren ,0,0,0);
394}
395
396void DeclarativeBoxPlotSeries::appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element)
397{
398 // Empty implementation; the children are parsed in componentComplete instead
399 Q_UNUSED(list);
400 Q_UNUSED(element);
401}
402
403DeclarativeBoxSet *DeclarativeBoxPlotSeries::at(int index)
404{
405 QList<QBoxSet *> setList = boxSets();
406 if (index >= 0 && index < setList.size())
407 return qobject_cast<DeclarativeBoxSet *>(object: setList[index]);
408
409 return 0;
410}
411
412DeclarativeBoxSet *DeclarativeBoxPlotSeries::insert(int index, const QString label, QVariantList values)
413{
414 DeclarativeBoxSet *barset = new DeclarativeBoxSet(label, this);
415 barset->setValues(values);
416 if (QBoxPlotSeries::insert(index, box: barset))
417 return barset;
418 delete barset;
419 return 0;
420}
421
422void DeclarativeBoxPlotSeries::onHovered(bool status, QBoxSet *boxset)
423{
424 emit hovered(status, boxset: qobject_cast<DeclarativeBoxSet *>(object: boxset));
425}
426
427void DeclarativeBoxPlotSeries::onClicked(QBoxSet *boxset)
428{
429 emit clicked(boxset: qobject_cast<DeclarativeBoxSet *>(object: boxset));
430}
431
432void DeclarativeBoxPlotSeries::onPressed(QBoxSet *boxset)
433{
434 emit pressed(boxset: qobject_cast<DeclarativeBoxSet *>(object: boxset));
435}
436
437void DeclarativeBoxPlotSeries::onReleased(QBoxSet *boxset)
438{
439 emit released(boxset: qobject_cast<DeclarativeBoxSet *>(object: boxset));
440}
441
442void DeclarativeBoxPlotSeries::onDoubleClicked(QBoxSet *boxset)
443{
444 emit doubleClicked(boxset: qobject_cast<DeclarativeBoxSet *>(object: boxset));
445}
446
447QString DeclarativeBoxPlotSeries::brushFilename() const
448{
449 return m_brushFilename;
450}
451
452void DeclarativeBoxPlotSeries::setBrushFilename(const QString &brushFilename)
453{
454 QImage brushImage(brushFilename);
455 if (QBoxPlotSeries::brush().textureImage() != brushImage) {
456 QBrush brush = QBoxPlotSeries::brush();
457 brush.setTextureImage(brushImage);
458 QBoxPlotSeries::setBrush(brush);
459 m_brushFilename = brushFilename;
460 m_brushImage = brushImage;
461 emit brushFilenameChanged(brushFilename);
462 }
463}
464
465void DeclarativeBoxPlotSeries::handleBrushChanged()
466{
467 // If the texture image of the brush has changed along the brush
468 // the brush file name needs to be cleared.
469 if (!m_brushFilename.isEmpty() && QBoxPlotSeries::brush().textureImage() != m_brushImage) {
470 m_brushFilename.clear();
471 emit brushFilenameChanged(brushFilename: QString());
472 }
473}
474
475QT_END_NAMESPACE
476
477#include "moc_declarativeboxplotseries_p.cpp"
478

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtcharts/src/chartsqml2/declarativeboxplotseries.cpp