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 | |