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

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