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

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