| 1 | // Copyright (C) 2016 The Qt Company Ltd. | 
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only | 
| 3 |  | 
| 4 | #include <QtCharts/QBoxSet> | 
| 5 | #include <private/qboxset_p.h> | 
| 6 | #include <private/charthelpers_p.h> | 
| 7 |  | 
| 8 | QT_BEGIN_NAMESPACE | 
| 9 |  | 
| 10 | /*! | 
| 11 |     \class QBoxSet | 
| 12 |     \inmodule QtCharts | 
| 13 |     \brief The QBoxSet class represents one item in a box-and-whiskers chart. | 
| 14 |  | 
| 15 |     A box-and-whiskers item is a graphical representation of a range and three median values | 
| 16 |     that is constructed from five different values. There are two ways to specify the values. | 
| 17 |     The first one is by using a constructor or stream operator (<<). The values have to be | 
| 18 |     specified in the following order: lower extreme, lower quartile, median, upper quartile, | 
| 19 |     and upper extreme. | 
| 20 |  | 
| 21 |     The second way is to create an empty QBoxSet instance and specify the values using the | 
| 22 |     setValue() method. | 
| 23 |  | 
| 24 |     See the \l{Charts with Widgets Gallery} to learn how to | 
| 25 |     create a box-and-whiskers chart. | 
| 26 |  | 
| 27 |     \sa QBoxPlotSeries | 
| 28 | */ | 
| 29 | /*! | 
| 30 |     \enum QBoxSet::ValuePositions | 
| 31 |  | 
| 32 |     This enum type defines the values of a box-and-whiskers item: | 
| 33 |  | 
| 34 |     \value LowerExtreme The smallest value of the box-and-whiskers item. | 
| 35 |     \value LowerQuartile The median value of the lower half of the box-and-whiskers item. | 
| 36 |     \value Median The median value of the box-and-whiskers item. | 
| 37 |     \value UpperQuartile The median value of the upper half of the box-and-whiskers item. | 
| 38 |     \value UpperExtreme The largest value of the box-and-whiskers item. | 
| 39 | */ | 
| 40 | /*! | 
| 41 |     \property QBoxSet::pen | 
| 42 |     \brief The pen used to draw the lines of the box-and-whiskers item. | 
| 43 | */ | 
| 44 | /*! | 
| 45 |     \property QBoxSet::brush | 
| 46 |     \brief The brush used fill the box of the box-and-whiskers item. | 
| 47 | */ | 
| 48 |  | 
| 49 | /*! | 
| 50 |     \fn void QBoxSet::clicked() | 
| 51 |     This signal is emitted when the user clicks a box-and-whiskers item in the chart. | 
| 52 | */ | 
| 53 |  | 
| 54 | /*! | 
| 55 |     \fn void QBoxSet::pressed() | 
| 56 |     This signal is emitted when the user clicks a box-and-whiskers item in the chart | 
| 57 |     and holds down the mouse button. | 
| 58 | */ | 
| 59 |  | 
| 60 | /*! | 
| 61 |     \fn void QBoxSet::released() | 
| 62 |     This signal is emitted when the user releases the mouse press on a box-and-whiskers item. | 
| 63 | */ | 
| 64 |  | 
| 65 | /*! | 
| 66 |     \fn void QBoxSet::doubleClicked() | 
| 67 |     This signal is emitted when the user double-clicks a box-and-whiskers item. | 
| 68 | */ | 
| 69 |  | 
| 70 | /*! | 
| 71 |     \fn void QBoxSet::hovered(bool status) | 
| 72 |  | 
| 73 |     This signal is emitted when a mouse is hovered over a box-and-whiskers item in a chart. | 
| 74 |     When the mouse moves over the item, \a status turns \c true, and when the mouse moves | 
| 75 |     away again, it turns \c false. | 
| 76 | */ | 
| 77 | /*! | 
| 78 |     \fn void QBoxSet::penChanged() | 
| 79 |     This signal is emitted when the pen of the box-and-whiskers item changes. | 
| 80 |     \sa pen | 
| 81 | */ | 
| 82 | /*! | 
| 83 |     \fn void QBoxSet::brushChanged() | 
| 84 |     This signal is emitted when the brush of the box-and-whiskers item changes. | 
| 85 |     \sa brush | 
| 86 | */ | 
| 87 | /*! | 
| 88 |     \fn void QBoxSet::valuesChanged() | 
| 89 |     This signal is emitted when multiple values of the box-and-whiskers item change. | 
| 90 |     \sa append() | 
| 91 | */ | 
| 92 | /*! | 
| 93 |     \fn void QBoxSet::valueChanged(int index) | 
| 94 |     This signal is emitted when the value of the box-and-whiskers item specified by | 
| 95 |     \a index is modified. | 
| 96 |     \sa at() | 
| 97 | */ | 
| 98 | /*! | 
| 99 |     \fn void QBoxSet::cleared() | 
| 100 |     This signal is emitted when all the values of the box-and-whiskers item are set to 0. | 
| 101 | */ | 
| 102 |  | 
| 103 | /*! | 
| 104 |     Constructs a box-and-whiskers item with the optional label \a label and parent \a parent. | 
| 105 | */ | 
| 106 | QBoxSet::QBoxSet(const QString label, QObject *parent) | 
| 107 |     : QObject(parent), | 
| 108 |       d_ptr(new QBoxSetPrivate(label, this)) | 
| 109 | { | 
| 110 | } | 
| 111 |  | 
| 112 | /*! | 
| 113 |     Constructs a box-and-whiskers item with the following ordered values: \a le specifies the | 
| 114 |     lower extreme, \a lq the lower quartile, \a m the median, \a uq the upper quartile, and | 
| 115 |     \a ue the upper quartile. Optionally, the \a label and \a parent can be specified. | 
| 116 |  */ | 
| 117 | QBoxSet::QBoxSet(const qreal le, const qreal lq, const qreal m, const qreal uq, const qreal ue, const QString label, QObject *parent) | 
| 118 |     : QObject(parent), | 
| 119 |       d_ptr(new QBoxSetPrivate(label, this)) | 
| 120 | { | 
| 121 |     d_ptr->append(value: le); | 
| 122 |     d_ptr->append(value: lq); | 
| 123 |     d_ptr->append(value: m); | 
| 124 |     d_ptr->append(value: uq); | 
| 125 |     d_ptr->append(value: ue); | 
| 126 | } | 
| 127 |  | 
| 128 | /*! | 
| 129 |     Destroys the a box-and-whiskers item. | 
| 130 | */ | 
| 131 | QBoxSet::~QBoxSet() | 
| 132 | { | 
| 133 | } | 
| 134 |  | 
| 135 | /*! | 
| 136 |     Appends the new value specified by \a value to the end of the box-and-whiskers item. | 
| 137 | */ | 
| 138 | void QBoxSet::append(const qreal value) | 
| 139 | { | 
| 140 |     if (d_ptr->append(value)) | 
| 141 |         emit valueChanged(index: d_ptr->m_appendCount - 1); | 
| 142 | } | 
| 143 |  | 
| 144 | /*! | 
| 145 |     Appends a list of real values specified by \a values to the end of the box-and-whiskers item. | 
| 146 |     \sa append() | 
| 147 | */ | 
| 148 | void QBoxSet::append(const QList<qreal> &values) | 
| 149 | { | 
| 150 |     if (d_ptr->append(values)) | 
| 151 |         emit valuesChanged(); | 
| 152 | } | 
| 153 |  | 
| 154 | /*! | 
| 155 |     Sets the label specified by \a label for the category of the box-and-whiskers item. | 
| 156 | */ | 
| 157 | void QBoxSet::setLabel(const QString label) | 
| 158 | { | 
| 159 |     d_ptr->m_label = label; | 
| 160 | } | 
| 161 |  | 
| 162 | /*! | 
| 163 |     Returns the label of the category of the box-and-whiskers item. | 
| 164 | */ | 
| 165 | QString QBoxSet::label() const | 
| 166 | { | 
| 167 |     return d_ptr->m_label; | 
| 168 | } | 
| 169 |  | 
| 170 | /*! | 
| 171 |     A convenience operator for appending the real value specified by \a value to the end | 
| 172 |     of the box-and-whiskers item. | 
| 173 |     \sa append() | 
| 174 | */ | 
| 175 | QBoxSet &QBoxSet::operator << (const qreal &value) | 
| 176 | { | 
| 177 |     append(value); | 
| 178 |     return *this; | 
| 179 | } | 
| 180 |  | 
| 181 | /*! | 
| 182 |     Sets the value specified by \a value in the position specified by \a index. | 
| 183 |     The index can be specified by using the ValuePositions enumeration values. | 
| 184 | */ | 
| 185 | void QBoxSet::setValue(const int index, const qreal value) | 
| 186 | { | 
| 187 |     d_ptr->setValue(index, value); | 
| 188 |     emit valueChanged(index); | 
| 189 | } | 
| 190 |  | 
| 191 | /*! | 
| 192 |     Sets all the values of the box-and-whiskers item to 0. | 
| 193 |  */ | 
| 194 | void QBoxSet::clear() | 
| 195 | { | 
| 196 |     d_ptr->clear(); | 
| 197 |     emit cleared(); | 
| 198 | } | 
| 199 |  | 
| 200 | /*! | 
| 201 |     Returns the value of the box-and-whiskers item specified by \a index. | 
| 202 |     The index can be specified by using ValuePositions enumeration values. | 
| 203 |     If the index is out of bounds, 0.0 is returned. | 
| 204 | */ | 
| 205 | qreal QBoxSet::at(const int index) const | 
| 206 | { | 
| 207 |     if (index < 0 || index >= 5) | 
| 208 |         return 0; | 
| 209 |     return d_ptr->m_values[index]; | 
| 210 | } | 
| 211 |  | 
| 212 | /*! | 
| 213 |     Returns the value of the box-and-whiskers item specified by \a index. | 
| 214 |     The index can be specified by using ValuePositions enumeration values. | 
| 215 |     If the index is out of bounds, 0.0 is returned. | 
| 216 | */ | 
| 217 | qreal QBoxSet::operator [](const int index) const | 
| 218 | { | 
| 219 |     return at(index); | 
| 220 | } | 
| 221 |  | 
| 222 | /*! | 
| 223 |     Returns the number of values appended to the box-and-whiskers item. | 
| 224 | */ | 
| 225 | int QBoxSet::count() const | 
| 226 | { | 
| 227 |     return d_ptr->m_appendCount; | 
| 228 | } | 
| 229 |  | 
| 230 | /*! | 
| 231 |     Sets the pen used to draw the box-and-whiskers item to \a pen. | 
| 232 | */ | 
| 233 | void QBoxSet::setPen(const QPen &pen) | 
| 234 | { | 
| 235 |     if (d_ptr->m_pen != pen) { | 
| 236 |         d_ptr->m_pen = pen; | 
| 237 |         emit d_ptr->updatedBox(); | 
| 238 |         emit penChanged(); | 
| 239 |     } | 
| 240 | } | 
| 241 |  | 
| 242 | /*! | 
| 243 |     Returns the pen used to draw the box-and-whiskers item. | 
| 244 | */ | 
| 245 | QPen QBoxSet::pen() const | 
| 246 | { | 
| 247 |     return d_ptr->m_pen; | 
| 248 | } | 
| 249 |  | 
| 250 | /*! | 
| 251 |     Sets the brush used to fill the box-and-whiskers item to \a brush. | 
| 252 | */ | 
| 253 | void QBoxSet::setBrush(const QBrush &brush) | 
| 254 | { | 
| 255 |     if (d_ptr->m_brush != brush) { | 
| 256 |         d_ptr->m_brush = brush; | 
| 257 |         emit d_ptr->updatedBox(); | 
| 258 |         emit brushChanged(); | 
| 259 |     } | 
| 260 | } | 
| 261 |  | 
| 262 | /*! | 
| 263 |     Returns the brush used to fill the box-and-whiskers item. | 
| 264 | */ | 
| 265 | QBrush QBoxSet::brush() const | 
| 266 | { | 
| 267 |     return d_ptr->m_brush; | 
| 268 | } | 
| 269 |  | 
| 270 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | 
| 271 |  | 
| 272 | QBoxSetPrivate::QBoxSetPrivate(const QString label, QBoxSet *parent) : QObject(parent), | 
| 273 |     q_ptr(parent), | 
| 274 |     m_label(label), | 
| 275 |     m_valuesCount(5), | 
| 276 |     m_appendCount(0), | 
| 277 |     m_pen(QPen(Qt::NoPen)), | 
| 278 |     m_brush(QBrush(Qt::NoBrush)), | 
| 279 |     m_series(0) | 
| 280 | { | 
| 281 |     m_values = new qreal[m_valuesCount]; | 
| 282 | } | 
| 283 |  | 
| 284 | QBoxSetPrivate::~QBoxSetPrivate() | 
| 285 | { | 
| 286 |     delete[] m_values; | 
| 287 | } | 
| 288 |  | 
| 289 | bool QBoxSetPrivate::append(qreal value) | 
| 290 | { | 
| 291 |     if (isValidValue(value) && m_appendCount < m_valuesCount) { | 
| 292 |         m_values[m_appendCount++] = value; | 
| 293 |         emit restructuredBox(); | 
| 294 |  | 
| 295 |         return true; | 
| 296 |     } | 
| 297 |     return false; | 
| 298 | } | 
| 299 |  | 
| 300 | bool QBoxSetPrivate::append(const QList<qreal> &values) | 
| 301 | { | 
| 302 |     bool success = false; | 
| 303 |  | 
| 304 |     for (const qreal value : values) { | 
| 305 |         if (isValidValue(value) && m_appendCount < m_valuesCount) { | 
| 306 |             success = true; | 
| 307 |             m_values[m_appendCount++] = value; | 
| 308 |         } | 
| 309 |     } | 
| 310 |  | 
| 311 |     if (success) | 
| 312 |         emit restructuredBox(); | 
| 313 |  | 
| 314 |     return success; | 
| 315 | } | 
| 316 |  | 
| 317 | void QBoxSetPrivate::clear() | 
| 318 | { | 
| 319 |     m_appendCount = 0; | 
| 320 |     for (int i = 0; i < m_valuesCount; i++) { | 
| 321 |          m_values[i] = 0.0; | 
| 322 |     } | 
| 323 |     emit restructuredBox(); | 
| 324 | } | 
| 325 |  | 
| 326 | void QBoxSetPrivate::setValue(const int index, const qreal value) | 
| 327 | { | 
| 328 |     if (index < m_valuesCount) { | 
| 329 |         m_values[index] = value; | 
| 330 |         emit updatedLayout(); | 
| 331 |     } | 
| 332 | } | 
| 333 |  | 
| 334 | qreal QBoxSetPrivate::value(const int index) | 
| 335 | { | 
| 336 |     if (index < 0 || index >= m_valuesCount) | 
| 337 |         return 0; | 
| 338 |     return m_values[index]; | 
| 339 | } | 
| 340 |  | 
| 341 | QT_END_NAMESPACE | 
| 342 |  | 
| 343 | #include "moc_qboxset.cpp" | 
| 344 | #include "moc_qboxset_p.cpp" | 
| 345 |  |