1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
5
6#include <QtCharts/QLegend>
7#include <private/qlegend_p.h>
8#include <QtCharts/QAbstractSeries>
9#include <private/qabstractseries_p.h>
10#include <private/qchart_p.h>
11#include <private/legendlayout_p.h>
12#include <private/chartpresenter_p.h>
13#include <private/abstractchartlayout_p.h>
14#include <QtCharts/QLegendMarker>
15#include <private/qlegendmarker_p.h>
16#include <private/legendmarkeritem_p.h>
17#include <private/legendmoveresizehandler_p.h>
18#include <private/chartdataset_p.h>
19#include <QtGui/QPainter>
20#include <QtGui/QPen>
21#include <QtWidgets/QGraphicsItemGroup>
22
23QT_BEGIN_NAMESPACE
24
25/*!
26 \class QLegend
27 \inmodule QtCharts
28 \inherits QGraphicsWidget
29 \brief The QLegend class displays the legend of a chart.
30
31 A legend is a graphical object that displays the legend of a chart. The legend state is updated
32 by QChart when series change. By default, the legend is attached to the chart, but it can be
33 detached to make it independent of chart layout. Legend objects cannot be created or deleted,
34 but they can be referenced via the QChart class.
35
36 \image examples_percentbarchart_legend.png
37
38 \sa QChart
39*/
40/*!
41 \qmltype Legend
42 \nativetype QLegend
43 \inqmlmodule QtCharts
44
45 \brief Displays the legend of a chart.
46
47 A legend is a graphical object that displays the legend of a chart. The legend state is updated
48 by the ChartView type when series change. The \l Legend type properties can be attached to the
49 ChartView type. For example:
50 \code
51 ChartView {
52 legend.visible: true
53 legend.alignment: Qt.AlignBottom
54 // Add a few series...
55 }
56 \endcode
57
58 \image examples_percentbarchart_legend.png
59
60 \note There is no QML API available for modifying legend markers. Markers
61 can be modified by creating a custom legend. For more information, see
62 \l {Using Legend Markers}.
63*/
64
65/*!
66 \property QLegend::alignment
67 \brief How the legend is aligned with the chart.
68
69 Can be Qt::AlignTop, Qt::AlignBottom, Qt::AlignLeft, Qt::AlignRight. If you set more than one
70 flag, the result is undefined.
71*/
72/*!
73 \qmlproperty alignment Legend::alignment
74 Defines how the legend is aligned with the chart. Can be \l{Qt::AlignLeft}{Qt.AlignLeft},
75 \l{Qt::AlignRight}{Qt.AlignRight}, \l{Qt::AlignBottom}{Qt.AlignBottom}, or
76 \l{Qt::AlignTop}{Qt.AlignTop}. If you set more than one flag, the result is undefined.
77*/
78
79/*!
80 \property QLegend::backgroundVisible
81 \brief Whether the legend background is visible.
82*/
83/*!
84 \qmlproperty bool Legend::backgroundVisible
85 Whether the legend background is visible.
86*/
87
88/*!
89 \qmlproperty bool Legend::visible
90 Whether the legend is visible.
91
92 By default, this property is \c true.
93 \sa QGraphicsObject::visible
94*/
95
96/*!
97 \property QLegend::color
98 \brief The background (brush) color of the legend.
99
100 If you change the color of the legend, the style of the legend brush is set to
101 Qt::SolidPattern.
102*/
103/*!
104 \qmlproperty color Legend::color
105 The background (brush) color of the legend.
106*/
107
108/*!
109 \property QLegend::borderColor
110 \brief The line color of the legend.
111*/
112/*!
113 \qmlproperty color Legend::borderColor
114 The line color of the legend.
115*/
116
117/*!
118 \property QLegend::font
119 \brief The font of the markers used by the legend.
120*/
121/*!
122 \qmlproperty Font Legend::font
123 The font of the markers used by the legend.
124*/
125
126/*!
127 \property QLegend::labelColor
128 \brief The color of the brush used to draw labels.
129*/
130/*!
131 \qmlproperty color Legend::labelColor
132 The color of the brush used to draw labels.
133*/
134
135/*!
136 \property QLegend::reverseMarkers
137 \brief Whether reverse order is used for the markers in the legend.
138
139 This property is \c false by default.
140*/
141/*!
142 \qmlproperty bool Legend::reverseMarkers
143 Whether reverse order is used for the markers in the legend. This property
144 is \c false by default.
145*/
146
147/*!
148 \property QLegend::showToolTips
149 \brief Whether tooltips are shown when the text is truncated.
150
151 This property is \c false by default.
152*/
153
154/*!
155 \enum QLegend::MarkerShape
156
157 This enum describes the shape used when rendering legend marker items.
158
159 \value MarkerShapeDefault Default shape determined by QLegend is used for the marker.
160 This value is supported only for individual QLegendMarker items.
161 \value MarkerShapeRectangle Rectangular markers are used.
162 Marker size is determined by font size.
163 \value MarkerShapeCircle Circular markers are used.
164 Marker size is determined by font size.
165 \value MarkerShapeRotatedRectangle Rotated rectangle shaped markers are used.
166 Marker size is determined by font size.
167 \value MarkerShapeTriangle Triangular markers are used.
168 Marker size is determined by font size.
169 \value MarkerShapeStar Star shaped markers are used.
170 Marker size is determined by font size.
171 \value MarkerShapePentagon Pentagon shaped markers are used.
172 Marker size is determined by font size.
173 \value MarkerShapeFromSeries The marker shape is determined by the series.
174 In case of a scatter series, the legend marker looks like a scatter dot and is the same
175 size as the dot. In case of a line or spline series, the legend marker looks like a
176 small segment of the line. For other series types, rectangular markers are shown.
177 If a \c lightMarker is specified for a series, the \c lightMarker will be shown and
178 its size will be determined by the series marker size.
179
180 \sa markerShape
181*/
182
183/*!
184 \qmlproperty enumeration Legend::markerShape
185 \since 5.9
186
187 The default shape of the legend markers.
188 The default value is \c{MarkerShapeRectangle}.
189
190 \value Legend.MarkerShapeRectangle Legend markers are rectangular
191 \value Legend.MarkerShapeCircle Legend markers are circular
192 \value MarkerShapeRotatedRectangle Legend markers are rotated rectangle shaped.
193 \value MarkerShapeTriangle Legend markers are triangular.
194 \value MarkerShapeStar Legend markers are star shaped.
195 \value MarkerShapePentagon Legend markers are pentagon shaped.
196 \value Legend.MarkerShapeFromSeries Legend marker shape is determined by the series
197
198 \sa QLegend::MarkerShape
199*/
200
201/*!
202 \property QLegend::markerShape
203 \since 5.9
204
205 The default shape of the legend markers.
206 The default value is \c{MarkerShapeRectangle}.
207*/
208
209/*!
210 \qmlproperty bool Legend::showToolTips
211 Whether tooltips are shown when the text is truncated. This property is \c false by default.
212 This property currently has no effect as there is no support for tooltips in QML.
213*/
214
215/*!
216 \fn void QLegend::attachedToChartChanged(bool attached)
217 This signal is emitted when the legend is \a attached to or detached from the chart.
218 \since 6.2
219*/
220
221/*!
222 \fn void QLegend::backgroundVisibleChanged(bool)
223 This signal is emitted when the visibility of the legend background changes to \a visible.
224*/
225
226/*!
227 \fn void QLegend::colorChanged(QColor)
228 This signal is emitted when the color of the legend background changes to \a color.
229*/
230
231/*!
232 \fn void QLegend::borderColorChanged(QColor)
233 This signal is emitted when the border color of the legend background changes to \a color.
234*/
235
236/*!
237 \fn void QLegend::fontChanged(QFont)
238 This signal is emitted when the font of the markers of the legend changes to \a font.
239*/
240
241/*!
242 \fn void QLegend::labelColorChanged(QColor color)
243 This signal is emitted when the color of the brush used to draw the legend
244 labels changes to \a color.
245*/
246
247/*!
248 \fn void QLegend::reverseMarkersChanged(bool)
249 This signal is emitted when the use of reverse order for the markers in the
250 legend is changed to \a reverseMarkers.
251*/
252
253/*!
254 \fn void QLegend::showToolTipsChanged(bool showToolTips)
255 This signal is emitted when the visibility of tooltips is changed to \a showToolTips.
256*/
257
258QLegend::QLegend(QChart *chart): QGraphicsWidget(chart),
259 d_ptr(new QLegendPrivate(chart->d_ptr->m_presenter, chart, this))
260{
261 setZValue(ChartPresenter::LegendZValue);
262 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
263 QObject::connect(sender: chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), receiver: d_ptr.data(), SLOT(handleSeriesAdded(QAbstractSeries*)));
264 QObject::connect(sender: chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), receiver: d_ptr.data(), SLOT(handleSeriesRemoved(QAbstractSeries*)));
265 setLayout(d_ptr->m_layout);
266}
267
268/*!
269 Destroys the legend object. The legend is always owned by a QChart, so an application
270 should never call this function.
271*/
272QLegend::~QLegend()
273{
274}
275
276/*!
277 \internal
278 */
279void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
280{
281 Q_UNUSED(option);
282 Q_UNUSED(widget);
283
284 if (!d_ptr->m_backgroundVisible)
285 return;
286
287 painter->setOpacity(opacity());
288 painter->setPen(d_ptr->m_pen);
289 painter->setBrush(d_ptr->m_brush);
290 painter->drawRoundedRect(rect: rect(), xRadius: d_ptr->roundness(size: rect().width()),
291 yRadius: d_ptr->roundness(size: rect().height()), mode: Qt::RelativeSize);
292}
293
294
295/*!
296 Sets the \a brush that is used to draw the background of the legend.
297 */
298void QLegend::setBrush(const QBrush &brush)
299{
300 if (d_ptr->m_brush != brush) {
301 d_ptr->m_brush = brush;
302 update();
303 emit colorChanged(color: brush.color());
304 }
305}
306
307/*!
308 Returns the brush used by the legend.
309 */
310QBrush QLegend::brush() const
311{
312 if (d_ptr->m_brush == QChartPrivate::defaultBrush())
313 return QBrush();
314 else
315 return d_ptr->m_brush;
316}
317
318void QLegend::setColor(QColor color)
319{
320 QBrush b = brush();
321 if (b.style() != Qt::SolidPattern || b.color() != color) {
322 b.setStyle(Qt::SolidPattern);
323 b.setColor(color);
324 setBrush(b);
325 }
326}
327
328QColor QLegend::color()
329{
330 return d_ptr->m_brush.color();
331}
332
333/*!
334 Sets the \a pen that is used to draw the legend borders.
335 */
336void QLegend::setPen(const QPen &pen)
337{
338 if (d_ptr->m_pen != pen) {
339 d_ptr->m_pen = pen;
340 update();
341 emit borderColorChanged(color: pen.color());
342 }
343}
344
345/*!
346 Returns the pen used by the legend.
347 */
348
349QPen QLegend::pen() const
350{
351 if (d_ptr->m_pen == QChartPrivate::defaultPen())
352 return QPen();
353 else
354 return d_ptr->m_pen;
355}
356
357void QLegend::setFont(const QFont &font)
358{
359 if (d_ptr->m_font != font) {
360 // Hide items to avoid flickering
361 d_ptr->items()->setVisible(false);
362 d_ptr->m_font = font;
363 const auto markers = d_ptr->markers();
364 for (QLegendMarker *marker : markers) {
365 marker->setFont(d_ptr->m_font);
366 }
367 layout()->invalidate();
368 emit fontChanged(font);
369 }
370}
371
372QFont QLegend::font() const
373{
374 return d_ptr->m_font;
375}
376
377void QLegend::setBorderColor(QColor color)
378{
379 QPen p = pen();
380 if (p.color() != color) {
381 p.setColor(color);
382 setPen(p);
383 }
384}
385
386QColor QLegend::borderColor()
387{
388 return d_ptr->m_pen.color();
389}
390
391/*!
392 Sets the brush used to draw the legend labels to \a brush.
393*/
394void QLegend::setLabelBrush(const QBrush &brush)
395{
396 if (d_ptr->m_labelBrush != brush) {
397 d_ptr->m_labelBrush = brush;
398 const auto markers = d_ptr->markers();
399 for (QLegendMarker *marker : markers) {
400 marker->setLabelBrush(d_ptr->m_labelBrush);
401 // Note: The pen of the marker rectangle could be exposed in the public QLegend API
402 // instead of mapping it from label brush color
403 marker->setPen(brush.color());
404 }
405 emit labelColorChanged(color: brush.color());
406 }
407}
408
409/*!
410 Returns the brush used to draw labels.
411*/
412QBrush QLegend::labelBrush() const
413{
414 if (d_ptr->m_labelBrush == QChartPrivate::defaultBrush())
415 return QBrush();
416 else
417 return d_ptr->m_labelBrush;
418}
419
420void QLegend::setLabelColor(QColor color)
421{
422 QBrush b = labelBrush();
423 if (b.style() != Qt::SolidPattern || b.color() != color) {
424 b.setStyle(Qt::SolidPattern);
425 b.setColor(color);
426 setLabelBrush(b);
427 }
428}
429
430QColor QLegend::labelColor() const
431{
432 return d_ptr->m_labelBrush.color();
433}
434
435
436void QLegend::setAlignment(Qt::Alignment alignment)
437{
438 if (d_ptr->m_alignment != alignment) {
439 d_ptr->m_alignment = alignment;
440 layout()->invalidate();
441 }
442}
443
444Qt::Alignment QLegend::alignment() const
445{
446 return d_ptr->m_alignment;
447}
448
449/*!
450 Detaches the legend from the chart. The chart will no longer adjust the layout of the legend.
451 */
452void QLegend::detachFromChart()
453{
454 bool changed = d_ptr->m_attachedToChart == true;
455 d_ptr->m_attachedToChart = false;
456 d_ptr->m_chart->layout()->invalidate();
457 setParent(0);
458
459 if (changed)
460 emit attachedToChartChanged(attachedToChart: false);
461}
462
463/*!
464 Attaches the legend to a chart. The chart may adjust the layout of the legend.
465 */
466void QLegend::attachToChart()
467{
468 bool changed = d_ptr->m_attachedToChart == false;
469 d_ptr->m_attachedToChart = true;
470 d_ptr->m_chart->layout()->invalidate();
471 setParent(d_ptr->m_chart);
472
473 if (changed)
474 emit attachedToChartChanged(attachedToChart: true);
475}
476
477/*!
478 Returns \c true, if the legend is attached to a chart.
479 */
480bool QLegend::isAttachedToChart()
481{
482 return d_ptr->m_attachedToChart;
483}
484
485/*!
486 Sets the visibility of the legend background to \a visible.
487 */
488void QLegend::setBackgroundVisible(bool visible)
489{
490 if (d_ptr->m_backgroundVisible != visible) {
491 d_ptr->m_backgroundVisible = visible;
492 update();
493 emit backgroundVisibleChanged(visible);
494 }
495}
496
497/*!
498 Returns the visibility of the legend background.
499 */
500bool QLegend::isBackgroundVisible() const
501{
502 return d_ptr->m_backgroundVisible;
503}
504
505/*!
506 Returns the list of markers in the legend. The list can be filtered by specifying
507 the \a series for which the markers are returned.
508*/
509QList<QLegendMarker*> QLegend::markers(QAbstractSeries *series) const
510{
511 return d_ptr->markers(series);
512}
513
514bool QLegend::reverseMarkers()
515{
516 return d_ptr->m_reverseMarkers;
517}
518
519void QLegend::setReverseMarkers(bool reverseMarkers)
520{
521 if (d_ptr->m_reverseMarkers != reverseMarkers) {
522 d_ptr->m_reverseMarkers = reverseMarkers;
523 layout()->invalidate();
524 emit reverseMarkersChanged(reverseMarkers);
525 }
526}
527
528/*!
529 Returns whether the tooltips are shown for the legend labels
530 when they are elided.
531*/
532
533bool QLegend::showToolTips() const
534{
535 return d_ptr->m_showToolTips;
536}
537
538/*!
539 When \a show is \c true, the legend labels will show a tooltip when
540 the mouse hovers over them if the label itself is shown elided.
541 This is \c false by default.
542*/
543
544void QLegend::setShowToolTips(bool show)
545{
546 if (d_ptr->m_showToolTips != show) {
547 d_ptr->m_showToolTips = show;
548 d_ptr->updateToolTips();
549 emit showToolTipsChanged(showToolTips: show);
550 }
551}
552
553/*!
554 Returns whether the legend can be dragged or resized using a mouse when it is detached.
555
556 \sa QLegend::setInteractive()
557 \since 6.2
558*/
559
560bool QLegend::isInteractive() const
561{
562 return d_ptr->m_interactive;
563}
564
565/*!
566 When \a interactive is \c true and the legend is detached, the legend is able to be moved and
567 resized with a mouse in a similar way to a window.
568
569 The legend will automatically attach to an edge of the chart by dragging it off of that edge.
570 Double clicking an attached legend will detach it.
571 This is \c false by default.
572
573 \sa QLegend::isInteractive()
574 \since 6.2
575*/
576
577void QLegend::setInteractive(bool interactive)
578{
579 if (d_ptr->m_interactive != interactive) {
580 d_ptr->m_interactive = interactive;
581 update();
582 emit interactiveChanged(interactive);
583 }
584}
585
586QLegend::MarkerShape QLegend::markerShape() const
587{
588 return d_ptr->m_markerShape;
589}
590
591void QLegend::setMarkerShape(QLegend::MarkerShape shape)
592{
593 QLegend::MarkerShape newShape = shape;
594 if (newShape == MarkerShapeDefault)
595 newShape = MarkerShapeRectangle;
596 if (d_ptr->m_markerShape != newShape) {
597 d_ptr->m_markerShape = newShape;
598 layout()->invalidate();
599 emit markerShapeChanged(shape: newShape);
600 }
601}
602
603/*!
604 \internal
605 \a event, see QGraphicsWidget for details.
606 */
607void QLegend::hideEvent(QHideEvent *event)
608{
609 if (isAttachedToChart())
610 d_ptr->m_presenter->layout()->invalidate();
611 QGraphicsWidget::hideEvent(event);
612}
613/*!
614 \internal
615 \a event, see QGraphicsWidget for details.
616 */
617void QLegend::showEvent(QShowEvent *event)
618{
619 if (isAttachedToChart())
620 layout()->invalidate();
621 QGraphicsWidget::showEvent(event);
622 //layout activation will show the items
623}
624
625////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
626
627QLegendPrivate::QLegendPrivate(ChartPresenter *presenter, QChart *chart, QLegend *q)
628 : q_ptr(q),
629 m_presenter(presenter),
630 m_layout(new LegendLayout(q)),
631 m_resizer(new LegendMoveResizeHandler(q)),
632 m_chart(chart),
633 m_items(new QGraphicsItemGroup(q)),
634 m_alignment(Qt::AlignTop),
635 m_brush(QChartPrivate::defaultBrush()),
636 m_pen(QChartPrivate::defaultPen()),
637 m_labelBrush(QChartPrivate::defaultBrush()),
638 m_diameter(5),
639 m_attachedToChart(true),
640 m_backgroundVisible(false),
641 m_reverseMarkers(false),
642 m_showToolTips(false),
643 m_interactive(false),
644 m_markerShape(QLegend::MarkerShapeRectangle)
645{
646 m_items->setHandlesChildEvents(false);
647}
648
649QLegendPrivate::~QLegendPrivate()
650{
651 delete m_resizer;
652}
653
654void QLegendPrivate::setOffset(const QPointF &offset)
655{
656 m_layout->setOffset(x: offset.x(), y: offset.y());
657}
658
659QPointF QLegendPrivate::offset() const
660{
661 return m_layout->offset();
662}
663
664int QLegendPrivate::roundness(qreal size)
665{
666 return 100 * m_diameter / int(size);
667}
668
669QList<QLegendMarker*> QLegendPrivate::markers(QAbstractSeries *series)
670{
671 // Return all markers
672 if (!series) {
673 return m_markers;
674 }
675
676 // Create filtered list
677 QList<QLegendMarker *> markers;
678 foreach (QLegendMarker *marker, m_markers) {
679 if (marker->series() == series) {
680 markers.append(t: marker);
681 }
682 }
683 return markers;
684}
685
686qreal QLegendPrivate::maxMarkerWidth() const
687{
688 qreal maxWidth = 0.0;
689 for (int i = 0; i < m_markers.size(); i++) {
690 LegendMarkerItem *item = m_markers.at(i)->d_ptr->item();
691 if (item)
692 maxWidth = qMax(a: item->markerRect().width(), b: maxWidth);
693 }
694 return maxWidth;
695}
696
697void QLegendPrivate::handleSeriesAdded(QAbstractSeries *series)
698{
699 if (m_series.contains(t: series)) {
700 return;
701 }
702
703 QList<QLegendMarker*> newMarkers = series->d_ptr->createLegendMarkers(legend: q_ptr);
704 decorateMarkers(markers: newMarkers);
705 addMarkers(markers: newMarkers);
706
707 QObject::connect(sender: series->d_ptr.data(), SIGNAL(countChanged()), receiver: this, SLOT(handleCountChanged()));
708 QObject::connect(sender: series, SIGNAL(visibleChanged()), receiver: this, SLOT(handleSeriesVisibleChanged()));
709
710 m_series.append(t: series);
711 m_items->setVisible(false);
712 m_layout->invalidate();
713}
714
715void QLegendPrivate::handleSeriesRemoved(QAbstractSeries *series)
716{
717 if (m_series.contains(t: series)) {
718 m_series.removeOne(t: series);
719 }
720
721 // Find out, which markers to remove
722 QList<QLegendMarker *> removed;
723 foreach (QLegendMarker *m, m_markers) {
724 if (m->series() == series) {
725 removed << m;
726 }
727 }
728 removeMarkers(markers: removed);
729
730 QObject::disconnect(sender: series->d_ptr.data(), SIGNAL(countChanged()), receiver: this, SLOT(handleCountChanged()));
731 QObject::disconnect(sender: series, SIGNAL(visibleChanged()), receiver: this, SLOT(handleSeriesVisibleChanged()));
732
733 m_layout->invalidate();
734}
735
736void QLegendPrivate::handleSeriesVisibleChanged()
737{
738 QAbstractSeries *series = qobject_cast<QAbstractSeries *> (object: sender());
739 Q_ASSERT(series);
740
741 foreach (QLegendMarker *marker, m_markers) {
742 if (marker->series() == series) {
743 marker->setVisible(series->isVisible());
744 }
745 }
746
747 if (m_chart->isVisible())
748 m_layout->invalidate();
749}
750
751QObject *QLegendPrivate::relatedObject(const QLegendMarker *l)
752{
753 return l->d_ptr->relatedObject();
754}
755
756// Find equivalent QLegendMarker by checking for relatedObject()
757static int indexOfEquivalent(const QLegendMarker *needle,
758 const QList<QLegendMarker *> &hayStack)
759{
760 const QObject *needleObject = QLegendPrivate::relatedObject(l: needle);
761 for (int i = 0, size = hayStack.size(); i < size; ++i) {
762 if (QLegendPrivate::relatedObject(l: hayStack.at(i)) == needleObject)
763 return i;
764 }
765 return -1;
766}
767
768// Find QLegendMarker for series
769static int indexOfSeries(const QAbstractSeries *series,
770 const QList<QLegendMarker *> &hayStack)
771{
772 for (int i = 0, size = hayStack.size(); i < size; ++i) {
773 if (hayStack.at(i)->series() == series)
774 return i;
775 }
776 return -1;
777}
778
779void QLegendPrivate::handleCountChanged()
780{
781 // Here we handle the changes in marker count.
782 // Can happen for example when pieslice(s) have been added to or removed from pieseries.
783
784 QAbstractSeriesPrivate *seriesP = qobject_cast<QAbstractSeriesPrivate *>(object: sender());
785 QAbstractSeries *series = seriesP->q_ptr;
786 QList<QLegendMarker *> createdMarkers = seriesP->createLegendMarkers(legend: q_ptr);
787 QList<bool> isNew(createdMarkers.size(), true);
788
789 const int pos = indexOfSeries(series, hayStack: m_markers);
790 // Remove markers of the series from m_markers and check against the newly
791 // created ones.
792 if (pos != -1) {
793 while (pos < m_markers.size() && m_markers.at(i: pos)->series() == series) {
794 QLegendMarker *oldMarker = m_markers.takeAt(i: pos);
795 const int newIndex = indexOfEquivalent(needle: oldMarker, hayStack: createdMarkers);
796 if (newIndex == -1) {
797 removeMarkerHelper(marker: oldMarker); // no longer exists
798 } else {
799 // Replace newly created marker by its equivalent
800 delete createdMarkers[newIndex];
801 createdMarkers[newIndex] = oldMarker;
802 isNew[newIndex] = false;
803 }
804 }
805 }
806
807 for (int i = 0, size = createdMarkers.size(); i < size; ++i) {
808 if (isNew.at(i)) {
809 insertMarkerHelper(marker: createdMarkers.at(i));
810 decorateMarker(marker: createdMarkers.at(i));
811 }
812 }
813
814 // Re-insert createdMarkers into m_markers in correct order.
815 if (pos == -1 || pos == m_markers.size()) {
816 m_markers.append(l: createdMarkers);
817 } else {
818 for (int c = createdMarkers.size() - 1; c >= 0; --c)
819 m_markers.insert(i: pos, t: createdMarkers.at(i: c));
820 }
821
822 q_ptr->layout()->invalidate();
823}
824
825// Helper function for marker insertion except m_markers handling
826void QLegendPrivate::insertMarkerHelper(QLegendMarker *marker)
827{
828 LegendMarkerItem *item = marker->d_ptr->item();
829 m_items->addToGroup(item);
830 m_markerHash.insert(key: item, value: marker);
831}
832
833void QLegendPrivate::addMarkers(const QList<QLegendMarker *> &markers)
834{
835 for (auto *marker : markers) {
836 insertMarkerHelper(marker);
837 m_markers << marker;
838 }
839}
840
841// Helper function for marker removal except m_markers handling
842void QLegendPrivate::removeMarkerHelper(QLegendMarker *marker)
843{
844 LegendMarkerItem *item = marker->d_ptr->item();
845 item->setVisible(false);
846 m_items->removeFromGroup(item);
847 m_markerHash.remove(key: item);
848 delete marker;
849}
850
851void QLegendPrivate::removeMarkers(const QList<QLegendMarker *> &markers)
852{
853 for (auto *marker : markers) {
854 m_markers.removeOne(t: marker);
855 removeMarkerHelper(marker);
856 }
857}
858
859void QLegendPrivate::decorateMarker(QLegendMarker *marker)
860{
861 marker->setFont(m_font);
862 marker->setLabelBrush(m_labelBrush);
863}
864
865void QLegendPrivate::decorateMarkers(const QList<QLegendMarker *> &markers)
866{
867 for (auto *marker : markers)
868 decorateMarker(marker);
869}
870
871void QLegendPrivate::updateToolTips()
872{
873 foreach (QLegendMarker *m, m_markers) {
874 if (m->d_ptr->m_item->displayedLabel() != m->label())
875 m->d_ptr->m_item->setToolTip(m->label());
876 else
877 m->d_ptr->m_item->setToolTip(QString());
878 }
879}
880
881QT_END_NAMESPACE
882
883#include "moc_qlegend.cpp"
884#include "moc_qlegend_p.cpp"
885

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtcharts/src/charts/legend/qlegend.cpp