1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Charts module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include <QtCharts/QXYSeries>
31#include <private/qxyseries_p.h>
32#include <private/abstractdomain_p.h>
33#include <QtCharts/QValueAxis>
34#include <private/xychart_p.h>
35#include <QtCharts/QXYLegendMarker>
36#include <private/charthelpers_p.h>
37#include <private/qchart_p.h>
38#include <QtGui/QPainter>
39
40QT_CHARTS_BEGIN_NAMESPACE
41
42/*!
43 \class QXYSeries
44 \inmodule QtCharts
45 \brief The QXYSeries class is a base class for line, spline, and scatter
46 series.
47*/
48/*!
49 \qmltype XYSeries
50 \instantiates QXYSeries
51 \inqmlmodule QtCharts
52
53 \inherits AbstractSeries
54
55 \brief A base type for line, spline, and scatter series.
56*/
57
58/*!
59 \qmlproperty AbstractAxis XYSeries::axisX
60 The x-axis used for the series. If you leave both axisX and axisXTop
61 undefined, a value axis is created for the series.
62 \sa axisXTop, ValueAxis
63*/
64
65/*!
66 \qmlproperty AbstractAxis XYSeries::axisY
67 The y-axis used for the series. If you leave both axisY and axisYRight
68 undefined, a value axis is created for the series.
69 \sa axisYRight, ValueAxis
70*/
71
72/*!
73 \qmlproperty AbstractAxis XYSeries::axisXTop
74 The x-axis used for the series, drawn on top of the chart view.
75
76 \note You can only provide either axisX or axisXTop, not both.
77 \sa axisX
78*/
79
80/*!
81 \qmlproperty AbstractAxis XYSeries::axisYRight
82 The y-axis used for the series, drawn to the right on the chart view.
83
84 \note You can only provide either axisY or axisYRight, not both.
85 \sa axisY
86*/
87
88/*!
89 \qmlproperty AbstractAxis XYSeries::axisAngular
90 The angular axis used for the series, drawn around the polar chart view.
91 \sa axisX
92*/
93
94/*!
95 \qmlproperty AbstractAxis XYSeries::axisRadial
96 The radial axis used for the series, drawn inside the polar chart view.
97 \sa axisY
98*/
99
100/*!
101 \property QXYSeries::pointsVisible
102 \brief Whether the data points are visible and should be drawn.
103*/
104/*!
105 \qmlproperty bool XYSeries::pointsVisible
106 Whether the data points are visible and should be drawn.
107*/
108
109/*!
110 \fn QPen QXYSeries::pen() const
111 Returns the pen used to draw the outline of the data points for the series.
112 \sa setPen()
113*/
114
115/*!
116 \fn QBrush QXYSeries::brush() const
117 Returns the brush used to fill the data points for the series.
118 \sa setBrush()
119*/
120
121/*!
122 \property QXYSeries::color
123 \brief The color of the series.
124
125 This is the line (pen) color in case of QLineSeries or QSplineSeries and the
126 fill (brush) color in case of QScatterSeries or QAreaSeries.
127 \sa pen(), brush()
128*/
129/*!
130 \qmlproperty color XYSeries::color
131 The color of the series. This is the line (pen) color in case of LineSeries
132 or SplineSeries and the fill (brush) color in case of ScatterSeries or
133 AreaSeries.
134*/
135
136/*!
137 \property QXYSeries::pointLabelsFormat
138 \brief The format used for showing labels with data points.
139
140 QXYSeries supports the following format tags:
141 \table
142 \row
143 \li @xPoint \li The x-coordinate of the data point.
144 \row
145 \li @yPoint \li The y-coordinate of the data point.
146 \endtable
147
148 For example, the following usage of the format tags would produce labels
149 that display the data point shown inside brackets separated by a comma
150 (x, y):
151
152 \code
153 series->setPointLabelsFormat("(@xPoint, @yPoint)");
154 \endcode
155
156 By default, the labels' format is set to \c {@xPoint, @yPoint}. The labels
157 are shown on the plot area, and the labels on the edge of the plot area are
158 cut. If the points are close to each other, the labels may overlap.
159
160 \sa pointLabelsVisible, pointLabelsFont, pointLabelsColor
161*/
162/*!
163 \qmlproperty string XYSeries::pointLabelsFormat
164 The format used for showing labels with data points.
165
166 \sa pointLabelsVisible, pointLabelsFont, pointLabelsColor
167*/
168/*!
169 \fn void QXYSeries::pointLabelsFormatChanged(const QString &format)
170 This signal is emitted when the format of data point labels changes to
171 \a format.
172*/
173
174/*!
175 \property QXYSeries::pointLabelsVisible
176 \brief The visibility of data point labels.
177
178 This property is \c false by default.
179
180 \sa pointLabelsFormat, pointLabelsClipping
181*/
182/*!
183 \qmlproperty bool XYSeries::pointLabelsVisible
184 The visibility of data point labels. This property is \c false by default.
185
186 \sa pointLabelsFormat, pointLabelsClipping
187*/
188/*!
189 \fn void QXYSeries::pointLabelsVisibilityChanged(bool visible)
190 This signal is emitted when the visibility of the data point labels
191 changes to \a visible.
192*/
193
194/*!
195 \property QXYSeries::pointLabelsFont
196 \brief The font used for data point labels.
197
198 \sa pointLabelsFormat
199*/
200/*!
201 \qmlproperty font XYSeries::pointLabelsFont
202 The font used for data point labels.
203
204 \sa pointLabelsFormat
205*/
206/*!
207 \fn void QXYSeries::pointLabelsFontChanged(const QFont &font);
208 This signal is emitted when the font used for data point labels changes to
209 \a font.
210*/
211
212/*!
213 \property QXYSeries::pointLabelsColor
214 \brief The color used for data point labels. By default, the color is the color of the brush
215 defined in theme for labels.
216
217 \sa pointLabelsFormat
218*/
219/*!
220 \qmlproperty font XYSeries::pointLabelsColor
221 The color used for data point labels. By default, the color is the color of the brush
222 defined in theme for labels.
223
224 \sa pointLabelsFormat
225*/
226/*!
227 \fn void QXYSeries::pointLabelsColorChanged(const QColor &color);
228 This signal is emitted when the color used for data point labels changes to
229 \a color.
230*/
231
232/*!
233 \property QXYSeries::pointLabelsClipping
234 \brief The clipping for data point labels.
235
236 This property is \c true by default. The labels on the edge of the plot area
237 are cut when clipping is enabled.
238
239 \sa pointLabelsVisible
240*/
241/*!
242 \qmlproperty bool XYSeries::pointLabelsClipping
243 The clipping for data point labels. This property is \c true by default. The
244 labels on the edge of the plot area are cut when clipping is enabled.
245
246 \sa pointLabelsVisible
247*/
248/*!
249 \fn void QXYSeries::pointLabelsClippingChanged(bool clipping)
250 This signal is emitted when the clipping of the data point labels changes to
251 \a clipping.
252*/
253
254/*!
255 \fn void QXYSeries::clicked(const QPointF& point)
256 This signal is emitted when the user triggers a mouse event by
257 clicking the point \a point in the chart.
258
259 \sa pressed(), released(), doubleClicked()
260*/
261/*!
262 \qmlsignal XYSeries::clicked(point point)
263 This signal is emitted when the user triggers a mouse event by clicking the
264 point \a point in the chart. For example:
265 \code
266 LineSeries {
267 XYPoint { x: 0; y: 0 }
268 XYPoint { x: 1.1; y: 2.1 }
269 onClicked: console.log("onClicked: " + point.x + ", " + point.y);
270 }
271 \endcode
272
273 The corresponding signal handler is \c onClicked().
274
275 \sa pressed(), released(), doubleClicked()
276*/
277
278/*!
279 \fn void QXYSeries::hovered(const QPointF &point, bool state)
280 This signal is emitted when a mouse is hovered over the point \a point in
281 the chart. When the mouse moves over the point, \a state turns \c true,
282 and when the mouse moves away again, it turns \c false.
283*/
284/*!
285 \qmlsignal XYSeries::hovered(point point, bool state)
286 This signal is emitted when a mouse is hovered over the point \a point in
287 the chart. When the mouse moves over the point, \a state turns \c true,
288 and when the mouse moves away again, it turns \c false.
289
290 The corresponding signal handler is \c onHovered().
291*/
292
293/*!
294 \fn void QXYSeries::pressed(const QPointF& point)
295 This signal is emitted when the user presses the data point \a point in the
296 chart and holds down the mouse button.
297
298 \sa clicked(), released(), doubleClicked()
299*/
300/*!
301 \qmlsignal XYSeries::pressed(point point)
302 This signal is emitted when the user presses the data point \a point in the
303 chart and holds down the mouse button. For example:
304 \code
305 LineSeries {
306 XYPoint { x: 0; y: 0 }
307 XYPoint { x: 1.1; y: 2.1 }
308 onPressed: console.log("onPressed: " + point.x + ", " + point.y);
309 }
310 \endcode
311
312 The corresponding signal handler is \c onPressed().
313
314 \sa clicked(), released(), doubleClicked()
315*/
316
317/*!
318 \fn void QXYSeries::released(const QPointF& point)
319 This signal is emitted when the user releases the mouse press on the data
320 point specified by \a point.
321 \sa pressed(), clicked(), doubleClicked()
322*/
323/*!
324 \qmlsignal XYSeries::released(point point)
325 This signal is emitted when the user releases the mouse press on the data
326 point specified by \a point.
327 For example:
328 \code
329 LineSeries {
330 XYPoint { x: 0; y: 0 }
331 XYPoint { x: 1.1; y: 2.1 }
332 onReleased: console.log("onReleased: " + point.x + ", " + point.y);
333 }
334 \endcode
335
336 The corresponding signal handler is \c onReleased().
337
338 \sa pressed(), clicked(), doubleClicked()
339*/
340
341/*!
342 \fn void QXYSeries::doubleClicked(const QPointF& point)
343 This signal is emitted when the user double-clicks the data point \a point
344 in the chart. The \a point is the point where the first press was triggered.
345 \sa pressed(), released(), clicked()
346*/
347/*!
348 \qmlsignal XYSeries::doubleClicked(point point)
349 This signal is emitted when the user double-clicks the data point \a point
350 in the chart. The \a point is the point where the first press was triggered.
351 For example:
352 \code
353 LineSeries {
354 XYPoint { x: 0; y: 0 }
355 XYPoint { x: 1.1; y: 2.1 }
356 onDoubleClicked: console.log("onDoubleClicked: " + point.x + ", " + point.y);
357 }
358 \endcode
359
360 The corresponding signal handler is \c onDoubleClicked().
361
362 \sa pressed(), released(), clicked()
363*/
364
365/*!
366 \fn void QXYSeries::pointReplaced(int index)
367 This signal is emitted when a point is replaced at the position specified by
368 \a index.
369 \sa replace()
370*/
371/*!
372 \qmlsignal XYSeries::pointReplaced(int index)
373 This signal is emitted when a point is replaced at the position specified by
374 \a index.
375
376 The corresponding signal handler is \c onPointReplaced().
377*/
378
379/*!
380 \fn void QXYSeries::pointsReplaced()
381 This signal is emitted when all points are replaced with other points.
382 \sa replace()
383*/
384/*!
385 \qmlsignal XYSeries::pointsReplaced()
386 This signal is emitted when all points are replaced with other points.
387
388 The corresponding signal handler is \c onPointsReplaced().
389*/
390
391/*!
392 \fn void QXYSeries::pointAdded(int index)
393 This signal is emitted when a point is added at the position specified by
394 \a index.
395 \sa append(), insert()
396*/
397/*!
398 \qmlsignal XYSeries::pointAdded(int index)
399 This signal is emitted when a point is added at the position specified by
400 \a index.
401
402 The corresponding signal handler is \c onPointAdded().
403*/
404
405/*!
406 \fn void QXYSeries::pointRemoved(int index)
407 This signal is emitted when a point is removed from the position specified
408 by \a index.
409 \sa remove()
410*/
411
412/*!
413 \qmlsignal XYSeries::pointRemoved(int index)
414 This signal is emitted when a point is removed from the position specified
415 by \a index.
416
417 The corresponding signal handler is \c onPointRemoved().
418*/
419
420/*!
421 \fn void QXYSeries::pointsRemoved(int index, int count)
422 This signal is emitted when the number of points specified by \a count
423 is removed starting at the position specified by \a index.
424 \sa removePoints(), clear()
425*/
426
427/*!
428 \qmlsignal XYSeries::pointsRemoved(int index, int count)
429 This signal is emitted when the number of points specified by \a count
430 is removed starting at the position specified by \a index.
431
432 The corresponding signal handler is \c onPointRemoved().
433*/
434
435/*!
436 \fn void QXYSeries::colorChanged(QColor color)
437 This signal is emitted when the line (pen) color changes to \a color.
438*/
439
440/*!
441 \fn void QXYSeries::penChanged(const QPen &pen)
442 This signal is emitted when the pen changes to \a pen.
443*/
444
445/*!
446 \fn void QXYSeriesPrivate::updated()
447 \internal
448*/
449
450/*!
451 \qmlmethod XYSeries::append(real x, real y)
452 Appends a point with the coordinates \a x and \a y to the series.
453*/
454
455/*!
456 \qmlmethod XYSeries::replace(real oldX, real oldY, real newX, real newY)
457 Replaces the point with the coordinates \a oldX and \a oldY with the point
458 with the coordinates \a newX and \a newY. Does nothing if the old point does
459 not exist.
460*/
461
462/*!
463 \qmlmethod XYSeries::remove(real x, real y)
464 Removes the point with the coordinates \a x and \a y from the series. Does
465 nothing if the point does not exist.
466*/
467
468/*!
469 \qmlmethod XYSeries::remove(int index)
470 Removes the point at the position specified by \a index from the series.
471*/
472
473/*!
474 \qmlmethod XYSeries::removePoints(int index, int count)
475 Removes the number of points specified by \a count from the series starting
476 at the position specified by \a index.
477*/
478
479/*!
480 \qmlmethod XYSeries::insert(int index, real x, real y)
481 Inserts a point with the coordinates \a x and \a y to the position specified
482 by \a index in the series. If the index is 0 or less than 0, the point is
483 prepended to the list of points. If the index is equal to or greater than
484 than the number of points in the series, the point is appended to the
485 list of points.
486*/
487
488/*!
489 \qmlmethod QPointF XYSeries::at(int index)
490 Returns the point at the position specified by \a index. Returns (0, 0) if
491 the index is not valid.
492*/
493
494/*!
495 \internal
496
497 Constructs an empty series object that is a child of \a parent.
498 When the series object is added to QChart, instance ownerships is transferred.
499*/
500QXYSeries::QXYSeries(QXYSeriesPrivate &d, QObject *parent)
501 : QAbstractSeries(d, parent)
502{
503}
504
505/*!
506 Deletes the series. Series added to QChart instances are owned by them,
507 and are deleted when the QChart instances are deleted.
508*/
509QXYSeries::~QXYSeries()
510{
511}
512
513/*!
514 Adds the data point with the coordinates \a x and \a y to the series.
515 */
516void QXYSeries::append(qreal x, qreal y)
517{
518 append(point: QPointF(x, y));
519}
520
521/*!
522 \overload
523 Adds the data point \a point to the series.
524 */
525void QXYSeries::append(const QPointF &point)
526{
527 Q_D(QXYSeries);
528
529 if (isValidValue(point)) {
530 d->m_points << point;
531 emit pointAdded(index: d->m_points.count() - 1);
532 }
533}
534
535/*!
536 \overload
537 Adds the list of data points specified by \a points to the series.
538 */
539void QXYSeries::append(const QList<QPointF> &points)
540{
541 foreach (const QPointF &point , points)
542 append(point);
543}
544
545/*!
546 Replaces the point with the coordinates \a oldX and \a oldY with the point
547 with the coordinates \a newX and \a newY. Does nothing if the old point does
548 not exist.
549
550 \sa pointReplaced()
551*/
552void QXYSeries::replace(qreal oldX, qreal oldY, qreal newX, qreal newY)
553{
554 replace(oldPoint: QPointF(oldX, oldY), newPoint: QPointF(newX, newY));
555}
556
557/*!
558 Replaces the point specified by \a oldPoint with the one specified by
559 \a newPoint.
560 \sa pointReplaced()
561*/
562void QXYSeries::replace(const QPointF &oldPoint, const QPointF &newPoint)
563{
564 Q_D(QXYSeries);
565 int index = d->m_points.indexOf(t: oldPoint);
566 if (index == -1)
567 return;
568 replace(index, newPoint);
569}
570
571/*!
572 Replaces the point at the position specified by \a index with the point that
573 has the coordinates \a newX and \a newY.
574 \sa pointReplaced()
575*/
576void QXYSeries::replace(int index, qreal newX, qreal newY)
577{
578 replace(index, newPoint: QPointF(newX, newY));
579}
580
581/*!
582 Replaces the point at the position specified by \a index with the point
583 specified by \a newPoint.
584 \sa pointReplaced()
585*/
586void QXYSeries::replace(int index, const QPointF &newPoint)
587{
588 Q_D(QXYSeries);
589 if (isValidValue(point: newPoint)) {
590 d->m_points[index] = newPoint;
591 emit pointReplaced(index);
592 }
593}
594
595/*!
596 Replaces the current points with the points specified by \a points.
597 \note This is much faster than replacing data points one by one,
598 or first clearing all data, and then appending the new data. Emits QXYSeries::pointsReplaced()
599 when the points have been replaced. However, note that using the overload that takes
600 \c{QVector<QPointF>} as parameter is faster than using this overload.
601 \sa pointsReplaced()
602*/
603void QXYSeries::replace(QList<QPointF> points)
604{
605 replace(points: points.toVector());
606}
607
608/*!
609 Replaces the current points with the points specified by \a points.
610 \note This is much faster than replacing data points one by one,
611 or first clearing all data, and then appending the new data. Emits QXYSeries::pointsReplaced()
612 when the points have been replaced.
613 \sa pointsReplaced()
614*/
615void QXYSeries::replace(QVector<QPointF> points)
616{
617 Q_D(QXYSeries);
618 d->m_points = points;
619 emit pointsReplaced();
620}
621
622/*!
623 Removes the point that has the coordinates \a x and \a y from the series.
624 \sa pointRemoved()
625*/
626void QXYSeries::remove(qreal x, qreal y)
627{
628 remove(point: QPointF(x, y));
629}
630
631/*!
632 Removes the data point \a point from the series.
633 \sa pointRemoved()
634*/
635void QXYSeries::remove(const QPointF &point)
636{
637 Q_D(QXYSeries);
638 int index = d->m_points.indexOf(t: point);
639 if (index == -1)
640 return;
641 remove(index);
642}
643
644/*!
645 Removes the point at the position specified by \a index from the series.
646 \sa pointRemoved()
647*/
648void QXYSeries::remove(int index)
649{
650 Q_D(QXYSeries);
651 d->m_points.remove(i: index);
652 emit pointRemoved(index);
653}
654
655/*!
656 Removes the number of points specified by \a count from the series starting at
657 the position specified by \a index.
658 \sa pointsRemoved()
659*/
660void QXYSeries::removePoints(int index, int count)
661{
662 // This function doesn't overload remove as there is chance for it to get mixed up with
663 // remove(qreal, qreal) overload in some implicit casting cases.
664 Q_D(QXYSeries);
665 if (count > 0) {
666 d->m_points.remove(i: index, n: count);
667 emit pointsRemoved(index, count);
668 }
669}
670
671/*!
672 Inserts the data point \a point in the series at the position specified by
673 \a index.
674 \sa pointAdded()
675*/
676void QXYSeries::insert(int index, const QPointF &point)
677{
678 Q_D(QXYSeries);
679 if (isValidValue(point)) {
680 index = qMax(a: 0, b: qMin(a: index, b: d->m_points.size()));
681 d->m_points.insert(i: index, t: point);
682 emit pointAdded(index);
683 }
684}
685
686/*!
687 Removes all points from the series.
688 \sa pointsRemoved()
689*/
690void QXYSeries::clear()
691{
692 Q_D(QXYSeries);
693 removePoints(index: 0, count: d->m_points.size());
694}
695
696/*!
697 Returns the points in the series as a list.
698 Use pointsVector() for better performance.
699*/
700QList<QPointF> QXYSeries::points() const
701{
702 Q_D(const QXYSeries);
703 return d->m_points.toList();
704}
705
706/*!
707 Returns the points in the series as a vector.
708 This is more efficient than calling points().
709*/
710QVector<QPointF> QXYSeries::pointsVector() const
711{
712 Q_D(const QXYSeries);
713 return d->m_points;
714}
715
716/*!
717 Returns the data point at the position specified by \a index in the internal
718 points vector.
719*/
720const QPointF &QXYSeries::at(int index) const
721{
722 Q_D(const QXYSeries);
723 return d->m_points.at(i: index);
724}
725
726/*!
727 Returns the number of data points in a series.
728*/
729int QXYSeries::count() const
730{
731 Q_D(const QXYSeries);
732 return d->m_points.count();
733}
734
735
736/*!
737 Sets the pen used for drawing points on the chart to \a pen. If the pen is
738 not defined, the pen from the chart theme is used.
739 \sa QChart::setTheme()
740*/
741void QXYSeries::setPen(const QPen &pen)
742{
743 Q_D(QXYSeries);
744 if (d->m_pen != pen) {
745 bool emitColorChanged = d->m_pen.color() != pen.color();
746 d->m_pen = pen;
747 emit d->updated();
748 if (emitColorChanged)
749 emit colorChanged(color: pen.color());
750 emit penChanged(pen);
751 }
752}
753
754QPen QXYSeries::pen() const
755{
756 Q_D(const QXYSeries);
757 if (d->m_pen == QChartPrivate::defaultPen())
758 return QPen();
759 else
760 return d->m_pen;
761}
762
763/*!
764 Sets the brush used for drawing points on the chart to \a brush. If the
765 brush is not defined, the brush from the chart theme setting is used.
766 \sa QChart::setTheme()
767*/
768void QXYSeries::setBrush(const QBrush &brush)
769{
770 Q_D(QXYSeries);
771 if (d->m_brush != brush) {
772 d->m_brush = brush;
773 emit d->updated();
774 }
775}
776
777QBrush QXYSeries::brush() const
778{
779 Q_D(const QXYSeries);
780 if (d->m_brush == QChartPrivate::defaultBrush())
781 return QBrush();
782 else
783 return d->m_brush;
784}
785
786void QXYSeries::setColor(const QColor &color)
787{
788 QPen p = pen();
789 if (p.color() != color) {
790 p.setColor(color);
791 setPen(p);
792 }
793}
794
795QColor QXYSeries::color() const
796{
797 return pen().color();
798}
799
800void QXYSeries::setPointsVisible(bool visible)
801{
802 Q_D(QXYSeries);
803 if (d->m_pointsVisible != visible) {
804 d->m_pointsVisible = visible;
805 emit d->updated();
806 }
807}
808
809bool QXYSeries::pointsVisible() const
810{
811 Q_D(const QXYSeries);
812 return d->m_pointsVisible;
813}
814
815void QXYSeries::setPointLabelsFormat(const QString &format)
816{
817 Q_D(QXYSeries);
818 if (d->m_pointLabelsFormat != format) {
819 d->m_pointLabelsFormat = format;
820 emit pointLabelsFormatChanged(format);
821 }
822}
823
824QString QXYSeries::pointLabelsFormat() const
825{
826 Q_D(const QXYSeries);
827 return d->m_pointLabelsFormat;
828}
829
830void QXYSeries::setPointLabelsVisible(bool visible)
831{
832 Q_D(QXYSeries);
833 if (d->m_pointLabelsVisible != visible) {
834 d->m_pointLabelsVisible = visible;
835 emit pointLabelsVisibilityChanged(visible);
836 }
837}
838
839bool QXYSeries::pointLabelsVisible() const
840{
841 Q_D(const QXYSeries);
842 return d->m_pointLabelsVisible;
843}
844
845void QXYSeries::setPointLabelsFont(const QFont &font)
846{
847 Q_D(QXYSeries);
848 if (d->m_pointLabelsFont != font) {
849 d->m_pointLabelsFont = font;
850 emit pointLabelsFontChanged(font);
851 }
852}
853
854QFont QXYSeries::pointLabelsFont() const
855{
856 Q_D(const QXYSeries);
857 return d->m_pointLabelsFont;
858}
859
860void QXYSeries::setPointLabelsColor(const QColor &color)
861{
862 Q_D(QXYSeries);
863 if (d->m_pointLabelsColor != color) {
864 d->m_pointLabelsColor = color;
865 emit pointLabelsColorChanged(color);
866 }
867}
868
869QColor QXYSeries::pointLabelsColor() const
870{
871 Q_D(const QXYSeries);
872 if (d->m_pointLabelsColor == QChartPrivate::defaultPen().color())
873 return QPen().color();
874 else
875 return d->m_pointLabelsColor;
876}
877
878void QXYSeries::setPointLabelsClipping(bool enabled)
879{
880 Q_D(QXYSeries);
881 if (d->m_pointLabelsClipping != enabled) {
882 d->m_pointLabelsClipping = enabled;
883 emit pointLabelsClippingChanged(clipping: enabled);
884 }
885}
886
887bool QXYSeries::pointLabelsClipping() const
888{
889 Q_D(const QXYSeries);
890 return d->m_pointLabelsClipping;
891}
892
893/*!
894 Stream operator for adding the data point \a point to the series.
895 \sa append()
896*/
897QXYSeries &QXYSeries::operator<< (const QPointF &point)
898{
899 append(point);
900 return *this;
901}
902
903
904/*!
905 Stream operator for adding the list of data points specified by \a points
906 to the series.
907 \sa append()
908*/
909
910QXYSeries &QXYSeries::operator<< (const QList<QPointF>& points)
911{
912 append(points);
913 return *this;
914}
915
916//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
917
918
919QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q)
920 : QAbstractSeriesPrivate(q),
921 m_pen(QChartPrivate::defaultPen()),
922 m_brush(QChartPrivate::defaultBrush()),
923 m_pointsVisible(false),
924 m_pointLabelsFormat(QLatin1String("@xPoint, @yPoint")),
925 m_pointLabelsVisible(false),
926 m_pointLabelsFont(QChartPrivate::defaultFont()),
927 m_pointLabelsColor(QChartPrivate::defaultPen().color()),
928 m_pointLabelsClipping(true)
929{
930}
931
932void QXYSeriesPrivate::initializeDomain()
933{
934 qreal minX(0);
935 qreal minY(0);
936 qreal maxX(1);
937 qreal maxY(1);
938
939 Q_Q(QXYSeries);
940
941 const QVector<QPointF> &points = q->pointsVector();
942
943 if (!points.isEmpty()) {
944 minX = points[0].x();
945 minY = points[0].y();
946 maxX = minX;
947 maxY = minY;
948
949 for (int i = 0; i < points.count(); i++) {
950 qreal x = points[i].x();
951 qreal y = points[i].y();
952 minX = qMin(a: minX, b: x);
953 minY = qMin(a: minY, b: y);
954 maxX = qMax(a: maxX, b: x);
955 maxY = qMax(a: maxY, b: y);
956 }
957 }
958
959 domain()->setRange(minX, maxX, minY, maxY);
960}
961
962QList<QLegendMarker*> QXYSeriesPrivate::createLegendMarkers(QLegend* legend)
963{
964 Q_Q(QXYSeries);
965 QList<QLegendMarker*> list;
966 return list << new QXYLegendMarker(q,legend);
967}
968
969void QXYSeriesPrivate::initializeAxes()
970{
971
972}
973
974QAbstractAxis::AxisType QXYSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
975{
976 Q_UNUSED(orientation);
977 return QAbstractAxis::AxisTypeValue;
978}
979
980QAbstractAxis* QXYSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
981{
982 Q_UNUSED(orientation);
983 return new QValueAxis;
984}
985
986void QXYSeriesPrivate::initializeAnimations(QtCharts::QChart::AnimationOptions options,
987 int duration, QEasingCurve &curve)
988{
989 XYChart *item = static_cast<XYChart *>(m_item.data());
990 Q_ASSERT(item);
991 if (item->animation())
992 item->animation()->stopAndDestroyLater();
993
994 if (options.testFlag(flag: QChart::SeriesAnimations))
995 item->setAnimation(new XYAnimation(item, duration, curve));
996 else
997 item->setAnimation(0);
998 QAbstractSeriesPrivate::initializeAnimations(options, duration, curve);
999}
1000
1001void QXYSeriesPrivate::drawSeriesPointLabels(QPainter *painter, const QVector<QPointF> &points,
1002 const int offset)
1003{
1004 if (points.size() == 0)
1005 return;
1006
1007 static const QString xPointTag(QLatin1String("@xPoint"));
1008 static const QString yPointTag(QLatin1String("@yPoint"));
1009 const int labelOffset = offset + 2;
1010
1011 QFont f(m_pointLabelsFont);
1012 f.setPixelSize(QFontInfo(m_pointLabelsFont).pixelSize());
1013 painter->setFont(f);
1014 painter->setPen(QPen(m_pointLabelsColor));
1015 QFontMetrics fm(painter->font());
1016 // m_points is used for the label here as it has the series point information
1017 // points variable passed is used for positioning because it has the coordinates
1018 const int pointCount = qMin(a: points.size(), b: m_points.size());
1019 for (int i(0); i < pointCount; i++) {
1020 QString pointLabel = m_pointLabelsFormat;
1021 pointLabel.replace(before: xPointTag, after: presenter()->numberToString(value: m_points.at(i).x()));
1022 pointLabel.replace(before: yPointTag, after: presenter()->numberToString(value: m_points.at(i).y()));
1023
1024 // Position text in relation to the point
1025 int pointLabelWidth = fm.horizontalAdvance(pointLabel);
1026 QPointF position(points.at(i));
1027 position.setX(position.x() - pointLabelWidth / 2);
1028 position.setY(position.y() - labelOffset);
1029
1030 painter->drawText(p: position, s: pointLabel);
1031 }
1032}
1033
1034QT_CHARTS_END_NAMESPACE
1035
1036#include "moc_qxyseries.cpp"
1037#include "moc_qxyseries_p.cpp"
1038

source code of qtcharts/src/charts/xychart/qxyseries.cpp