| 1 | // Copyright (C) 2023 The Qt Company Ltd. | 
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only | 
| 3 |  | 
| 4 | #include <QtGraphs/qabstractseries.h> | 
| 5 | #include <QtGraphs/qbarseries.h> | 
| 6 | #include <QtGraphs/qbarset.h> | 
| 7 | #include <private/qabstractseries_p.h> | 
| 8 | #include <private/qbarseries_p.h> | 
| 9 | #include <private/qbarset_p.h> | 
| 10 | #include <private/qgraphsview_p.h> | 
| 11 |  | 
| 12 | QT_BEGIN_NAMESPACE | 
| 13 |  | 
| 14 | /*! | 
| 15 |     \class QBarSeries | 
| 16 |     \inmodule QtGraphs | 
| 17 |     \ingroup graphs_2D | 
| 18 |     \brief The QBarSeries class presents data in bar graphs. | 
| 19 |  | 
| 20 |     This class draws data by default as a series of bars grouped by category, | 
| 21 |     with one bar per category from each bar set added to the series. | 
| 22 |     It also supports horizontal bars and grouping bars as stacked. | 
| 23 |  | 
| 24 |     A bar series needs the GraphsView x-axis to be set to a BarCategoryAxis and | 
| 25 |     the y-axis set to ValueAxis. | 
| 26 |  | 
| 27 |     \sa QBarSet, QAbstractSeries | 
| 28 | */ | 
| 29 | /*! | 
| 30 |     \qmltype BarSeries | 
| 31 |     \nativetype QBarSeries | 
| 32 |     \inqmlmodule QtGraphs | 
| 33 |     \ingroup graphs_qml_2D | 
| 34 |     \inherits AbstractSeries | 
| 35 |  | 
| 36 |     \brief Presents data in bar graphs. | 
| 37 |  | 
| 38 |     Draws data by default as a series of bars grouped by category, | 
| 39 |     with one bar per category from each bar set added to the series. | 
| 40 |     It also supports horizontal bars and grouping bars as stacked. | 
| 41 | */ | 
| 42 |  | 
| 43 | /*! | 
| 44 |     \property QBarSeries::barWidth | 
| 45 |     \brief The width of the bars of the series. | 
| 46 |  | 
| 47 |     The unit of width is the unit of the x-axis. The minimum width for bars is zero, and negative | 
| 48 |     values are treated as zero. Setting the width to zero means that the width of the bar on the | 
| 49 |     screen is one pixel regardless of the scale of the x-axis. Bars wider than zero are scaled | 
| 50 |     using the x-axis scale. | 
| 51 |  | 
| 52 |     By default, the barWidth is 0.5 (bars will take 50% of the available width). | 
| 53 |     The valid values range from 0.0 (0%) to 1.0 (100%). | 
| 54 |  | 
| 55 |     \note When used with QBarSeries, this value specifies the width of a group of bars instead of | 
| 56 |     that of a single bar. | 
| 57 |     \sa QBarSeries | 
| 58 | */ | 
| 59 |  | 
| 60 | /*! | 
| 61 |     \enum QBarSeries::BarsType | 
| 62 |  | 
| 63 |     This enum value describes the type of the bar series: | 
| 64 |  | 
| 65 |     \value Groups Bar sets are grouped by category. | 
| 66 |     \value Stacked Bar sets are stacked after each other by category. | 
| 67 |     \value StackedPercent Bar sets are stacked after each other by category. | 
| 68 |            The segment size corresponds to the percentage of the segment value | 
| 69 |            compared with the total value of all segments in the stack. | 
| 70 | */ | 
| 71 | /*! | 
| 72 |     \property QBarSeries::barsType | 
| 73 |     \brief The type of the bar series. | 
| 74 | */ | 
| 75 | /*! | 
| 76 |     \qmlproperty enumeration BarSeries::barsType | 
| 77 |  | 
| 78 |     The type of the bar series: | 
| 79 |  | 
| 80 |     \value BarSeries.BarsType.Groups | 
| 81 |         Bar sets are grouped by category. This is the default value. | 
| 82 |     \value BarSeries.BarsType.Stacked | 
| 83 |         Bar sets are stacked after each other by category. | 
| 84 |     \value BarSeries.BarsType.StackedPercent | 
| 85 |         Bar sets are stacked after each other by category. The segment size corresponds | 
| 86 |         to the percentage of the segment value compared with the total value of all | 
| 87 |         segments in the stack. | 
| 88 | */ | 
| 89 |  | 
| 90 | /*! | 
| 91 |     \qmlproperty real BarSeries::barWidth | 
| 92 |     The unit of width is the unit of the x-axis. The minimum width for bars is zero, and negative | 
| 93 |     values are treated as zero. Setting the width to zero means that the width of the bar on the | 
| 94 |     screen is one pixel regardless of the scale of the x-axis. Bars wider than zero are scaled | 
| 95 |     using the x-axis scale. | 
| 96 |  | 
| 97 |     By default, the barWidth is 0.5 (bars will take 50% of the available width). | 
| 98 |     The valid values range from 0.0 (0%) to 1.0 (100%). | 
| 99 |  | 
| 100 |     \note When used with the BarSeries type, this value specifies the width of a group of bars | 
| 101 |     instead of that of a single bar. | 
| 102 | */ | 
| 103 |  | 
| 104 | /*! | 
| 105 |     \property QBarSeries::count | 
| 106 |     \brief The number of bar sets in a bar series. | 
| 107 | */ | 
| 108 | /*! | 
| 109 |     \qmlproperty int BarSeries::count | 
| 110 |     The number of bar sets in a bar series. | 
| 111 | */ | 
| 112 |  | 
| 113 | /*! | 
| 114 |     \property QBarSeries::labelsVisible | 
| 115 |     \brief The visibility of the labels in a bar series. | 
| 116 |     The default label visibility is \c false. | 
| 117 | */ | 
| 118 | /*! | 
| 119 |     \qmlproperty bool BarSeries::labelsVisible | 
| 120 |     The visibility of the labels in a bar series. | 
| 121 |     The default label visibility is \c false. | 
| 122 | */ | 
| 123 |  | 
| 124 | /*! | 
| 125 |     \property QBarSeries::labelsFormat | 
| 126 |     \brief The format used for showing labels in a bar series. | 
| 127 |  | 
| 128 |     QBarSeries supports the following format tag: | 
| 129 |     \table | 
| 130 |     \row | 
| 131 |     \li @value      \li The value of the bar | 
| 132 |     \endtable | 
| 133 |  | 
| 134 |     For example, the following usage of the format tags would produce labels that show the value | 
| 135 |     followed by the unit (u): | 
| 136 |     \code | 
| 137 |     series->setLabelsFormat("@value u"); | 
| 138 |     \endcode | 
| 139 |  | 
| 140 |     By default, the labels show the value of the bar. For the percent bar series, \e % is added | 
| 141 |     after the value. The labels are shown on the plot area, if the bars are close to each other, | 
| 142 |     the labels may overlap. | 
| 143 |  | 
| 144 |     \sa labelsVisible, labelsPosition, labelsPrecision | 
| 145 | */ | 
| 146 | /*! | 
| 147 |     \qmlproperty string BarSeries::labelsFormat | 
| 148 |     The format used for showing labels in a bar series. | 
| 149 |  | 
| 150 |     \sa QBarSeries::labelsFormat, labelsVisible, labelsPosition | 
| 151 | */ | 
| 152 |  | 
| 153 | /*! | 
| 154 |     \enum QBarSeries::LabelsPosition | 
| 155 |  | 
| 156 |     This enum value describes the position of the data value labels: | 
| 157 |  | 
| 158 |     \value Center Label is located in the center of the bar. | 
| 159 |     \value InsideEnd Label is located inside the bar at the top. | 
| 160 |     \value InsideBase Label is located inside the bar at the bottom. | 
| 161 |     \value OutsideEnd Label is located outside the bar at the top. | 
| 162 | */ | 
| 163 |  | 
| 164 | /*! | 
| 165 |     \property QBarSeries::labelsPosition | 
| 166 |     \brief The position of value labels. | 
| 167 |  | 
| 168 |     \sa labelsVisible, labelsFormat | 
| 169 | */ | 
| 170 | /*! | 
| 171 |     \qmlproperty enumeration BarSeries::labelsPosition | 
| 172 |  | 
| 173 |     The position of the data value labels: | 
| 174 |  | 
| 175 |     \value  BarSeries.LabelsPosition.Center | 
| 176 |         Label is located in the center of the bar. | 
| 177 |     \value  BarSeries.LabelsPosition.InsideEnd | 
| 178 |         Label is located inside the bar at the top. | 
| 179 |     \value  BarSeries.LabelsPosition.InsideBase | 
| 180 |         Label is located inside the bar at the bottom. | 
| 181 |     \value  BarSeries.LabelsPosition.OutsideEnd | 
| 182 |         Label is located outside the bar at the top. | 
| 183 |  | 
| 184 |     \sa labelsVisible, labelsFormat | 
| 185 | */ | 
| 186 |  | 
| 187 | /*! | 
| 188 |     \property QBarSeries::labelsMargin | 
| 189 |     \brief The margin of the value labels in pixels. | 
| 190 |  | 
| 191 |     This margin from side is used when \l labelsPosition is set to something else | 
| 192 |     than \c LabelsPosition.Center. The default value is \c 0. | 
| 193 | */ | 
| 194 | /*! | 
| 195 |     \qmlproperty real BarSeries::labelsMargin | 
| 196 |     The margin of the value labels in pixels. | 
| 197 |  | 
| 198 |     This margin from side is used when \l labelsPosition is set to something else | 
| 199 |     than \c LabelsPosition.Center. The default value is \c 0. | 
| 200 | */ | 
| 201 |  | 
| 202 | /*! | 
| 203 |     \property QBarSeries::labelsAngle | 
| 204 |     \brief The angle of the value labels in degrees. | 
| 205 | */ | 
| 206 | /*! | 
| 207 |     \qmlproperty real BarSeries::labelsAngle | 
| 208 |     The angle of the value labels in degrees. | 
| 209 | */ | 
| 210 |  | 
| 211 | /*! | 
| 212 |     \property QBarSeries::labelsPrecision | 
| 213 |     \brief The maximum amount of significant digits shown in value labels. | 
| 214 |  | 
| 215 |     Default value is 6. | 
| 216 | */ | 
| 217 | /*! | 
| 218 |     \qmlproperty real BarSeries::labelsPrecision | 
| 219 |     The maximum amount of significant digits shown in value labels. | 
| 220 |  | 
| 221 |     Default value is 6. | 
| 222 | */ | 
| 223 |  | 
| 224 | /*! | 
| 225 |     \property QBarSeries::barDelegate | 
| 226 |     \brief A custom QML component used for visualizing each of the bars. | 
| 227 |     Instance of this component is created for each of the bar. | 
| 228 |     When this is not defined, a default rectangle visualization for bars is used. | 
| 229 |  | 
| 230 |     The dynamic properties available for this component are: | 
| 231 |  | 
| 232 |     \table | 
| 233 |     \header | 
| 234 |         \li Type | 
| 235 |         \li Name | 
| 236 |         \li Description | 
| 237 |     \row | 
| 238 |         \li QColor | 
| 239 |         \li barColor | 
| 240 |         \li The fill color of the bar. This value comes either from the \l QGraphsTheme | 
| 241 |         or from \l{QBarSet::color} if the \l QBarSet overrides the color. | 
| 242 |     \row | 
| 243 |         \li QColor | 
| 244 |         \li barBorderColor | 
| 245 |         \li The border color of the bar. This value comes either from the \l QGraphsTheme | 
| 246 |         or from \l{QBarSet::borderColor} if the \l QBarSet overrides the color. | 
| 247 |     \row | 
| 248 |         \li qreal | 
| 249 |         \li barBorderWidth | 
| 250 |         \li The width of the bar border. This value comes either from the \l QGraphsTheme | 
| 251 |         or from \l{QBarSet::borderWidth} if the \l QBarSet overrides the width. | 
| 252 |     \row | 
| 253 |         \li qreal | 
| 254 |         \li barValue | 
| 255 |         \li The value of the bar. This value comes from the \l{QBarSet::values}. | 
| 256 |     \row | 
| 257 |         \li QString | 
| 258 |         \li barLabel | 
| 259 |         \li The label of the bar. This value comes from the \l{QBarSet::label}. | 
| 260 |     \row | 
| 261 |         \li bool | 
| 262 |         \li barSelected | 
| 263 |         \li This value is true when the bar is selected, meaning that the bar index | 
| 264 |         is in \l{QBarSet::selectedBars}. | 
| 265 |     \endtable | 
| 266 |  | 
| 267 |     To use any of these, add property with the defined name into your custom component. | 
| 268 |     For example \c{"property color barColor"} and \c{"property real barValue"}. | 
| 269 | */ | 
| 270 | /*! | 
| 271 |     \qmlproperty Component BarSeries::barDelegate | 
| 272 |     A custom QML component used for visualizing each of the bars. | 
| 273 |     Instance of this component is created for each of the bar. | 
| 274 |     When this is not defined, a default rectangle visualization for bars is used. | 
| 275 |  | 
| 276 |     The dynamic properties available for this component are: | 
| 277 |  | 
| 278 |     \table | 
| 279 |     \header | 
| 280 |         \li Type | 
| 281 |         \li Name | 
| 282 |         \li Description | 
| 283 |     \row | 
| 284 |         \li color | 
| 285 |         \li barColor | 
| 286 |         \li The fill color of the bar. This value comes either from the \l GraphsTheme | 
| 287 |         or from \l{BarSet::color} if the \l BarSet overrides the color. | 
| 288 |     \row | 
| 289 |         \li color | 
| 290 |         \li barBorderColor | 
| 291 |         \li The border color of the bar. This value comes either from the \l GraphsTheme | 
| 292 |         or from \l{BarSet::borderColor} if the \l BarSet overrides the color. | 
| 293 |     \row | 
| 294 |         \li real | 
| 295 |         \li barBorderWidth | 
| 296 |         \li The width of the bar border. This value comes either from the \l GraphsTheme | 
| 297 |         or from \l{BarSet::borderWidth} if the \l BarSet overrides the width. | 
| 298 |     \row | 
| 299 |         \li real | 
| 300 |         \li barValue | 
| 301 |         \li The value of the bar. This value comes from the \l{BarSet::values}. | 
| 302 |     \row | 
| 303 |         \li string | 
| 304 |         \li barLabel | 
| 305 |         \li The label of the bar. This value comes from the \l{BarSet::label}. | 
| 306 |     \row | 
| 307 |         \li bool | 
| 308 |         \li barSelected | 
| 309 |         \li This value is true when the bar is selected, meaning that the bar index | 
| 310 |         is in \l{BarSet::selectedBars}. | 
| 311 |     \endtable | 
| 312 |  | 
| 313 |     To use any of these, add property with the defined name into your custom component. | 
| 314 |     For example \c{"property color barColor"} and \c{"property real barValue"}. | 
| 315 | */ | 
| 316 |  | 
| 317 | /*! | 
| 318 |     \property QBarSeries::barSets | 
| 319 |     \brief A list of sets added to the series. | 
| 320 |  */ | 
| 321 | /*! | 
| 322 |     \qmlproperty list<BarSet> BarSeries::barSets | 
| 323 |     A list of sets added to the series. | 
| 324 | */ | 
| 325 |  | 
| 326 | /*! | 
| 327 |     \fn void QBarSeries::updatedBars() | 
| 328 |     This signal is emitted when bars are updated. | 
| 329 | */ | 
| 330 |  | 
| 331 | /*! | 
| 332 |     \fn void QBarSeries::labelsVisibleChanged(bool visible) | 
| 333 |     This signal is emitted when the labels' visibility changes to \a visible. | 
| 334 |     \sa labelsVisible(), setLabelsVisible() | 
| 335 | */ | 
| 336 |  | 
| 337 | /*! | 
| 338 |     \fn void QBarSeries::barsetsAdded(const QList<QBarSet *> &sets) | 
| 339 |     This signal is emitted when the bar sets specified by \a sets are added to the series. | 
| 340 |     \sa append(), insert() | 
| 341 | */ | 
| 342 | /*! | 
| 343 |     \qmlsignal BarSeries::barsetsAdded() | 
| 344 |     This signal is emitted when bar sets are added to the series. | 
| 345 | */ | 
| 346 |  | 
| 347 | /*! | 
| 348 |     \fn void QBarSeries::barsetsRemoved(const QList<QBarSet *> &sets) | 
| 349 |     This signal is emitted when the bar sets specified by \a sets are removed from the series. | 
| 350 |     \sa remove() | 
| 351 | */ | 
| 352 | /*! | 
| 353 |     \qmlsignal BarSeries::barsetsRemoved() | 
| 354 |     This signal is emitted when bar sets are removed from the series. | 
| 355 | */ | 
| 356 |  | 
| 357 | /*! | 
| 358 |     \fn void QBarSeries::setValueChanged(qsizetype index, QBarSet *barset) | 
| 359 |     This signal is emitted when a barset's value is changed. \a index is the index of | 
| 360 |     the barset in the series. The \a barset is a pointer to the changed set. | 
| 361 | */ | 
| 362 | /*! | 
| 363 |     \fn void QBarSeries::setValueAdded(qsizetype index, qsizetype count, QBarSet *barset) | 
| 364 |     This signal is emitted when a barset's value is changed. \a index is the index of | 
| 365 |     the barset in the series. The number of the added values is indicated \a count. | 
| 366 |     The \a barset is a pointer to the changed set. | 
| 367 | */ | 
| 368 | /*! | 
| 369 |     \fn void QBarSeries::setValueRemoved(qsizetype index, qsizetype count, QBarSet *barset) | 
| 370 |     This signal is emitted when a barset's value is changed. \a index is the index of | 
| 371 |     the barset in the series. The number of the removed values is indicated \a count. | 
| 372 |     The \a barset is a pointer to the changed set. | 
| 373 | */ | 
| 374 |  | 
| 375 | /*! | 
| 376 |     \qmlmethod BarSet BarSeries::at(int index) | 
| 377 |     Returns the bar set at \a index. Returns null if the index is not valid. | 
| 378 | */ | 
| 379 |  | 
| 380 | /*! | 
| 381 |     \qmlmethod BarSet BarSeries::insert(int index, string label, VariantList values) | 
| 382 |     Adds a new bar set with \a label and \a values to \a index. \a values can be a list | 
| 383 |     of real values or a list of XYPoint types. | 
| 384 |  | 
| 385 |     If the index value is equal to or less than zero, the new bar set is prepended to the bar | 
| 386 |     series. If the index value is equal to or greater than the number of bar sets in the bar | 
| 387 |     series, the new bar set is appended to the bar series. | 
| 388 |  | 
| 389 |     \sa append() | 
| 390 | */ | 
| 391 |  | 
| 392 | /*! | 
| 393 |     \qmlmethod bool BarSeries::remove(BarSet barset) | 
| 394 |     Removes the bar set specified by \a barset from the series. Returns \c true if successful, | 
| 395 |     \c false otherwise. | 
| 396 | */ | 
| 397 |  | 
| 398 | /*! | 
| 399 |     \qmlmethod BarSeries::clear() | 
| 400 |     Removes all bar sets from the series. | 
| 401 | */ | 
| 402 |  | 
| 403 | /*! | 
| 404 |     \qmlmethod bool BarSeries::replace(int index, BarSet barset) | 
| 405 |     Replaces the bar set at the position specified by \a index from the series and replaces it | 
| 406 |     with \a barset. Returns \c true if successful, \c false otherwise. | 
| 407 | */ | 
| 408 |  | 
| 409 | /*! | 
| 410 |     \qmlmethod Barset BarSeries::at(int index) | 
| 411 |     Returns the bar set specified by \a index from the series. Returns \c null otherwise. | 
| 412 | */ | 
| 413 |  | 
| 414 | /*! | 
| 415 |     \qmlmethod int BarSeries::find(BarSet barset) | 
| 416 |     Returns the index of the bar set specified by \a barset from the series. Returns \c -1 if | 
| 417 |     not found. | 
| 418 | */ | 
| 419 |  | 
| 420 | /*! | 
| 421 |     \qmlmethod BarSeries::removeMultiple(int index, int count) | 
| 422 |     Removes a range of bar sets as specified by the \a index and \a count. The call | 
| 423 |     traverses over all sets even if removal of one fails. | 
| 424 | */ | 
| 425 |  | 
| 426 | /*! | 
| 427 |     \qmlmethod bool BarSeries::remove(int index) | 
| 428 |     Removes the bar set specified by \a index from the series. Returns \c true if the | 
| 429 |     removal was successful, \c false otherwise. | 
| 430 | */ | 
| 431 |  | 
| 432 | /*! | 
| 433 |     \qmlmethod bool BarSeries::replace(BarSet oldSet, BarSet newSet) | 
| 434 |     Replaces the bar set specified by \a oldSet with newSet. Returns \c true if the | 
| 435 |     removal was successful, \c false otherwise. \a oldSet is destroyed if this  | 
| 436 |     is successful. | 
| 437 | */ | 
| 438 |  | 
| 439 | /*! | 
| 440 |     \qmlmethod bool BarSeries::replace(list<BarSet> sets) | 
| 441 |     Completely replaces all current bar set with \a sets. The size does not need | 
| 442 |     to match. Returns false if any of the bar set in \a sets are invalid. | 
| 443 | */ | 
| 444 |  | 
| 445 | /*! | 
| 446 |     \internal | 
| 447 | */ | 
| 448 |  | 
| 449 | /*! | 
| 450 |     Constructs an empty bar series that is a QObject and a child of \a parent. | 
| 451 | */ | 
| 452 | QBarSeries::QBarSeries(QObject *parent) | 
| 453 |     : QAbstractSeries(*(new QBarSeriesPrivate()), parent) | 
| 454 | {} | 
| 455 |  | 
| 456 | QBarSeries::~QBarSeries() {} | 
| 457 |  | 
| 458 | QBarSeries::QBarSeries(QBarSeriesPrivate &dd, QObject *parent) | 
| 459 |     : QAbstractSeries(dd, parent) | 
| 460 | {} | 
| 461 |  | 
| 462 | /*! | 
| 463 |     Returns the bar series. | 
| 464 | */ | 
| 465 | QAbstractSeries::SeriesType QBarSeries::type() const | 
| 466 | { | 
| 467 |     return QAbstractSeries::SeriesType::Bar; | 
| 468 | } | 
| 469 |  | 
| 470 | /*! | 
| 471 |     \property QBarSeries::seriesColors | 
| 472 |     \brief The list of base colors to be used for all the objects in the series. | 
| 473 |  | 
| 474 |     If there are more series than colors, the color list wraps and starts again | 
| 475 |     with the first color in the list. If this is not set (default), colors | 
| 476 |     from the \l{QGraphsTheme::seriesColors} will be used. | 
| 477 | */ | 
| 478 | /*! | 
| 479 |     \qmlproperty list<color> BarSeries::seriesColors | 
| 480 |     The list of base colors to be used for all the objects in the series. | 
| 481 |  | 
| 482 |     If there are more series than colors, the color list wraps and starts again | 
| 483 |     with the first color in the list. If this is not set (default), colors | 
| 484 |     from the \l{GraphsTheme::seriesColors} will be used. | 
| 485 | */ | 
| 486 | QList<QColor> QBarSeries::seriesColors() const | 
| 487 | { | 
| 488 |     Q_D(const QBarSeries); | 
| 489 |     return d->m_seriesColors; | 
| 490 | } | 
| 491 |  | 
| 492 | void QBarSeries::setSeriesColors(const QList<QColor> &newSeriesColors) | 
| 493 | { | 
| 494 |     Q_D(QBarSeries); | 
| 495 |     if (d->m_seriesColors == newSeriesColors) | 
| 496 |         return; | 
| 497 |     d->m_seriesColors = newSeriesColors; | 
| 498 |     emit seriesColorsChanged(); | 
| 499 |     emit update(); | 
| 500 | } | 
| 501 |  | 
| 502 | /*! | 
| 503 |     \property QBarSeries::borderColors | 
| 504 |     \brief The list of border colors to be used for all the objects in the series. | 
| 505 |  | 
| 506 |     If there are more series than colors, the color list wraps and starts again | 
| 507 |     with the first color in the list. If this is not set (default), colors | 
| 508 |     from the \l{QGraphsTheme::borderColors} will be used. | 
| 509 | */ | 
| 510 | /*! | 
| 511 |     \qmlproperty list<color> BarSeries::borderColors | 
| 512 |     The list of border colors to be used for all the objects in the series. | 
| 513 |  | 
| 514 |     If there are more series than colors, the color list wraps and starts again | 
| 515 |     with the first color in the list. If this is not set (default), colors | 
| 516 |     from the \l{GraphsTheme::borderColors} will be used. | 
| 517 | */ | 
| 518 | QList<QColor> QBarSeries::borderColors() const | 
| 519 | { | 
| 520 |     Q_D(const QBarSeries); | 
| 521 |     return d->m_borderColors; | 
| 522 | } | 
| 523 |  | 
| 524 | void QBarSeries::setBorderColors(const QList<QColor> &newBorderColors) | 
| 525 | { | 
| 526 |     Q_D(QBarSeries); | 
| 527 |     if (d->m_borderColors == newBorderColors) | 
| 528 |         return; | 
| 529 |     d->m_borderColors = newBorderColors; | 
| 530 |     emit borderColorsChanged(); | 
| 531 |     emit update(); | 
| 532 | } | 
| 533 |  | 
| 534 | void QBarSeries::setBarsType(QBarSeries::BarsType type) | 
| 535 | { | 
| 536 |     Q_D(QBarSeries); | 
| 537 |     if (d->m_barsType != type) { | 
| 538 |         d->m_barsType = type; | 
| 539 |         emit barsTypeChanged(type); | 
| 540 |         emit update(); | 
| 541 |     } | 
| 542 | } | 
| 543 |  | 
| 544 | QBarSeries::BarsType QBarSeries::barsType() const | 
| 545 | { | 
| 546 |     Q_D(const QBarSeries); | 
| 547 |     return d->m_barsType; | 
| 548 | } | 
| 549 |  | 
| 550 | /*! | 
| 551 |     Sets the width of the bars of the series to \a width. | 
| 552 | */ | 
| 553 | void QBarSeries::setBarWidth(qreal width) | 
| 554 | { | 
| 555 |     Q_D(QBarSeries); | 
| 556 |     if (d->barWidth() != width) { | 
| 557 |         d->setBarWidth(width); | 
| 558 |         emit barWidthChanged(); | 
| 559 |     } | 
| 560 | } | 
| 561 |  | 
| 562 | /*! | 
| 563 |     Returns the width of the bars of the series. | 
| 564 |     \sa setBarWidth() | 
| 565 | */ | 
| 566 | qreal QBarSeries::barWidth() const | 
| 567 | { | 
| 568 |     Q_D(const QBarSeries); | 
| 569 |     return d->barWidth(); | 
| 570 | } | 
| 571 |  | 
| 572 | /*! | 
| 573 |     Adds a set of bars specified by \a set to the bar series and takes ownership of it. If the set | 
| 574 |     is null or it already belongs to the series, it will not be appended. | 
| 575 |     Returns \c true if appending succeeded. | 
| 576 | */ | 
| 577 | bool QBarSeries::append(QBarSet *set) | 
| 578 | { | 
| 579 |     Q_D(QBarSeries); | 
| 580 |     bool success = d->append(set); | 
| 581 |     if (success) { | 
| 582 |         QList<QBarSet *> sets; | 
| 583 |         sets.append(t: set); | 
| 584 |         set->setParent(this); | 
| 585 |         QObject::connect(sender: set, signal: &QBarSet::update, context: this, slot: &QBarSeries::update); | 
| 586 |         emit barsetsAdded(sets); | 
| 587 |         emit barSetsChanged(); | 
| 588 |         emit countChanged(); | 
| 589 |         emit update(); | 
| 590 |     } | 
| 591 |     return success; | 
| 592 | } | 
| 593 |  | 
| 594 | /*! | 
| 595 |     Removes the bar set specified by \a set from the series and permanently deletes it if | 
| 596 |     the removal succeeds. Returns \c true if the set was removed. | 
| 597 | */ | 
| 598 | bool QBarSeries::remove(QBarSet *set) | 
| 599 | { | 
| 600 |     Q_D(QBarSeries); | 
| 601 |     bool success = d->remove(set); | 
| 602 |     if (success) { | 
| 603 |         QList<QBarSet *> sets; | 
| 604 |         sets.append(t: set); | 
| 605 |         set->setParent(0); | 
| 606 |         QObject::disconnect(sender: set, signal: &QBarSet::update, receiver: this, slot: &QBarSeries::update); | 
| 607 |         emit barsetsRemoved(sets); | 
| 608 |         emit barSetsChanged(); | 
| 609 |         emit countChanged(); | 
| 610 |         emit update(); | 
| 611 |         delete set; | 
| 612 |         set = 0; | 
| 613 |     } | 
| 614 |     return success; | 
| 615 | } | 
| 616 |  | 
| 617 | /*! | 
| 618 |     Takes a single \a set from the series. Does not delete the bar set object. | 
| 619 |     \note The series remains the barset's parent object. You must set the | 
| 620 |     parent object to take full ownership. | 
| 621 |  | 
| 622 |     Returns \c true if the take operation succeeds. | 
| 623 | */ | 
| 624 | bool QBarSeries::take(QBarSet *set) | 
| 625 | { | 
| 626 |     Q_D(QBarSeries); | 
| 627 |     bool success = d->remove(set); | 
| 628 |     if (success) { | 
| 629 |         QList<QBarSet *> sets; | 
| 630 |         sets.append(t: set); | 
| 631 |         QObject::disconnect(sender: set, signal: &QBarSet::update, receiver: this, slot: &QBarSeries::update); | 
| 632 |         emit barsetsRemoved(sets); | 
| 633 |         emit barSetsChanged(); | 
| 634 |         emit countChanged(); | 
| 635 |         emit update(); | 
| 636 |     } | 
| 637 |     return success; | 
| 638 | } | 
| 639 |  | 
| 640 | /*! | 
| 641 |     Adds a list of bar sets specified by \a sets to a bar series and takes ownership of the sets. | 
| 642 |     Returns \c true if all sets were appended successfully. If any of the sets is null or was | 
| 643 |     previously appended to the series, nothing is appended and this function returns \c false. | 
| 644 |     If any of the sets appears in the list more than once, nothing is appended and this function | 
| 645 |     returns \c false. | 
| 646 | */ | 
| 647 | bool QBarSeries::append(const QList<QBarSet *> &sets) | 
| 648 | { | 
| 649 |     Q_D(QBarSeries); | 
| 650 |     if (!d->append(sets)) | 
| 651 |         return false; | 
| 652 |  | 
| 653 |     for (auto *set : sets) { | 
| 654 |         set->setParent(this); | 
| 655 |         QObject::connect(sender: set, signal: &QBarSet::update, context: this, slot: &QBarSeries::update); | 
| 656 |     } | 
| 657 |  | 
| 658 |     emit barsetsAdded(sets); | 
| 659 |     emit barSetsChanged(); | 
| 660 |     emit countChanged(); | 
| 661 |     emit update(); | 
| 662 |     return true; | 
| 663 | } | 
| 664 |  | 
| 665 | /*! | 
| 666 |     Inserts a bar set specified by \a set to a series at the position specified by \a index | 
| 667 |     and takes ownership of the set. If the set is null or already belongs to the series, it will | 
| 668 |     not be appended. Returns \c true if inserting succeeds. | 
| 669 | */ | 
| 670 | bool QBarSeries::insert(qsizetype index, QBarSet *set) | 
| 671 | { | 
| 672 |     Q_D(QBarSeries); | 
| 673 |     bool success = d->insert(index, set); | 
| 674 |     if (success) { | 
| 675 |         QList<QBarSet *> sets; | 
| 676 |         sets.append(t: set); | 
| 677 |         QObject::connect(sender: set, signal: &QBarSet::update, context: this, slot: &QBarSeries::update); | 
| 678 |         emit barsetsAdded(sets); | 
| 679 |         emit barSetsChanged(); | 
| 680 |         emit countChanged(); | 
| 681 |         emit update(); | 
| 682 |     } | 
| 683 |     return success; | 
| 684 | } | 
| 685 |  | 
| 686 | /*! | 
| 687 |     Removes all bar sets from the series and permanently deletes them. | 
| 688 | */ | 
| 689 | void QBarSeries::clear() | 
| 690 | { | 
| 691 |     Q_D(QBarSeries); | 
| 692 |     const QList<QBarSet *> sets = barSets(); | 
| 693 |     bool success = d->remove(sets); | 
| 694 |     if (success) { | 
| 695 |         emit barsetsRemoved(sets); | 
| 696 |         emit barSetsChanged(); | 
| 697 |         emit countChanged(); | 
| 698 |         for (QBarSet *set : sets) { | 
| 699 |             QObject::disconnect(sender: set, signal: &QBarSet::update, receiver: this, slot: &QBarSeries::update); | 
| 700 |             set->deleteLater(); | 
| 701 |         } | 
| 702 |         emit update(); | 
| 703 |     } | 
| 704 | } | 
| 705 |  | 
| 706 | /*! | 
| 707 |     Replaces the BarSet which is present at \a index with \a set. | 
| 708 |     The original BarSet will be permanently deleted. | 
| 709 | */ | 
| 710 | void QBarSeries::replace(qsizetype index, QBarSet *set) | 
| 711 | { | 
| 712 |     Q_D(QBarSeries); | 
| 713 |  | 
| 714 |     if (d->m_barSets.size() <= index) | 
| 715 |         return; | 
| 716 |     if (!set) | 
| 717 |         return; | 
| 718 |     if (index < 0) | 
| 719 |         index = 0; | 
| 720 |  | 
| 721 |     remove(set: d->m_barSets[index]); | 
| 722 |     d->insert(index, set); | 
| 723 |  | 
| 724 |     QList<QBarSet *> sets; | 
| 725 |     sets.append(t: set); | 
| 726 |     QObject::connect(sender: set, signal: &QBarSet::update, context: this, slot: &QBarSeries::update); | 
| 727 |     emit barsetsReplaced(sets); | 
| 728 | } | 
| 729 |  | 
| 730 | /*! | 
| 731 |     Retrieves the BarSet specified at the location \a index. | 
| 732 |     Returns null if no BarSet was found. | 
| 733 | */ | 
| 734 | QBarSet *QBarSeries::at(qsizetype index) | 
| 735 | { | 
| 736 |     Q_D(QBarSeries); | 
| 737 |  | 
| 738 |     if (d->m_barSets.size() <= index) | 
| 739 |         return nullptr; | 
| 740 |     if (index < 0) | 
| 741 |         return nullptr; | 
| 742 |  | 
| 743 |     return d->m_barSets[index]; | 
| 744 | } | 
| 745 |  | 
| 746 | /*! | 
| 747 |     Returns the index of the first BarSet found as defined by \a set. Returns -1 if no BarSet was found. | 
| 748 | */ | 
| 749 | qsizetype QBarSeries::find(QBarSet *set) const | 
| 750 | { | 
| 751 |     Q_D(const QBarSeries); | 
| 752 |  | 
| 753 |     for (qsizetype i = 0; i < d->m_barSets.size(); ++i) { | 
| 754 |         if (set == d->m_barSets[i]) | 
| 755 |             return i; | 
| 756 |     } | 
| 757 |  | 
| 758 |     return -1; | 
| 759 | } | 
| 760 |  | 
| 761 | /*! | 
| 762 |     Removes multiple BarSets from the series starting from \a index to a number of \a count. | 
| 763 |     The BarSets will be permanently deleted. | 
| 764 | */ | 
| 765 | void QBarSeries::removeMultiple(qsizetype index, qsizetype count) | 
| 766 | { | 
| 767 |     Q_D(QBarSeries); | 
| 768 |  | 
| 769 |     if (index + count >= d->m_barSets.size()) | 
| 770 |         return; | 
| 771 |     if (index < 0 || count < 0) | 
| 772 |         return; | 
| 773 |  | 
| 774 |     for (qsizetype i = index; i < index + count; ++i) | 
| 775 |         remove(set: d->m_barSets[index]); | 
| 776 | } | 
| 777 |  | 
| 778 | /*! | 
| 779 |     Removes the BarSet at the location \a index. The BarSet will be permanently deleted. | 
| 780 | */ | 
| 781 | bool QBarSeries::remove(qsizetype index) | 
| 782 | { | 
| 783 |     Q_D(QBarSeries); | 
| 784 |  | 
| 785 |     if (index >= d->m_barSets.size()) | 
| 786 |         return false; | 
| 787 |     if (index < 0) | 
| 788 |         return false; | 
| 789 |  | 
| 790 |     return remove(set: d->m_barSets[index]); | 
| 791 | } | 
| 792 |  | 
| 793 | /*! | 
| 794 |     Replaces the BarSet specified by \a oldValue with the one in \a newValue. The BarSet | 
| 795 |     in \a oldValue will be permanently deleted if found inside the series. Returns \c true if | 
| 796 |     the replace is successful. | 
| 797 | */ | 
| 798 | bool QBarSeries::replace(QBarSet *oldValue, QBarSet *newValue) | 
| 799 | { | 
| 800 |     Q_D(QBarSeries); | 
| 801 |  | 
| 802 |     if (!oldValue || !newValue) | 
| 803 |         return false; | 
| 804 |     if (oldValue == newValue) | 
| 805 |         return false; | 
| 806 |  | 
| 807 |     for (qsizetype i = 0; i < d->m_barSets.size(); ++i) { | 
| 808 |         if (d->m_barSets[i] == oldValue) { | 
| 809 |             remove(set: d->m_barSets[i]); | 
| 810 |             d->insert(index: i, set: newValue); | 
| 811 |  | 
| 812 |             QList<QBarSet *> sets; | 
| 813 |             sets.append(t: newValue); | 
| 814 |             QObject::connect(sender: newValue, signal: &QBarSet::update, context: this, slot: &QBarSeries::update); | 
| 815 |             emit barsetsReplaced(sets); | 
| 816 |             return true; | 
| 817 |         } | 
| 818 |     } | 
| 819 |  | 
| 820 |     return false; | 
| 821 | } | 
| 822 |  | 
| 823 | /*! | 
| 824 |     Replaces the entire BarSet list inside of this BarSeries with the BarSets specified by \a sets. | 
| 825 |     All of the original BarSets will be permanently deleted. Returns \c true if all BarSets are replaced. | 
| 826 | */ | 
| 827 | bool QBarSeries::replace(const QList<QBarSet *> &sets) | 
| 828 | { | 
| 829 |     Q_D(QBarSeries); | 
| 830 |  | 
| 831 |     for (const auto set : sets) { | 
| 832 |         if (!set) | 
| 833 |             return false; | 
| 834 |     } | 
| 835 |  | 
| 836 |     for (const auto set : d->m_barSets) { | 
| 837 |         remove(set); | 
| 838 |     } | 
| 839 |  | 
| 840 |     for (const auto set : sets) { | 
| 841 |         QObject::connect(sender: set, signal: &QBarSet::update, context: this, slot: &QBarSeries::update); | 
| 842 |     } | 
| 843 |  | 
| 844 |     d->append(sets); | 
| 845 |     emit barsetsReplaced(sets); | 
| 846 |  | 
| 847 |     return true; | 
| 848 | } | 
| 849 |  | 
| 850 | /*! | 
| 851 |     Returns the number of bar sets in a bar series. | 
| 852 | */ | 
| 853 | qsizetype QBarSeries::count() const | 
| 854 | { | 
| 855 |     Q_D(const QBarSeries); | 
| 856 |     return d->m_barSets.size(); | 
| 857 | } | 
| 858 |  | 
| 859 | /*! | 
| 860 |     Returns a list of bar sets in a bar series. Keeps the ownership of the bar sets. | 
| 861 |  */ | 
| 862 | QList<QBarSet *> QBarSeries::barSets() const | 
| 863 | { | 
| 864 |     Q_D(const QBarSeries); | 
| 865 |     return d->m_barSets; | 
| 866 | } | 
| 867 |  | 
| 868 | /*! | 
| 869 |     Sets the visibility of labels in a bar series to \a visible. | 
| 870 | */ | 
| 871 | void QBarSeries::setLabelsVisible(bool visible) | 
| 872 | { | 
| 873 |     Q_D(QBarSeries); | 
| 874 |     if (d->m_labelsVisible != visible) { | 
| 875 |         d->setLabelsVisible(visible); | 
| 876 |         emit labelsVisibleChanged(visible); | 
| 877 |         emit update(); | 
| 878 |     } | 
| 879 | } | 
| 880 |  | 
| 881 | /*! | 
| 882 |     Returns the visibility of labels. | 
| 883 | */ | 
| 884 | bool QBarSeries::labelsVisible() const | 
| 885 | { | 
| 886 |     Q_D(const QBarSeries); | 
| 887 |     return d->m_labelsVisible; | 
| 888 | } | 
| 889 |  | 
| 890 | void QBarSeries::setLabelsFormat(const QString &format) | 
| 891 | { | 
| 892 |     Q_D(QBarSeries); | 
| 893 |     if (d->m_labelsFormat != format) { | 
| 894 |         d->m_labelsFormat = format; | 
| 895 |         d->setLabelsDirty(true); | 
| 896 |         emit labelsFormatChanged(format); | 
| 897 |         emit update(); | 
| 898 |     } | 
| 899 | } | 
| 900 |  | 
| 901 | QString QBarSeries::labelsFormat() const | 
| 902 | { | 
| 903 |     Q_D(const QBarSeries); | 
| 904 |     return d->m_labelsFormat; | 
| 905 | } | 
| 906 |  | 
| 907 | void QBarSeries::setLabelsMargin(qreal margin) | 
| 908 | { | 
| 909 |     Q_D(QBarSeries); | 
| 910 |     if (d->m_labelsMargin != margin) { | 
| 911 |         d->m_labelsMargin = margin; | 
| 912 |         d->setLabelsDirty(true); | 
| 913 |         emit labelsMarginChanged(margin); | 
| 914 |         emit update(); | 
| 915 |     } | 
| 916 | } | 
| 917 |  | 
| 918 | qreal QBarSeries::labelsMargin() const | 
| 919 | { | 
| 920 |     Q_D(const QBarSeries); | 
| 921 |     return d->m_labelsMargin; | 
| 922 | } | 
| 923 |  | 
| 924 | void QBarSeries::setLabelsAngle(qreal angle) | 
| 925 | { | 
| 926 |     Q_D(QBarSeries); | 
| 927 |     if (d->m_labelsAngle != angle) { | 
| 928 |         d->m_labelsAngle = angle; | 
| 929 |         d->setLabelsDirty(true); | 
| 930 |         emit labelsAngleChanged(angle); | 
| 931 |         emit update(); | 
| 932 |     } | 
| 933 | } | 
| 934 |  | 
| 935 | qreal QBarSeries::labelsAngle() const | 
| 936 | { | 
| 937 |     Q_D(const QBarSeries); | 
| 938 |     return d->m_labelsAngle; | 
| 939 | } | 
| 940 |  | 
| 941 | void QBarSeries::setLabelsPosition(QBarSeries::LabelsPosition position) | 
| 942 | { | 
| 943 |     Q_D(QBarSeries); | 
| 944 |     if (d->m_labelsPosition != position) { | 
| 945 |         d->m_labelsPosition = position; | 
| 946 |         emit labelsPositionChanged(position); | 
| 947 |         emit update(); | 
| 948 |     } | 
| 949 | } | 
| 950 |  | 
| 951 | QBarSeries::LabelsPosition QBarSeries::labelsPosition() const | 
| 952 | { | 
| 953 |     Q_D(const QBarSeries); | 
| 954 |     return d->m_labelsPosition; | 
| 955 | } | 
| 956 |  | 
| 957 | void QBarSeries::setLabelsPrecision(int precision) | 
| 958 | { | 
| 959 |     Q_D(QBarSeries); | 
| 960 |     if (d->m_labelsPrecision != precision) { | 
| 961 |         d->m_labelsPrecision = precision; | 
| 962 |         d->setLabelsDirty(true); | 
| 963 |         emit labelsPrecisionChanged(precision); | 
| 964 |         emit update(); | 
| 965 |     } | 
| 966 | } | 
| 967 |  | 
| 968 | int QBarSeries::labelsPrecision() const | 
| 969 | { | 
| 970 |     Q_D(const QBarSeries); | 
| 971 |     return d->m_labelsPrecision; | 
| 972 | } | 
| 973 |  | 
| 974 | QQmlComponent *QBarSeries::barDelegate() const | 
| 975 | { | 
| 976 |     Q_D(const QBarSeries); | 
| 977 |     return d->m_barDelegate; | 
| 978 | } | 
| 979 |  | 
| 980 | void QBarSeries::setBarDelegate(QQmlComponent *newBarDelegate) | 
| 981 | { | 
| 982 |     Q_D(QBarSeries); | 
| 983 |     if (d->m_barDelegate == newBarDelegate) | 
| 984 |         return; | 
| 985 |     d->m_barDelegate = newBarDelegate; | 
| 986 |     d->m_barDelegateDirty = true; | 
| 987 |     emit barDelegateChanged(); | 
| 988 |     emit update(); | 
| 989 | } | 
| 990 |  | 
| 991 | // Select all the elements in the series | 
| 992 | void QBarSeries::selectAll() | 
| 993 | { | 
| 994 |     Q_D(QBarSeries); | 
| 995 |     for (auto s : d->m_barSets) { | 
| 996 |         s->selectAllBars(); | 
| 997 |     } | 
| 998 | } | 
| 999 |  | 
| 1000 | // Deselect all the elements in the series | 
| 1001 | void QBarSeries::deselectAll() | 
| 1002 | { | 
| 1003 |     Q_D(QBarSeries); | 
| 1004 |     for (auto s : d->m_barSets) { | 
| 1005 |         s->deselectAllBars(); | 
| 1006 |     } | 
| 1007 | } | 
| 1008 |  | 
| 1009 | void QBarSeries::componentComplete() | 
| 1010 | { | 
| 1011 |     for (auto *child : children()) { | 
| 1012 |         if (auto bs = qobject_cast<QBarSet *>(object: child)) | 
| 1013 |             append(set: bs); | 
| 1014 |     } | 
| 1015 |     QAbstractSeries::componentComplete(); | 
| 1016 | } | 
| 1017 |  | 
| 1018 | void QBarSeries::handleSetValueChange(qsizetype index) | 
| 1019 | { | 
| 1020 |     QBarSet *set = qobject_cast<QBarSet *>(object: sender()); | 
| 1021 |     if (set) | 
| 1022 |         emit setValueChanged(index, barset: set); | 
| 1023 |     emit update(); | 
| 1024 | } | 
| 1025 |  | 
| 1026 | void QBarSeries::handleSetValueAdd(qsizetype index, qsizetype count) | 
| 1027 | { | 
| 1028 |     QBarSet *set = qobject_cast<QBarSet *>(object: sender()); | 
| 1029 |     if (set) | 
| 1030 |         emit setValueAdded(index, count, barset: set); | 
| 1031 |     emit update(); | 
| 1032 | } | 
| 1033 |  | 
| 1034 | void QBarSeries::handleSetValueRemove(qsizetype index, qsizetype count) | 
| 1035 | { | 
| 1036 |     QBarSet *set = qobject_cast<QBarSet *>(object: sender()); | 
| 1037 |     if (set) | 
| 1038 |         emit setValueRemoved(index, count, barset: set); | 
| 1039 |     emit update(); | 
| 1040 | } | 
| 1041 |  | 
| 1042 | bool QBarSeries::barDelegateDirty() const | 
| 1043 | { | 
| 1044 |     Q_D(const QBarSeries); | 
| 1045 |     return d->m_barDelegateDirty; | 
| 1046 | } | 
| 1047 |  | 
| 1048 | void QBarSeries::setBarDelegateDirty(bool dirty) | 
| 1049 | { | 
| 1050 |     Q_D(QBarSeries); | 
| 1051 |     d->m_barDelegateDirty = dirty; | 
| 1052 | } | 
| 1053 |  | 
| 1054 | QBarSeriesPrivate::QBarSeriesPrivate() | 
| 1055 |     : m_barWidth(0.5) // Default value is 50% of category width | 
| 1056 |       , m_labelsVisible(false) | 
| 1057 |       , m_visible(true) | 
| 1058 |       , m_blockBarUpdate(false) | 
| 1059 |       , m_labelsFormat() | 
| 1060 |       , m_labelsMargin(0) | 
| 1061 |       , m_labelsAngle(0) | 
| 1062 |       , m_labelsPrecision(6) | 
| 1063 |       , m_labelsDirty(true) | 
| 1064 |       , m_barDelegateDirty(false) | 
| 1065 | { | 
| 1066 | } | 
| 1067 |  | 
| 1068 | qsizetype QBarSeriesPrivate::categoryCount() const | 
| 1069 | { | 
| 1070 |     // No categories defined. return count of longest set. | 
| 1071 |     qsizetype count = 0; | 
| 1072 |     for (qsizetype i = 0; i < m_barSets.size(); i++) { | 
| 1073 |         if (m_barSets.at(i)->count() > count) | 
| 1074 |             count = m_barSets.at(i)->count(); | 
| 1075 |     } | 
| 1076 |  | 
| 1077 |     return count; | 
| 1078 | } | 
| 1079 |  | 
| 1080 | void QBarSeriesPrivate::setBarWidth(qreal width) | 
| 1081 | { | 
| 1082 |     Q_Q(QBarSeries); | 
| 1083 |     width = std::clamp<qreal>(val: width, lo: 0.0, hi: 1.0); | 
| 1084 |     if (!qFuzzyCompare(p1: width, p2: m_barWidth)) { | 
| 1085 |         m_barWidth = width; | 
| 1086 |         q->update(); | 
| 1087 |     } | 
| 1088 | } | 
| 1089 |  | 
| 1090 | qreal QBarSeriesPrivate::barWidth() const | 
| 1091 | { | 
| 1092 |     return m_barWidth; | 
| 1093 | } | 
| 1094 |  | 
| 1095 | QBarSet *QBarSeriesPrivate::barsetAt(qsizetype index) | 
| 1096 | { | 
| 1097 |     return m_barSets.at(i: index); | 
| 1098 | } | 
| 1099 |  | 
| 1100 | void QBarSeriesPrivate::setVisible(bool visible) | 
| 1101 | { | 
| 1102 |     Q_Q(QBarSeries); | 
| 1103 |     m_visible = visible; | 
| 1104 |     emit q->visibleChanged(); | 
| 1105 | } | 
| 1106 |  | 
| 1107 | void QBarSeriesPrivate::setLabelsVisible(bool visible) | 
| 1108 | { | 
| 1109 |     m_labelsVisible = visible; | 
| 1110 | } | 
| 1111 |  | 
| 1112 | qreal QBarSeriesPrivate::min() | 
| 1113 | { | 
| 1114 |     if (m_barSets.size() <= 0) | 
| 1115 |         return 0; | 
| 1116 |  | 
| 1117 |     qreal min = INT_MAX; | 
| 1118 |  | 
| 1119 |     for (int i = 0; i < m_barSets.size(); i++) { | 
| 1120 |         qsizetype categoryCount = m_barSets.at(i)->count(); | 
| 1121 |         for (qsizetype j = 0; j < categoryCount; j++) { | 
| 1122 |             qreal temp = m_barSets.at(i)->at(index: j); | 
| 1123 |             if (temp < min) | 
| 1124 |                 min = temp; | 
| 1125 |         } | 
| 1126 |     } | 
| 1127 |     return min; | 
| 1128 | } | 
| 1129 |  | 
| 1130 | qreal QBarSeriesPrivate::max() | 
| 1131 | { | 
| 1132 |     if (m_barSets.size() <= 0) | 
| 1133 |         return 0; | 
| 1134 |  | 
| 1135 |     qreal max = INT_MIN; | 
| 1136 |  | 
| 1137 |     for (int i = 0; i < m_barSets.size(); i++) { | 
| 1138 |         qsizetype categoryCount = m_barSets.at(i)->count(); | 
| 1139 |         for (qsizetype j = 0; j < categoryCount; j++) { | 
| 1140 |             qreal temp = m_barSets.at(i)->at(index: j); | 
| 1141 |             if (temp > max) | 
| 1142 |                 max = temp; | 
| 1143 |         } | 
| 1144 |     } | 
| 1145 |  | 
| 1146 |     return max; | 
| 1147 | } | 
| 1148 |  | 
| 1149 | qreal QBarSeriesPrivate::valueAt(int set, int category) | 
| 1150 | { | 
| 1151 |     if ((set < 0) || (set >= m_barSets.size())) | 
| 1152 |         return 0; // No set, no value. | 
| 1153 |     else if ((category < 0) || (category >= m_barSets.at(i: set)->count())) | 
| 1154 |         return 0; // No category, no value. | 
| 1155 |  | 
| 1156 |     return m_barSets.at(i: set)->at(index: category); | 
| 1157 | } | 
| 1158 |  | 
| 1159 | qreal QBarSeriesPrivate::percentageAt(int set, int category) | 
| 1160 | { | 
| 1161 |     if ((set < 0) || (set >= m_barSets.size())) | 
| 1162 |         return 0; // No set, no value. | 
| 1163 |     else if ((category < 0) || (category >= m_barSets.at(i: set)->count())) | 
| 1164 |         return 0; // No category, no value. | 
| 1165 |  | 
| 1166 |     qreal value = m_barSets.at(i: set)->at(index: category); | 
| 1167 |     qreal sum = categorySum(category); | 
| 1168 |     if (qFuzzyCompare(p1: sum, p2: 0)) | 
| 1169 |         return 0; | 
| 1170 |  | 
| 1171 |     return value / sum; | 
| 1172 | } | 
| 1173 |  | 
| 1174 | qreal QBarSeriesPrivate::categorySum(qsizetype category) | 
| 1175 | { | 
| 1176 |     qreal sum(0); | 
| 1177 |     qsizetype count = m_barSets.size(); // Count sets | 
| 1178 |     for (qsizetype set = 0; set < count; set++) { | 
| 1179 |         if (category < m_barSets.at(i: set)->count()) | 
| 1180 |             sum += m_barSets.at(i: set)->at(index: category); | 
| 1181 |     } | 
| 1182 |     return sum; | 
| 1183 | } | 
| 1184 |  | 
| 1185 | qreal QBarSeriesPrivate::absoluteCategorySum(int category) | 
| 1186 | { | 
| 1187 |     qreal sum(0); | 
| 1188 |     qsizetype count = m_barSets.size(); // Count sets | 
| 1189 |     for (qsizetype set = 0; set < count; set++) { | 
| 1190 |         if (category < m_barSets.at(i: set)->count()) | 
| 1191 |             sum += qAbs(t: m_barSets.at(i: set)->at(index: category)); | 
| 1192 |     } | 
| 1193 |     return sum; | 
| 1194 | } | 
| 1195 |  | 
| 1196 | qreal QBarSeriesPrivate::maxCategorySum() | 
| 1197 | { | 
| 1198 |     qreal max = INT_MIN; | 
| 1199 |     qsizetype count = categoryCount(); | 
| 1200 |     for (qsizetype i = 0; i < count; i++) { | 
| 1201 |         qreal sum = categorySum(category: i); | 
| 1202 |         if (sum > max) | 
| 1203 |             max = sum; | 
| 1204 |     } | 
| 1205 |     return max; | 
| 1206 | } | 
| 1207 |  | 
| 1208 | qreal QBarSeriesPrivate::minX() | 
| 1209 | { | 
| 1210 |     if (m_barSets.size() <= 0) | 
| 1211 |         return 0; | 
| 1212 |  | 
| 1213 |     qreal min = INT_MAX; | 
| 1214 |  | 
| 1215 |     for (int i = 0; i < m_barSets.size(); i++) { | 
| 1216 |         qsizetype categoryCount = m_barSets.at(i)->count(); | 
| 1217 |         for (qsizetype j = 0; j < categoryCount; j++) { | 
| 1218 |             qreal temp = m_barSets.at(i)->d_func()->m_values.at(i: j).x(); | 
| 1219 |             if (temp < min) | 
| 1220 |                 min = temp; | 
| 1221 |         } | 
| 1222 |     } | 
| 1223 |     return min; | 
| 1224 | } | 
| 1225 |  | 
| 1226 | qreal QBarSeriesPrivate::maxX() | 
| 1227 | { | 
| 1228 |     if (m_barSets.size() <= 0) | 
| 1229 |         return 0; | 
| 1230 |  | 
| 1231 |     qreal max = INT_MIN; | 
| 1232 |  | 
| 1233 |     for (int i = 0; i < m_barSets.size(); i++) { | 
| 1234 |         qsizetype categoryCount = m_barSets.at(i)->count(); | 
| 1235 |         for (qsizetype j = 0; j < categoryCount; j++) { | 
| 1236 |             qreal temp = m_barSets.at(i)->d_func()->m_values.at(i: j).x(); | 
| 1237 |             if (temp > max) | 
| 1238 |                 max = temp; | 
| 1239 |         } | 
| 1240 |     } | 
| 1241 |  | 
| 1242 |     return max; | 
| 1243 | } | 
| 1244 |  | 
| 1245 | qreal QBarSeriesPrivate::categoryTop(qsizetype category) | 
| 1246 | { | 
| 1247 |     // Returns top (sum of all positive values) of category. | 
| 1248 |     // Returns 0, if all values are negative | 
| 1249 |     qreal top(0); | 
| 1250 |     qsizetype count = m_barSets.size(); | 
| 1251 |     for (qsizetype set = 0; set < count; set++) { | 
| 1252 |         if (category < m_barSets.at(i: set)->count()) { | 
| 1253 |             qreal temp = m_barSets.at(i: set)->at(index: category); | 
| 1254 |             if (temp > 0) { | 
| 1255 |                 top += temp; | 
| 1256 |             } | 
| 1257 |         } | 
| 1258 |     } | 
| 1259 |     return top; | 
| 1260 | } | 
| 1261 |  | 
| 1262 | qreal QBarSeriesPrivate::categoryBottom(qsizetype category) | 
| 1263 | { | 
| 1264 |     // Returns bottom (sum of all negative values) of category | 
| 1265 |     // Returns 0, if all values are positive | 
| 1266 |     qreal bottom(0); | 
| 1267 |     qsizetype count = m_barSets.size(); | 
| 1268 |     for (qsizetype set = 0; set < count; set++) { | 
| 1269 |         if (category < m_barSets.at(i: set)->count()) { | 
| 1270 |             qreal temp = m_barSets.at(i: set)->at(index: category); | 
| 1271 |             if (temp < 0) { | 
| 1272 |                 bottom += temp; | 
| 1273 |             } | 
| 1274 |         } | 
| 1275 |     } | 
| 1276 |     return bottom; | 
| 1277 | } | 
| 1278 | qreal QBarSeriesPrivate::top() | 
| 1279 | { | 
| 1280 |     // Returns top of all categories | 
| 1281 |     qreal top(0); | 
| 1282 |     qsizetype count = categoryCount(); | 
| 1283 |     for (qsizetype i = 0; i < count; i++) { | 
| 1284 |         qreal temp = categoryTop(category: i); | 
| 1285 |         if (temp > top) | 
| 1286 |             top = temp; | 
| 1287 |     } | 
| 1288 |     return top; | 
| 1289 | } | 
| 1290 |  | 
| 1291 | qreal QBarSeriesPrivate::bottom() | 
| 1292 | { | 
| 1293 |     // Returns bottom of all categories | 
| 1294 |     qreal bottom(0); | 
| 1295 |     qsizetype count = categoryCount(); | 
| 1296 |     for (qsizetype i = 0; i < count; i++) { | 
| 1297 |         qreal temp = categoryBottom(category: i); | 
| 1298 |         if (temp < bottom) | 
| 1299 |             bottom = temp; | 
| 1300 |     } | 
| 1301 |     return bottom; | 
| 1302 | } | 
| 1303 |  | 
| 1304 | bool QBarSeriesPrivate::blockBarUpdate() | 
| 1305 | { | 
| 1306 |     return m_blockBarUpdate; | 
| 1307 | } | 
| 1308 |  | 
| 1309 | bool QBarSeriesPrivate::append(QBarSet *set) | 
| 1310 | { | 
| 1311 |     if ((m_barSets.contains(t: set)) || (set == 0)) | 
| 1312 |         return false; // Fail if set is already in list or set is null. | 
| 1313 |  | 
| 1314 |     m_barSets.append(t: set); | 
| 1315 |     Q_Q(QBarSeries); | 
| 1316 |     QObject::connect(sender: set, signal: &QBarSet::updatedBars, context: q, slot: &QBarSeries::updatedBars); | 
| 1317 |     QObject::connect(sender: set, signal: &QBarSet::valueChanged, context: q, slot: &QBarSeries::handleSetValueChange); | 
| 1318 |     QObject::connect(sender: set, signal: &QBarSet::valueAdded, context: q, slot: &QBarSeries::handleSetValueAdd); | 
| 1319 |     QObject::connect(sender: set, signal: &QBarSet::valueRemoved, context: q, slot: &QBarSeries::handleSetValueRemove); | 
| 1320 |     QObject::connect(sender: set, signal: &QBarSet::selectedBarsChanged, context: q, slot: &QBarSeries::updatedBars); | 
| 1321 |  | 
| 1322 |     return true; | 
| 1323 | } | 
| 1324 |  | 
| 1325 | bool QBarSeriesPrivate::remove(QBarSet *set) | 
| 1326 | { | 
| 1327 |     if (!m_barSets.contains(t: set)) | 
| 1328 |         return false; // Fail if set is not in list | 
| 1329 |  | 
| 1330 |     m_barSets.removeOne(t: set); | 
| 1331 |     Q_Q(QBarSeries); | 
| 1332 |     QObject::disconnect(sender: set, signal: &QBarSet::updatedBars, receiver: q, slot: &QBarSeries::updatedBars); | 
| 1333 |     QObject::disconnect(sender: set, signal: &QBarSet::valueChanged, receiver: q, slot: &QBarSeries::handleSetValueChange); | 
| 1334 |     QObject::disconnect(sender: set, signal: &QBarSet::valueAdded, receiver: q, slot: &QBarSeries::handleSetValueAdd); | 
| 1335 |     QObject::disconnect(sender: set, signal: &QBarSet::valueRemoved, receiver: q, slot: &QBarSeries::handleSetValueRemove); | 
| 1336 |     QObject::disconnect(sender: set, signal: &QBarSet::selectedBarsChanged, receiver: q, slot: &QBarSeries::updatedBars); | 
| 1337 |  | 
| 1338 |     return true; | 
| 1339 | } | 
| 1340 |  | 
| 1341 | bool QBarSeriesPrivate::append(const QList<QBarSet *> &sets) | 
| 1342 | { | 
| 1343 |     for (auto *set : sets) { | 
| 1344 |         if ((set == 0) || (m_barSets.contains(t: set))) | 
| 1345 |             return false; // Fail if any of the sets is null or is already appended. | 
| 1346 |         if (sets.count(t: set) != 1) | 
| 1347 |             return false; // Also fail if same set is more than once in given list. | 
| 1348 |     } | 
| 1349 |  | 
| 1350 |     Q_Q(QBarSeries); | 
| 1351 |     for (auto *set : sets) { | 
| 1352 |         m_barSets.append(t: set); | 
| 1353 |         QObject::connect(sender: set, signal: &QBarSet::updatedBars, context: q, slot: &QBarSeries::updatedBars); | 
| 1354 |         QObject::connect(sender: set, signal: &QBarSet::valueChanged, context: q, slot: &QBarSeries::handleSetValueChange); | 
| 1355 |         QObject::connect(sender: set, signal: &QBarSet::valueAdded, context: q, slot: &QBarSeries::handleSetValueAdd); | 
| 1356 |         QObject::connect(sender: set, signal: &QBarSet::valueRemoved, context: q, slot: &QBarSeries::handleSetValueRemove); | 
| 1357 |         QObject::connect(sender: set, signal: &QBarSet::selectedBarsChanged, context: q, slot: &QBarSeries::updatedBars); | 
| 1358 |     } | 
| 1359 |  | 
| 1360 |     return true; | 
| 1361 | } | 
| 1362 |  | 
| 1363 | bool QBarSeriesPrivate::remove(const QList<QBarSet *> &sets) | 
| 1364 | { | 
| 1365 |     if (sets.size() == 0) | 
| 1366 |         return false; | 
| 1367 |  | 
| 1368 |     for (QBarSet *set : sets) { | 
| 1369 |         if ((set == 0) || (!m_barSets.contains(t: set))) | 
| 1370 |             return false; // Fail if any of the sets is null or is not in series | 
| 1371 |         if (sets.count(t: set) != 1) | 
| 1372 |             return false; // Also fail if same set is more than once in given list. | 
| 1373 |     } | 
| 1374 |  | 
| 1375 |     Q_Q(QBarSeries); | 
| 1376 |     for (QBarSet *set : sets) { | 
| 1377 |         m_barSets.removeOne(t: set); | 
| 1378 |         QObject::disconnect(sender: set, signal: &QBarSet::updatedBars, receiver: q, slot: &QBarSeries::updatedBars); | 
| 1379 |         QObject::disconnect(sender: set, | 
| 1380 |                             signal: &QBarSet::valueChanged, | 
| 1381 |                             receiver: q, | 
| 1382 |                             slot: &QBarSeries::handleSetValueChange); | 
| 1383 |         QObject::disconnect(sender: set, signal: &QBarSet::valueAdded, receiver: q, slot: &QBarSeries::handleSetValueAdd); | 
| 1384 |         QObject::disconnect(sender: set, | 
| 1385 |                             signal: &QBarSet::valueRemoved, | 
| 1386 |                             receiver: q, | 
| 1387 |                             slot: &QBarSeries::handleSetValueRemove); | 
| 1388 |         QObject::disconnect(sender: set, signal: &QBarSet::selectedBarsChanged, receiver: q, slot: &QBarSeries::updatedBars); | 
| 1389 |     } | 
| 1390 |  | 
| 1391 |     return true; | 
| 1392 | } | 
| 1393 |  | 
| 1394 | bool QBarSeriesPrivate::insert(qsizetype index, QBarSet *set) | 
| 1395 | { | 
| 1396 |     if ((m_barSets.contains(t: set)) || (set == 0)) | 
| 1397 |         return false; // Fail if set is already in list or set is null. | 
| 1398 |  | 
| 1399 |     m_barSets.insert(i: index, t: set); | 
| 1400 |     Q_Q(QBarSeries); | 
| 1401 |     QObject::connect(sender: set, signal: &QBarSet::updatedBars, context: q, slot: &QBarSeries::updatedBars); | 
| 1402 |     QObject::connect(sender: set, signal: &QBarSet::valueChanged, context: q, slot: &QBarSeries::handleSetValueChange); | 
| 1403 |     QObject::connect(sender: set, signal: &QBarSet::valueAdded, context: q, slot: &QBarSeries::handleSetValueAdd); | 
| 1404 |     QObject::connect(sender: set, signal: &QBarSet::valueRemoved, context: q, slot: &QBarSeries::handleSetValueRemove); | 
| 1405 |     QObject::disconnect(sender: set, signal: &QBarSet::selectedBarsChanged, receiver: q, slot: &QBarSeries::updatedBars); | 
| 1406 |  | 
| 1407 |     return true; | 
| 1408 | } | 
| 1409 |  | 
| 1410 | QT_END_NAMESPACE | 
| 1411 |  | 
| 1412 | #include "moc_qbarseries.cpp" | 
| 1413 |  |