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

source code of qtgraphs/src/graphs2d/barchart/qbarseries.cpp