| 1 | // Copyright (C) 2023 The Qt Company Ltd. | 
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only | 
| 3 |  | 
| 4 | #include <QtGraphs/qbarset.h> | 
| 5 | #include <private/qbarset_p.h> | 
| 6 | #include <private/charthelpers_p.h> | 
| 7 |  | 
| 8 | QT_BEGIN_NAMESPACE | 
| 9 |  | 
| 10 | /*! | 
| 11 |     \class QBarSet | 
| 12 |     \inmodule QtGraphs | 
| 13 |     \ingroup graphs_2D | 
| 14 |     \brief The QBarSet class represents one set of bars in a bar graph. | 
| 15 |  | 
| 16 |     A bar set contains one data value for each category. The first value of a set is assumed to | 
| 17 |     belong to the first category, the second one to the second category, and so on. If the set has | 
| 18 |     fewer values than there are categories, the missing values are assumed to be located at the end | 
| 19 |     of the set. For missing values in the middle of a set, the numerical value of zero is used. | 
| 20 |     Labels for zero value sets are not shown. | 
| 21 |  | 
| 22 |     \sa QBarSeries | 
| 23 | */ | 
| 24 | /*! | 
| 25 |     \qmltype BarSet | 
| 26 |     \nativetype QBarSet | 
| 27 |     \inqmlmodule QtGraphs | 
| 28 |     \ingroup graphs_qml_2D | 
| 29 |     \brief Represents one set of bars in a bar graph. | 
| 30 |  | 
| 31 |     A bar set contains one data value for each category. The first value of a set is assumed to | 
| 32 |     belong to the first category, the second one to the second category, and so on. If the set has | 
| 33 |     fewer values than there are categories, the missing values are assumed to be located at the end | 
| 34 |     of the set. For missing values in the middle of a set, the numerical value of zero is used. | 
| 35 |     Labels for zero value sets are not shown. | 
| 36 |  | 
| 37 |     \sa BarSeries | 
| 38 | */ | 
| 39 |  | 
| 40 | /*! | 
| 41 |     \property QBarSet::label | 
| 42 |     \brief The label of the bar set. | 
| 43 | */ | 
| 44 | /*! | 
| 45 |     \qmlproperty string BarSet::label | 
| 46 |     The label of the bar set. | 
| 47 | */ | 
| 48 |  | 
| 49 | /*! | 
| 50 |     \property QBarSet::color | 
| 51 |     \brief The fill color of the bar set. | 
| 52 | */ | 
| 53 | /*! | 
| 54 |     \qmlproperty color BarSet::color | 
| 55 |     The fill color of the bar set. | 
| 56 | */ | 
| 57 |  | 
| 58 | /*! | 
| 59 |     \property QBarSet::selectedColor | 
| 60 |     \brief The fill color of the selected set. | 
| 61 | */ | 
| 62 | /*! | 
| 63 |     \qmlproperty color BarSet::selectedColor | 
| 64 |     The fill color of the selected set. | 
| 65 | */ | 
| 66 |  | 
| 67 | /*! | 
| 68 |     \property QBarSet::borderColor | 
| 69 |     \brief The border color of the bar set. | 
| 70 | */ | 
| 71 | /*! | 
| 72 |     \qmlproperty color BarSet::borderColor | 
| 73 |     The border color of the bar set. | 
| 74 | */ | 
| 75 |  | 
| 76 | /*! | 
| 77 |     \property QBarSet::borderWidth | 
| 78 |     \brief The width of the border line. | 
| 79 |     By default, the width is -1, meaning the border width is defined by the theme. | 
| 80 | */ | 
| 81 | /*! | 
| 82 |     \qmlproperty real BarSet::borderWidth | 
| 83 |      By default, the width is -1, meaning the border width is defined by the theme. | 
| 84 | */ | 
| 85 |  | 
| 86 | /*! | 
| 87 |     \property QBarSet::count | 
| 88 |     \brief The number of values in the bar set. | 
| 89 | */ | 
| 90 | /*! | 
| 91 |     \qmlproperty int BarSet::count | 
| 92 |     The number of values in the bar set. | 
| 93 | */ | 
| 94 |  | 
| 95 | /*! | 
| 96 |     \property QBarSet::labelColor | 
| 97 |     \brief The text (label) color of the bar set. | 
| 98 | */ | 
| 99 | /*! | 
| 100 |     \qmlproperty color BarSet::labelColor | 
| 101 |     The text (label) color of the bar set. | 
| 102 | */ | 
| 103 |  | 
| 104 | /*! | 
| 105 |     \property QBarSet::selectedBars | 
| 106 |     \brief The indexes of the bars which are currently selected. | 
| 107 | */ | 
| 108 | /*! | 
| 109 |     \qmlproperty list BarSet::selectedBars | 
| 110 |     The indexes of the bars which are currently selected. | 
| 111 | */ | 
| 112 |  | 
| 113 | /*! | 
| 114 |    \property QBarSet::values | 
| 115 |    \brief The values of the bar set. | 
| 116 |  | 
| 117 |     You can set a list of either \l [QML]{real} or \l [QML]{point} | 
| 118 |     types as values. | 
| 119 |  | 
| 120 |     If you set a list of real types as values, they directly define the bar set values. | 
| 121 |  | 
| 122 |     If you set a list of point types as values, the x-coordinate of the point specifies its | 
| 123 |     zero-based index in the bar set. The size of the bar set is the highest x-coordinate value + 1. | 
| 124 |     If a point is missing for any x-coordinate between zero and the highest value, | 
| 125 |     it gets the value zero. | 
| 126 |  */ | 
| 127 | /*! | 
| 128 |     \qmlproperty list<variant> BarSet::values | 
| 129 |     The values of the bar set. You can set a list of either \l [QML]{real} or \l [QML]{point} | 
| 130 |     types as values. | 
| 131 |  | 
| 132 |     If you set a list of real types as values, they directly define the bar set values. | 
| 133 |  | 
| 134 |     If you set a list of point types as values, the x-coordinate of the point specifies its | 
| 135 |     zero-based index in the bar set. The size of the bar set is the highest x-coordinate value + 1. | 
| 136 |     If a point is missing for any x-coordinate between zero and the highest value, | 
| 137 |     it gets the value zero. | 
| 138 |  | 
| 139 |     For example, the following bar sets have equal values: | 
| 140 |     \code | 
| 141 |         myBarSet1.values = [5, 0, 1, 5]; | 
| 142 |         myBarSet2.values = [Qt.point(0, 5), Qt.point(2, 1), Qt.point(3, 5)]; | 
| 143 |     \endcode | 
| 144 | */ | 
| 145 |  | 
| 146 | /*! | 
| 147 |     \fn void QBarSet::update() | 
| 148 |     This signal is emitted when the barset is updated. | 
| 149 | */ | 
| 150 | /*! | 
| 151 |     \qmlsignal BarSet::update() | 
| 152 |     This signal is emitted when the barset is updated. | 
| 153 | */ | 
| 154 |  | 
| 155 | /*! | 
| 156 |     \qmlsignal BarSet::labelChanged() | 
| 157 |     This signal is emitted when the label of the bar set changes. | 
| 158 |     \sa label | 
| 159 | */ | 
| 160 |  | 
| 161 | /*! | 
| 162 |     \qmlsignal BarSet::colorChanged(color) | 
| 163 |     This signal is emitted when the fill color of the bar set changes to \a color. | 
| 164 | */ | 
| 165 |  | 
| 166 | /*! | 
| 167 |     \qmlsignal BarSet::borderColorChanged(color) | 
| 168 |     This signal is emitted when the border color of the bar set changes to \a color. | 
| 169 | */ | 
| 170 |  | 
| 171 | /*! | 
| 172 |     \qmlsignal BarSet::labelColorChanged(color) | 
| 173 |     This signal is emitted when the text (label) color of the bar set changes to \a color. | 
| 174 | */ | 
| 175 |  | 
| 176 | /*! | 
| 177 |     \qmlsignal BarSet::valuesChanged() | 
| 178 |     This signal is emitted when the values of the bar set change. | 
| 179 | */ | 
| 180 |  | 
| 181 | /*! | 
| 182 |     \qmlsignal BarSet::selectedColorChanged(color color) | 
| 183 |     This signal is emitted when the selected bar color changes. The new color is | 
| 184 |     \a color. | 
| 185 | */ | 
| 186 |  | 
| 187 | /*! | 
| 188 |     \qmlsignal BarSet::countChanged() | 
| 189 |     This signal is emitted when the barset's value count changes. | 
| 190 | */ | 
| 191 |  | 
| 192 | /*! | 
| 193 |     \qmlsignal BarSet::borderWidthChanged(real width) | 
| 194 |     This signal is emitted when the barset's border width changes. | 
| 195 |     The new width is \a width. | 
| 196 | */ | 
| 197 |  | 
| 198 | /*! | 
| 199 |     \fn void QBarSet::valuesAdded(qsizetype index, qsizetype count) | 
| 200 |     This signal is emitted when new values are added to the bar set. | 
| 201 |     \a index indicates the position of the first inserted value, and \a count is the number | 
| 202 |     of inserted values. | 
| 203 |     \sa append(), insert() | 
| 204 | */ | 
| 205 | /*! | 
| 206 |     \qmlsignal BarSet::valuesAdded(int index, int count) | 
| 207 |     This signal is emitted when new values are added to the bar set. | 
| 208 |     \a index indicates the position of the first inserted value, and \a count is the number | 
| 209 |     of inserted values. | 
| 210 | */ | 
| 211 |  | 
| 212 | /*! | 
| 213 |     \fn void QBarSet::valuesRemoved(qsizetype index, qsizetype count) | 
| 214 |     This signal is emitted when values are removed from the bar set. | 
| 215 |     \a index indicates the position of the first removed value, and \a count is the number | 
| 216 |     of removed values. | 
| 217 |     \sa remove() | 
| 218 | */ | 
| 219 | /*! | 
| 220 |     \qmlsignal BarSet::valuesRemoved(int index, int count) | 
| 221 |     This signal is emitted when values are removed from the bar set. | 
| 222 |     \a index indicates the position of the first removed value, and \a count is the number | 
| 223 |     of removed values. | 
| 224 | */ | 
| 225 |  | 
| 226 | /*! | 
| 227 |     \fn void QBarSet::valueChanged(qsizetype index) | 
| 228 |     This signal is emitted when the value at the position specified by \a index is modified. | 
| 229 |     \sa at() | 
| 230 | */ | 
| 231 | /*! | 
| 232 |     \qmlsignal BarSet::valueChanged(int index) | 
| 233 |     This signal is emitted when the value at the position specified by \a index is modified. | 
| 234 | */ | 
| 235 |  | 
| 236 | /*! | 
| 237 |     \fn void QBarSet::updatedBars() | 
| 238 |     This signal is emitted when the bars in this set are updated. | 
| 239 | */ | 
| 240 | /*! | 
| 241 |     \qmlsignal BarSet::updatedBars() | 
| 242 |     This signal is emitted when the bars in this set are updated. | 
| 243 | */ | 
| 244 |  | 
| 245 | /*! | 
| 246 |     \fn void QBarSet::valueAdded(qsizetype index, qsizetype count) | 
| 247 |     This signal is emitted when new values are added to the bar set. | 
| 248 |     \a index indicates the position of the first inserted value, and \a count | 
| 249 |     is the number of inserted values. | 
| 250 | */ | 
| 251 | /*! | 
| 252 |     \qmlsignal BarSet::valueAdded(int index, int count) | 
| 253 |     This signal is emitted when new values are added to the bar set. | 
| 254 |     \a index indicates the position of the first inserted value, and \a count | 
| 255 |     is the number of inserted values. | 
| 256 | */ | 
| 257 |  | 
| 258 | /*! | 
| 259 |     \fn void QBarSet::valueRemoved(qsizetype index, qsizetype count) | 
| 260 |     This signal is emitted when values are removed from the bar set. | 
| 261 |     \a index indicates the position of the first removed value, and \a count | 
| 262 |     is the number of removed values. | 
| 263 | */ | 
| 264 | /*! | 
| 265 |     \qmlsignal BarSet::valueRemoved(int index, int count) | 
| 266 |     This signal is emitted when values are removed from the bar set. | 
| 267 |     \a index indicates the position of the first removed value, and \a count | 
| 268 |     is the number of removed values. | 
| 269 | */ | 
| 270 |  | 
| 271 | /*! | 
| 272 |     \fn void QBarSet::selectedBarsChanged(const QList<qsizetype> &indexes) | 
| 273 |     This signal is emitted when the selected bar changes. \a indexes is | 
| 274 |     a list selected bar indexes. | 
| 275 | */ | 
| 276 | /*! | 
| 277 |     \qmlsignal BarSet::selectedBarsChanged(list<int> indexes) | 
| 278 |     This signal is emitted when the selected bar changes. \a indexes is | 
| 279 |     a list selected bar indexes. | 
| 280 | */ | 
| 281 |  | 
| 282 | QBarSet::QBarSet(QObject *parent) | 
| 283 |     : QBarSet(QString(), parent) | 
| 284 | {} | 
| 285 |  | 
| 286 | /*! | 
| 287 |     Constructs a bar set with the label \a label and the parent \a parent. | 
| 288 | */ | 
| 289 | QBarSet::QBarSet(const QString &label, QObject *parent) | 
| 290 |     : QObject(*(new QBarSetPrivate(label)), parent) | 
| 291 | {} | 
| 292 |  | 
| 293 | /*! | 
| 294 |     Removes the bar set. | 
| 295 | */ | 
| 296 | QBarSet::~QBarSet() | 
| 297 | { | 
| 298 |     // NOTE: d_ptr destroyed by QObject | 
| 299 | } | 
| 300 |  | 
| 301 | /*! | 
| 302 |     Sets \a label as the new label for the bar set. | 
| 303 | */ | 
| 304 | void QBarSet::setLabel(const QString &label) | 
| 305 | { | 
| 306 |     Q_D(QBarSet); | 
| 307 |     if (d->m_label != label) { | 
| 308 |         d->m_label = label; | 
| 309 |         d->setLabelsDirty(true); | 
| 310 |         emit update(); | 
| 311 |         emit labelChanged(); | 
| 312 |     } | 
| 313 | } | 
| 314 |  | 
| 315 | /*! | 
| 316 |     Returns the label of the bar set. | 
| 317 | */ | 
| 318 | QString QBarSet::label() const | 
| 319 | { | 
| 320 |     Q_D(const QBarSet); | 
| 321 |     return d->m_label; | 
| 322 | } | 
| 323 |  | 
| 324 | /*! | 
| 325 |     \qmlmethod BarSet::append(real value) | 
| 326 |     Appends the new value specified by \a value to the end of the bar set. | 
| 327 | */ | 
| 328 | /*! | 
| 329 |     Appends the new value specified by \a value to the end of the bar set. | 
| 330 | */ | 
| 331 | void QBarSet::append(qreal value) | 
| 332 | { | 
| 333 |     Q_D(QBarSet); | 
| 334 |     // Convert to QPointF | 
| 335 |     qsizetype index = d->m_values.size(); | 
| 336 |     d->append(value: QPointF(d->m_values.size(), value)); | 
| 337 |     emit valuesAdded(index, count: 1); | 
| 338 |     emit countChanged(); | 
| 339 |     emit update(); | 
| 340 | } | 
| 341 |  | 
| 342 | /*! | 
| 343 |     \qmlmethod BarSet::append(list<real> values) | 
| 344 |     Appends the list of real values specified by \a values to the end of the bar set. | 
| 345 |  | 
| 346 |     \sa append() | 
| 347 | */ | 
| 348 | /*! | 
| 349 |     Appends the list of real values specified by \a values to the end of the bar set. | 
| 350 |  | 
| 351 |     \sa append() | 
| 352 | */ | 
| 353 | void QBarSet::append(const QList<qreal> &values) | 
| 354 | { | 
| 355 |     Q_D(QBarSet); | 
| 356 |     qsizetype index = d->m_values.size(); | 
| 357 |     d->append(values); | 
| 358 |     emit valuesAdded(index, count: values.size()); | 
| 359 |     emit countChanged(); | 
| 360 |     emit update(); | 
| 361 | } | 
| 362 |  | 
| 363 | /*! | 
| 364 |     \qmlmethod BarSet::insert(int index, real value) | 
| 365 |     Inserts \a value in the position specified by \a index. | 
| 366 |     The values following the inserted value are moved up one position. | 
| 367 |  | 
| 368 |     \sa remove() | 
| 369 | */ | 
| 370 | /*! | 
| 371 |     Inserts \a value in the position specified by \a index. | 
| 372 |     The values following the inserted value are moved up one position. | 
| 373 |  | 
| 374 |     \sa remove() | 
| 375 | */ | 
| 376 | void QBarSet::insert(qsizetype index, qreal value) | 
| 377 | { | 
| 378 |     Q_D(QBarSet); | 
| 379 |     d->insert(index, value); | 
| 380 |  | 
| 381 |     bool callSignal = false; | 
| 382 |     if (!d->m_selectedBars.isEmpty()) { | 
| 383 |         // if value was inserted we need to move already selected bars by 1 | 
| 384 |         QSet<qsizetype> selectedAfterInsert; | 
| 385 |         for (const auto &value : std::as_const(t&: d->m_selectedBars)) { | 
| 386 |             if (value >= index) { | 
| 387 |                 selectedAfterInsert << value + 1; | 
| 388 |                 callSignal = true; | 
| 389 |             } else { | 
| 390 |                 selectedAfterInsert << value; | 
| 391 |             } | 
| 392 |         } | 
| 393 |         d->m_selectedBars = selectedAfterInsert; | 
| 394 |         emit update(); | 
| 395 |     } | 
| 396 |  | 
| 397 |     emit valuesAdded(index, count: 1); | 
| 398 |     emit countChanged(); | 
| 399 |     if (callSignal) | 
| 400 |         emit selectedBarsChanged(indexes: selectedBars()); | 
| 401 | } | 
| 402 |  | 
| 403 | /*! | 
| 404 |     \qmlmethod BarSet::remove(int index, int count) | 
| 405 |     Removes the number of values specified by \a count from the bar set starting | 
| 406 |     with the value specified by \a index. | 
| 407 |  | 
| 408 |     If you leave out \a count, only the value specified by \a index is removed. | 
| 409 | */ | 
| 410 | /*! | 
| 411 |     Removes the number of values specified by \a count from the bar set starting with | 
| 412 |     the value specified by \a index. | 
| 413 |     \sa insert() | 
| 414 | */ | 
| 415 | void QBarSet::remove(qsizetype index, qsizetype count) | 
| 416 | { | 
| 417 |     Q_D(QBarSet); | 
| 418 |     qsizetype removedCount = d->remove(index, count); | 
| 419 |     if (removedCount > 0) { | 
| 420 |         emit valuesRemoved(index, count: removedCount); | 
| 421 |         emit countChanged(); | 
| 422 |         emit update(); | 
| 423 |     } | 
| 424 | } | 
| 425 |  | 
| 426 | /*! | 
| 427 |     \qmlmethod BarSet::replace(int index, real value) | 
| 428 |     Adds the value specified by \a value to the bar set at the position | 
| 429 |     specified by \a index. | 
| 430 | */ | 
| 431 | /*! | 
| 432 |     Adds the value specified by \a value to the bar set at the position specified by \a index. | 
| 433 | */ | 
| 434 | void QBarSet::replace(qsizetype index, qreal value) | 
| 435 | { | 
| 436 |     Q_D(QBarSet); | 
| 437 |     if (index >= 0 && index < d->m_values.size()) { | 
| 438 |         d->replace(index, value); | 
| 439 |         emit valueChanged(index); | 
| 440 |         emit update(); | 
| 441 |     } | 
| 442 | } | 
| 443 |  | 
| 444 | /*! | 
| 445 |     \qmlmethod real BarSet::at(int index) | 
| 446 |     Returns the value specified by \a index from the bar set. | 
| 447 |     If the index is out of bounds, 0.0 is returned. | 
| 448 | */ | 
| 449 | /*! | 
| 450 |     Returns the value specified by \a index from the bar set. | 
| 451 |     If the index is out of bounds, 0.0 is returned. | 
| 452 | */ | 
| 453 | qreal QBarSet::at(qsizetype index) const | 
| 454 | { | 
| 455 |     Q_D(const QBarSet); | 
| 456 |     if (index < 0 || index >= d->m_values.size()) | 
| 457 |         return 0; | 
| 458 |     return d->m_values.at(i: index).y(); | 
| 459 | } | 
| 460 |  | 
| 461 | /*! | 
| 462 |     \qmlmethod int BarSet::count() | 
| 463 |     Returns the number of values in a bar set. | 
| 464 | */ | 
| 465 | /*! | 
| 466 |     Returns the number of values in a bar set. | 
| 467 | */ | 
| 468 | qsizetype QBarSet::count() const | 
| 469 | { | 
| 470 |     Q_D(const QBarSet); | 
| 471 |     return d->m_values.size(); | 
| 472 | } | 
| 473 |  | 
| 474 | /*! | 
| 475 |     \qmlmethod real BarSet::sum() | 
| 476 |     Returns the sum of all values in the bar set. | 
| 477 | */ | 
| 478 | /*! | 
| 479 |     Returns the sum of all values in the bar set. | 
| 480 | */ | 
| 481 | qreal QBarSet::sum() const | 
| 482 | { | 
| 483 |     Q_D(const QBarSet); | 
| 484 |     qreal total(0); | 
| 485 |     for (int i = 0; i < d->m_values.size(); i++) | 
| 486 |         total += d->m_values.at(i).y(); | 
| 487 |     return total; | 
| 488 | } | 
| 489 |  | 
| 490 | /*! | 
| 491 |     \qmlmethod BarSet::clear() | 
| 492 |     Removes all values from the set. | 
| 493 | */ | 
| 494 | /*! | 
| 495 |     Removes all values from the set. | 
| 496 | */ | 
| 497 | void QBarSet::clear() | 
| 498 | { | 
| 499 |     Q_D(QBarSet); | 
| 500 |     remove(index: 0, count: d->m_values.size()); | 
| 501 | } | 
| 502 |  | 
| 503 | /*! | 
| 504 |     A convenience operator for appending the real value specified by \a value to the end of the | 
| 505 |     bar set. | 
| 506 |  | 
| 507 |     \sa append() | 
| 508 | */ | 
| 509 | QBarSet &QBarSet::operator << (qreal value) | 
| 510 | { | 
| 511 |     append(value); | 
| 512 |     return *this; | 
| 513 | } | 
| 514 |  | 
| 515 | /*! | 
| 516 |     Returns the value of the bar set specified by \a index. | 
| 517 |     If the index is out of bounds, 0.0 is returned. | 
| 518 | */ | 
| 519 | qreal QBarSet::operator [](qsizetype index) const | 
| 520 | { | 
| 521 |     return at(index); | 
| 522 | } | 
| 523 |  | 
| 524 | /*! | 
| 525 |     Returns the fill color for the bar set. | 
| 526 | */ | 
| 527 | QColor QBarSet::color() const | 
| 528 | { | 
| 529 |     Q_D(const QBarSet); | 
| 530 |     return d->m_color; | 
| 531 | } | 
| 532 |  | 
| 533 | /*! | 
| 534 |     Sets the fill color for the bar set to \a color. | 
| 535 | */ | 
| 536 | void QBarSet::setColor(QColor color) | 
| 537 | { | 
| 538 |     Q_D(QBarSet); | 
| 539 |     if (d->m_color != color) { | 
| 540 |         d->m_color = color; | 
| 541 |         emit update(); | 
| 542 |         emit colorChanged(color); | 
| 543 |     } | 
| 544 | } | 
| 545 |  | 
| 546 | /*! | 
| 547 |     Returns the line color for the bar set. | 
| 548 | */ | 
| 549 | QColor QBarSet::borderColor() const | 
| 550 | { | 
| 551 |     Q_D(const QBarSet); | 
| 552 |     return d->m_borderColor; | 
| 553 | } | 
| 554 |  | 
| 555 | /*! | 
| 556 |     Sets the line color for the bar set to \a color. | 
| 557 | */ | 
| 558 | void QBarSet::setBorderColor(QColor color) | 
| 559 | { | 
| 560 |     Q_D(QBarSet); | 
| 561 |     if (d->m_borderColor != color) { | 
| 562 |         d->m_borderColor = color; | 
| 563 |         emit update(); | 
| 564 |         emit borderColorChanged(color); | 
| 565 |     } | 
| 566 | } | 
| 567 |  | 
| 568 | /*! | 
| 569 |     Returns the text color for the bar set. | 
| 570 | */ | 
| 571 | QColor QBarSet::labelColor() const | 
| 572 | { | 
| 573 |     Q_D(const QBarSet); | 
| 574 |     return d->m_labelColor; | 
| 575 | } | 
| 576 |  | 
| 577 | /*! | 
| 578 |     Sets the text color for the bar set to \a color. | 
| 579 | */ | 
| 580 | void QBarSet::setLabelColor(QColor color) | 
| 581 | { | 
| 582 |     Q_D(QBarSet); | 
| 583 |     if (d->m_labelColor != color) { | 
| 584 |         d->m_labelColor = color; | 
| 585 |         emit update(); | 
| 586 |         emit labelColorChanged(color); | 
| 587 |     } | 
| 588 | } | 
| 589 |  | 
| 590 | /*! | 
| 591 |     Returns the color of the selected bars. | 
| 592 |  | 
| 593 |     This is the fill (brush) color of bars marked as selected. If not specified, | 
| 594 |     value of QBarSet::color is used as default. | 
| 595 |     \sa color | 
| 596 | */ | 
| 597 | QColor QBarSet::selectedColor() const | 
| 598 | { | 
| 599 |     Q_D(const QBarSet); | 
| 600 |     return d->m_selectedColor; | 
| 601 | } | 
| 602 |  | 
| 603 | /*! | 
| 604 |     Sets the \a color of the selected bars. | 
| 605 |     \sa selectedColor | 
| 606 | */ | 
| 607 | void QBarSet::setSelectedColor(QColor color) | 
| 608 | { | 
| 609 |     Q_D(QBarSet); | 
| 610 |     if (d->m_selectedColor != color) { | 
| 611 |         d->m_selectedColor = color; | 
| 612 |         d->setLabelsDirty(true); | 
| 613 |         emit update(); | 
| 614 |         emit updatedBars(); | 
| 615 |         emit selectedColorChanged(color); | 
| 616 |     } | 
| 617 | } | 
| 618 |  | 
| 619 |  | 
| 620 | qreal QBarSet::borderWidth() const | 
| 621 | { | 
| 622 |     Q_D(const QBarSet); | 
| 623 |     return d->m_borderWidth; | 
| 624 | } | 
| 625 |  | 
| 626 | void QBarSet::setBorderWidth(qreal width) | 
| 627 | { | 
| 628 |     Q_D(QBarSet); | 
| 629 |     width = qMax(a: 0.0, b: width); | 
| 630 |     if (!qFuzzyCompare(p1: d->m_borderWidth, p2: width)) { | 
| 631 |         d->m_borderWidth = width; | 
| 632 |         emit update(); | 
| 633 |         emit borderWidthChanged(width); | 
| 634 |     } | 
| 635 | } | 
| 636 |  | 
| 637 | QVariantList QBarSet::values() const | 
| 638 | { | 
| 639 |     QVariantList values; | 
| 640 |     for (qsizetype i(0); i < count(); i++) | 
| 641 |         values.append(t: QVariant(QBarSet::at(index: i))); | 
| 642 |     return values; | 
| 643 | } | 
| 644 |  | 
| 645 | void QBarSet::setValues(const QVariantList &values) | 
| 646 | { | 
| 647 |     bool valuesUpdated = false; | 
| 648 |     // See if we can replace values instead of remove & add all. | 
| 649 |     // This way e.g. selections remain. | 
| 650 |     const bool doReplace = count() == values.size(); | 
| 651 |  | 
| 652 |     if (!doReplace) { | 
| 653 |         while (count()) | 
| 654 |             remove(index: count() - 1); | 
| 655 |         valuesUpdated = true; | 
| 656 |     } | 
| 657 |  | 
| 658 |     if (values.size() > 0 && values.at(i: 0).canConvert<QPoint>()) { | 
| 659 |         // Create list of values for appending if the first item is Qt.point | 
| 660 |         int maxValue = 0; | 
| 661 |         for (int i = 0; i < values.size(); i++) { | 
| 662 |             if (values.at(i).canConvert<QPoint>() && | 
| 663 |                 values.at(i).toPoint().x() > maxValue) { | 
| 664 |                 maxValue = values.at(i).toPoint().x(); | 
| 665 |             } | 
| 666 |         } | 
| 667 |  | 
| 668 |         QList<qreal> indexValueList; | 
| 669 |         indexValueList.resize(size: maxValue + 1); | 
| 670 |  | 
| 671 |         for (int i = 0; i < values.size(); i++) { | 
| 672 |             if (values.at(i).canConvert<QPoint>()) | 
| 673 |                 indexValueList.replace(i: values.at(i).toPoint().x(), t: values.at(i).toPointF().y()); | 
| 674 |         } | 
| 675 |  | 
| 676 |         for (int i = 0; i < indexValueList.size(); i++) { | 
| 677 |             if (doReplace) | 
| 678 |                 QBarSet::replace(index: i, value: indexValueList.at(i)); | 
| 679 |             else | 
| 680 |                 QBarSet::append(value: indexValueList.at(i)); | 
| 681 |             valuesUpdated = true; | 
| 682 |         } | 
| 683 |  | 
| 684 |     } else { | 
| 685 |         for (int i(0); i < values.size(); i++) { | 
| 686 |             if (values.at(i).canConvert<double>()) { | 
| 687 |                 if (doReplace) | 
| 688 |                     QBarSet::replace(index: i, value: values[i].toDouble()); | 
| 689 |                 else | 
| 690 |                     QBarSet::append(value: values[i].toDouble()); | 
| 691 |                 valuesUpdated = true; | 
| 692 |             } | 
| 693 |         } | 
| 694 |     } | 
| 695 |     emit update(); | 
| 696 |     if (valuesUpdated) | 
| 697 |         emit valuesChanged(); | 
| 698 | } | 
| 699 |  | 
| 700 |  | 
| 701 | /*! | 
| 702 |     \qmlmethod bool BarSet::isBarSelected(int index) | 
| 703 |     Returns \c true if the bar at the given \a index is among selected bars and \c false otherwise. | 
| 704 |     \note Selected bars are drawn using the selected color if it was specified using BarSet::setSelectedColor. | 
| 705 |     \sa selectedBars, setBarSelected(), selectedColor | 
| 706 |  */ | 
| 707 | /*! | 
| 708 |     Returns \c true if the bar at the given \a index is among selected bars and \c false otherwise. | 
| 709 |     \note Selected bars are drawn using the selected color if it was specified using QBarSet::setSelectedColor. | 
| 710 |     \sa selectedBars(), setBarSelected(), setSelectedColor() | 
| 711 |  */ | 
| 712 | bool QBarSet::isBarSelected(qsizetype index) const | 
| 713 | { | 
| 714 |     Q_D(const QBarSet); | 
| 715 |     return d->isBarSelected(index); | 
| 716 | } | 
| 717 |  | 
| 718 | /*! | 
| 719 |     \qmlmethod BarSet::selectBar(int index) | 
| 720 |     Marks the bar at \a index as selected. | 
| 721 |     \note Emits BarSet::selectedBarsChanged. | 
| 722 |     \sa setBarSelected() | 
| 723 |  */ | 
| 724 | /*! | 
| 725 |     Marks the bar at \a index as selected. | 
| 726 |     \note Emits QBarSet::selectedBarsChanged. | 
| 727 |     \sa setBarSelected() | 
| 728 |  */ | 
| 729 | void QBarSet::selectBar(qsizetype index) | 
| 730 | { | 
| 731 |     setBarSelected(index, selected: true); | 
| 732 | } | 
| 733 |  | 
| 734 | /*! | 
| 735 |     \qmlmethod BarSet::deselectBar(int index) | 
| 736 |     Deselects the bar at \a index. | 
| 737 |     \note Emits BarSet::selectedBarsChanged. | 
| 738 |     \sa setBarSelected() | 
| 739 |  */ | 
| 740 | /*! | 
| 741 |     Deselects the bar at \a index. | 
| 742 |     \note Emits QBarSet::selectedBarsChanged. | 
| 743 |     \sa setBarSelected() | 
| 744 |  */ | 
| 745 | void QBarSet::deselectBar(qsizetype index) | 
| 746 | { | 
| 747 |     setBarSelected(index, selected: false); | 
| 748 | } | 
| 749 |  | 
| 750 | /*! | 
| 751 |     \qmlmethod BarSet::setBarSelected(int index, bool selected) | 
| 752 |     Marks the bar at \a index as either selected or deselected as specified by \a selected. | 
| 753 |     \note Selected bars are drawn using the selected color if it was specified. Emits BarSet::selectedBarsChanged. | 
| 754 |     \sa selectedColor | 
| 755 |  */ | 
| 756 | /*! | 
| 757 |     Marks the bar at \a index as either selected or deselected as specified by \a selected. | 
| 758 |     \note Selected bars are drawn using the selected color if it was specified. Emits QBarSet::selectedBarsChanged. | 
| 759 |     \sa setSelectedColor() | 
| 760 |  */ | 
| 761 | void QBarSet::setBarSelected(qsizetype index, bool selected) | 
| 762 | { | 
| 763 |     Q_D(QBarSet); | 
| 764 |     bool callSignal = false; | 
| 765 |     d->setBarSelected(index, selected, callSignal); | 
| 766 |  | 
| 767 |     if (callSignal) | 
| 768 |         emit selectedBarsChanged(indexes: selectedBars()); | 
| 769 |     emit update(); | 
| 770 | } | 
| 771 |  | 
| 772 | /*! | 
| 773 |     \qmlmethod BarSet::selectAllBars() | 
| 774 |     Marks all bars in the set as selected. | 
| 775 |     \note Emits BarSet::selectedBarsChanged. | 
| 776 |     \sa setBarSelected() | 
| 777 |  */ | 
| 778 | /*! | 
| 779 |     Marks all bars in the set as selected. | 
| 780 |     \note Emits QBarSet::selectedBarsChanged. | 
| 781 |     \sa setBarSelected() | 
| 782 |  */ | 
| 783 | void QBarSet::selectAllBars() | 
| 784 | { | 
| 785 |     Q_D(QBarSet); | 
| 786 |     bool callSignal = false; | 
| 787 |     for (int i = 0; i < d->m_values.size(); ++i) | 
| 788 |         d->setBarSelected(index: i, selected: true, callSignal); | 
| 789 |  | 
| 790 |     if (callSignal) | 
| 791 |         emit selectedBarsChanged(indexes: selectedBars()); | 
| 792 |     emit update(); | 
| 793 | } | 
| 794 |  | 
| 795 | /*! | 
| 796 |     \qmlmethod BarSet::deselectAllBars() | 
| 797 |     Deselects all bars in the set. | 
| 798 |     \note Emits BarSet::selectedBarsChanged. | 
| 799 |     \sa setBarSelected() | 
| 800 |  */ | 
| 801 | /*! | 
| 802 |     Deselects all bars in the set. | 
| 803 |     \note Emits QBarSet::selectedBarsChanged. | 
| 804 |     \sa setBarSelected() | 
| 805 |  */ | 
| 806 | void QBarSet::deselectAllBars() | 
| 807 | { | 
| 808 |     Q_D(QBarSet); | 
| 809 |     bool callSignal = false; | 
| 810 |     for (int i = 0; i < d->m_values.size(); ++i) | 
| 811 |         d->setBarSelected(index: i, selected: false, callSignal); | 
| 812 |  | 
| 813 |     if (callSignal) | 
| 814 |         emit selectedBarsChanged(indexes: selectedBars()); | 
| 815 |     emit update(); | 
| 816 | } | 
| 817 |  | 
| 818 | /*! | 
| 819 |     \qmlmethod BarSet::selectBars(list<int> indexes) | 
| 820 |     Marks multiple bars passed in an \a indexes list as selected. | 
| 821 |     \note Emits BarSet::selectedBarsChanged. | 
| 822 |     \sa setBarSelected() | 
| 823 |  */ | 
| 824 | /*! | 
| 825 |     Marks multiple bars passed in an \a indexes list as selected. | 
| 826 |     \note Emits QBarSet::selectedBarsChanged. | 
| 827 |     \sa setBarSelected() | 
| 828 |  */ | 
| 829 | void QBarSet::selectBars(const QList<qsizetype> &indexes) | 
| 830 | { | 
| 831 |     Q_D(QBarSet); | 
| 832 |     bool callSignal = false; | 
| 833 |     for (const qsizetype &index : indexes) | 
| 834 |         d->setBarSelected(index, selected: true, callSignal); | 
| 835 |  | 
| 836 |     if (callSignal) | 
| 837 |         emit selectedBarsChanged(indexes: selectedBars()); | 
| 838 |     emit update(); | 
| 839 | } | 
| 840 |  | 
| 841 | /*! | 
| 842 |     \qmlmethod BarSet::deselectBars(list<int> indexes) | 
| 843 |     Marks multiple bars passed in an \a indexes list as deselected. | 
| 844 |     \note Emits BarSet::selectedBarsChanged. | 
| 845 |     \sa setBarSelected() | 
| 846 |  */ | 
| 847 | /*! | 
| 848 |     Marks multiple bars passed in an \a indexes list as deselected. | 
| 849 |     \note Emits QBarSet::selectedBarsChanged. | 
| 850 |     \sa setBarSelected() | 
| 851 |  */ | 
| 852 | void QBarSet::deselectBars(const QList<qsizetype> &indexes) | 
| 853 | { | 
| 854 |     Q_D(QBarSet); | 
| 855 |     bool callSignal = false; | 
| 856 |     for (const qsizetype &index : indexes) | 
| 857 |         d->setBarSelected(index, selected: false, callSignal); | 
| 858 |  | 
| 859 |     if (callSignal) | 
| 860 |         emit selectedBarsChanged(indexes: selectedBars()); | 
| 861 |     emit update(); | 
| 862 | } | 
| 863 |  | 
| 864 | /*! | 
| 865 |     \qmlmethod BarSet::toggleSelection(list<int> indexes) | 
| 866 |     Changes the selection state of bars at the given \a indexes to the opposite one. | 
| 867 |     \note Emits BarSet::selectedBarsChanged. | 
| 868 |     \sa setBarSelected() | 
| 869 |  */ | 
| 870 | /*! | 
| 871 |     Changes the selection state of bars at the given \a indexes to the opposite one. | 
| 872 |     \note Emits QBarSet::selectedBarsChanged. | 
| 873 |     \sa setBarSelected() | 
| 874 |  */ | 
| 875 | void QBarSet::toggleSelection(const QList<qsizetype> &indexes) | 
| 876 | { | 
| 877 |     Q_D(QBarSet); | 
| 878 |     bool callSignal = false; | 
| 879 |     for (const qsizetype &index : indexes) | 
| 880 |         d->setBarSelected(index, selected: !isBarSelected(index), callSignal); | 
| 881 |  | 
| 882 |     if (callSignal) | 
| 883 |         emit selectedBarsChanged(indexes: selectedBars()); | 
| 884 |     emit update(); | 
| 885 | } | 
| 886 |  | 
| 887 | /*! | 
| 888 |   Returns a list of bars marked as selected. | 
| 889 |   \sa setBarSelected() | 
| 890 |  */ | 
| 891 | QList<qsizetype> QBarSet::selectedBars() const | 
| 892 | { | 
| 893 |     Q_D(const QBarSet); | 
| 894 |     return QList<qsizetype>(d->m_selectedBars.begin(), d->m_selectedBars.end()); | 
| 895 | } | 
| 896 |  | 
| 897 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | 
| 898 |  | 
| 899 | QBarSetPrivate::QBarSetPrivate(const QString &label) | 
| 900 |     : m_label(label) | 
| 901 |     , m_visualsDirty(true) | 
| 902 | {} | 
| 903 |  | 
| 904 | QBarSetPrivate::~QBarSetPrivate() {} | 
| 905 |  | 
| 906 | void QBarSetPrivate::append(QPointF value) | 
| 907 | { | 
| 908 |     if (isValidValue(point: value)) { | 
| 909 |         Q_Q(QBarSet); | 
| 910 |         m_values.append(t: value); | 
| 911 |         emit q->valueAdded(index: m_values.size() - 1, count: 1); | 
| 912 |     } | 
| 913 | } | 
| 914 |  | 
| 915 | void QBarSetPrivate::append(const QList<QPointF> &values) | 
| 916 | { | 
| 917 |     qsizetype originalIndex = m_values.size(); | 
| 918 |     for (const auto &value : values) { | 
| 919 |         if (isValidValue(point: value)) | 
| 920 |             m_values.append(t: value); | 
| 921 |     } | 
| 922 |     Q_Q(QBarSet); | 
| 923 |     emit q->valueAdded(index: originalIndex, count: values.size()); | 
| 924 | } | 
| 925 |  | 
| 926 | void QBarSetPrivate::append(const QList<qreal> &values) | 
| 927 | { | 
| 928 |     qsizetype originalIndex = m_values.size(); | 
| 929 |     qsizetype index = originalIndex; | 
| 930 |     for (const auto value : values) { | 
| 931 |         if (isValidValue(value)) { | 
| 932 |             m_values.append(t: QPointF(index, value)); | 
| 933 |             index++; | 
| 934 |         } | 
| 935 |     } | 
| 936 |     Q_Q(QBarSet); | 
| 937 |     emit q->valueAdded(index: originalIndex, count: values.size()); | 
| 938 | } | 
| 939 |  | 
| 940 | void QBarSetPrivate::insert(qsizetype index, qreal value) | 
| 941 | { | 
| 942 |     m_values.insert(i: index, t: QPointF(index, value)); | 
| 943 |     Q_Q(QBarSet); | 
| 944 |     emit q->valueAdded(index, count: 1); | 
| 945 | } | 
| 946 |  | 
| 947 | void QBarSetPrivate::insert(qsizetype index, QPointF value) | 
| 948 | { | 
| 949 |     m_values.insert(i: index, t: value); | 
| 950 |     Q_Q(QBarSet); | 
| 951 |     emit q->valueAdded(index, count: 1); | 
| 952 | } | 
| 953 |  | 
| 954 | qsizetype QBarSetPrivate::remove(qsizetype index, qsizetype count) | 
| 955 | { | 
| 956 |     qsizetype removeCount = count; | 
| 957 |  | 
| 958 |     if ((index < 0) || (m_values.size() == 0)) | 
| 959 |         return 0; // Invalid index or not values in list, remove nothing. | 
| 960 |     else if ((index + count) > m_values.size()) | 
| 961 |         removeCount = m_values.size() - index; // Trying to remove more items than list has. Limit amount to be removed. | 
| 962 |  | 
| 963 |     int c = 0; | 
| 964 |     while (c < removeCount) { | 
| 965 |         m_values.removeAt(i: index); | 
| 966 |         c++; | 
| 967 |     } | 
| 968 |  | 
| 969 |     bool callSignal = false; | 
| 970 |     if (!m_selectedBars.empty()) { | 
| 971 |         QSet<qsizetype> selectedAfterRemoving; | 
| 972 |  | 
| 973 |         for (const qsizetype &selectedBarIndex : std::as_const(t&: m_selectedBars)) { | 
| 974 |             if (selectedBarIndex < index) { | 
| 975 |                 selectedAfterRemoving << selectedBarIndex; | 
| 976 |             } else if (selectedBarIndex >= index + removeCount) { | 
| 977 |                 selectedAfterRemoving << selectedBarIndex - removeCount; | 
| 978 |                 callSignal = true; | 
| 979 |             } else { | 
| 980 |                 callSignal = true; | 
| 981 |             } | 
| 982 |         } | 
| 983 |  | 
| 984 |         m_selectedBars = selectedAfterRemoving; | 
| 985 |     } | 
| 986 |     Q_Q(QBarSet); | 
| 987 |     emit q->valueRemoved(index, count: removeCount); | 
| 988 |     if (callSignal) | 
| 989 |         emit q->selectedBarsChanged(indexes: q->selectedBars()); | 
| 990 |  | 
| 991 |     return removeCount; | 
| 992 | } | 
| 993 |  | 
| 994 | void QBarSetPrivate::replace(qsizetype index, qreal value) | 
| 995 | { | 
| 996 |     if (index < 0 || index >= m_values.size()) | 
| 997 |         return; | 
| 998 |  | 
| 999 |     m_values.replace(i: index, t: QPointF(index, value)); | 
| 1000 | } | 
| 1001 |  | 
| 1002 | qreal QBarSetPrivate::pos(qsizetype index) const | 
| 1003 | { | 
| 1004 |     if (index < 0 || index >= m_values.size()) | 
| 1005 |         return 0; | 
| 1006 |     return m_values.at(i: index).x(); | 
| 1007 | } | 
| 1008 |  | 
| 1009 | qreal QBarSetPrivate::value(qsizetype index) const | 
| 1010 | { | 
| 1011 |     if (index < 0 || index >= m_values.size()) | 
| 1012 |         return 0; | 
| 1013 |     return m_values.at(i: index).y(); | 
| 1014 | } | 
| 1015 |  | 
| 1016 | void QBarSetPrivate::setBarSelected(qsizetype index, bool selected, bool &callSignal) | 
| 1017 | { | 
| 1018 |     if (index < 0 || index > m_values.size() - 1) | 
| 1019 |         return; | 
| 1020 |  | 
| 1021 |     if (selected) { | 
| 1022 |         if (!isBarSelected(index)) { | 
| 1023 |             m_selectedBars << index; | 
| 1024 |             callSignal = true; | 
| 1025 |         } | 
| 1026 |     } else { | 
| 1027 |         if (isBarSelected(index)) { | 
| 1028 |             m_selectedBars.remove(value: index); | 
| 1029 |             callSignal = true; | 
| 1030 |         } | 
| 1031 |     } | 
| 1032 |  | 
| 1033 |     if (callSignal) | 
| 1034 |         setVisualsDirty(true); | 
| 1035 | } | 
| 1036 |  | 
| 1037 | bool QBarSetPrivate::isBarSelected(qsizetype index) const | 
| 1038 | { | 
| 1039 |     return m_selectedBars.contains(value: index); | 
| 1040 | } | 
| 1041 |  | 
| 1042 | QT_END_NAMESPACE | 
| 1043 |  | 
| 1044 | #include "moc_qbarset.cpp" | 
| 1045 |  |