1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtGraphs/qxyseries.h>
5#include <private/qxyseries_p.h>
6#include <private/charthelpers_p.h>
7
8QT_BEGIN_NAMESPACE
9
10/*!
11 \class QXYSeries
12 \inmodule QtGraphs
13 \ingroup graphs_2D
14 \brief The QXYSeries class is a parent class for all x & y series classes.
15
16 In QXYSeries, data points are defined as a list of QPointF, defining X and Y positions.
17
18 \sa QLineSeries, QScatterSeries
19*/
20/*!
21 \qmltype XYSeries
22 \nativetype QXYSeries
23 \inqmlmodule QtGraphs
24 \ingroup graphs_qml_2D
25 \inherits AbstractSeries
26 \brief A parent type for all x & y series types.
27
28 In XYSeries, data points are defined as a list of point types, defining X and Y positions.
29*/
30
31/*!
32 \fn void QXYSeries::pointReplaced(qsizetype index)
33 This signal is emitted when a point is replaced at the position specified by
34 \a index.
35 \sa replace()
36*/
37/*!
38 \qmlsignal XYSeries::pointReplaced(int index)
39 This signal is emitted when a point is replaced at the position specified by
40 \a index.
41*/
42
43/*!
44 \fn void QXYSeries::pointsReplaced()
45 This signal is emitted when all points are replaced.
46*/
47/*!
48 \qmlsignal XYSeries::pointsReplaced()
49 This signal is emitted when all points are replaced.
50*/
51
52/*!
53 \qmlsignal XYSeries::colorChanged(color color)
54 This signal is emitted when the line color changes to \a color.
55*/
56
57/*!
58 \qmlsignal XYSeries::selectedColorChanged(color color)
59 This signal is emitted when the color of selected series changes to \a color.
60*/
61
62/*!
63 \qmlsignal XYSeries::selectedPointsChanged()
64 This signal is emitted when the set of selected points changes.
65*/
66
67/*!
68 \qmlsignal XYSeries::pointMarkerChanged()
69 This signal is emitted when a point is changed.
70*/
71
72/*!
73 \qmlsignal XYSeries::draggableChanged()
74 This signal is emitted when a series becomes draggable by a mouse/touch or
75 becomes fixed.
76*/
77
78QXYSeries::QXYSeries(QXYSeriesPrivate &dd, QObject *parent)
79 : QAbstractSeries(dd, parent)
80{
81 QObject::connect(sender: this, signal: &QXYSeries::selectedPointsChanged, context: this, slot: &QAbstractSeries::update);
82 QObject::connect(sender: this, signal: &QXYSeries::pointAdded, context: this, slot: &QAbstractSeries::update);
83 QObject::connect(sender: this, signal: &QXYSeries::pointReplaced, context: this, slot: &QAbstractSeries::update);
84 QObject::connect(sender: this, signal: &QXYSeries::pointsReplaced, context: this, slot: &QAbstractSeries::update);
85 QObject::connect(sender: this, signal: &QXYSeries::pointRemoved, context: this, slot: &QAbstractSeries::update);
86 QObject::connect(sender: this, signal: &QXYSeries::pointsRemoved, context: this, slot: &QAbstractSeries::update);
87}
88
89/*!
90 \qmlmethod XYSeries::append(real x, real y)
91 Appends a point with the coordinates \a x and \a y to the series.
92*/
93/*!
94 Appends a point with the coordinates \a x and \a y to the series.
95*/
96void QXYSeries::append(qreal x, qreal y)
97{
98 append(point: QPointF(x, y));
99}
100
101/*!
102 \qmlmethod XYSeries::append(point point)
103 Appends a point with the coordinates \a point to the series.
104*/
105/*!
106 Appends a point with the coordinates \a point to the series.
107*/
108void QXYSeries::append(QPointF point)
109{
110 Q_D(QXYSeries);
111 if (isValidValue(point)) {
112 if (d->m_graphTransition && d->m_graphTransition->initialized()
113 && d->m_graphTransition->contains(type: QGraphAnimation::GraphAnimationType::GraphPoint)) {
114 d->m_graphTransition->stop();
115 d->m_graphTransition->onPointChanged(type: QGraphTransition::TransitionType::PointAdded,
116 index: d->m_points.size(),
117 point);
118 } else {
119 d->m_points << point;
120 emit pointAdded(index: d->m_points.size() - 1);
121 emit countChanged();
122 }
123 }
124}
125
126/*!
127 \qmlmethod XYSeries::append(list<point> points)
128 Appends points with the coordinates \a points to the series.
129*/
130/*!
131 Appends points with the coordinates \a points to the series.
132*/
133void QXYSeries::append(const QList<QPointF> &points)
134{
135 for (const QPointF &point : points)
136 append(point);
137}
138
139/*!
140 \qmlmethod XYSeries::replace(real oldX, real oldY, real newX, real newY)
141 Replaces the point with the coordinates \a oldX and \a oldY with the point
142 with the coordinates \a newX and \a newY. Does nothing if the old point does
143 not exist.
144*/
145/*!
146 Replaces the point with the coordinates \a oldX and \a oldY with the point
147 with the coordinates \a newX and \a newY. Does nothing if the old point does
148 not exist.
149*/
150void QXYSeries::replace(qreal oldX, qreal oldY, qreal newX, qreal newY)
151{
152 replace(oldPoint: QPointF(oldX, oldY), newPoint: QPointF(newX, newY));
153}
154
155/*!
156 \qmlmethod XYSeries::replace(point oldPoint, point newPoint)
157 Replaces the point with the coordinates \a oldPoint with the point
158 with the coordinates \a newPoint. Does nothing if the old point does
159 not exist.
160*/
161/*!
162 Replaces the point with the coordinates \a oldPoint with the point
163 with the coordinates \a newPoint. Does nothing if the old point does
164 not exist.
165*/
166void QXYSeries::replace(QPointF oldPoint, QPointF newPoint)
167{
168 Q_D(QXYSeries);
169 qsizetype index = d->m_points.indexOf(t: oldPoint);
170 if (index == -1)
171 return;
172 replace(index, newPoint);
173}
174
175/*!
176 \qmlmethod XYSeries::replace(int index, real newX, real newY)
177 Replaces the point at the position specified by \a index with the point
178 that has the coordinates \a newX and \a newY.
179*/
180/*!
181 Replaces the point at the position specified by \a index with the point
182 that has the coordinates \a newX and \a newY.
183*/
184void QXYSeries::replace(qsizetype index, qreal newX, qreal newY)
185{
186 replace(index, newPoint: QPointF(newX, newY));
187}
188
189/*!
190 \qmlmethod XYSeries::replace(int index, point newPoint)
191 Replaces the point at the position specified by \a index with the point
192 that has the coordinates \a newPoint.
193*/
194/*!
195 Replaces the point at the position specified by \a index with the point
196 that has the coordinates \a newPoint.
197*/
198void QXYSeries::replace(qsizetype index, QPointF newPoint)
199{
200 Q_D(QXYSeries);
201
202 if (index < 0 || index >= d->m_points.size())
203 return;
204
205 if (isValidValue(point: newPoint)) {
206 if (d->m_graphTransition && d->m_graphTransition->initialized()
207 && d->m_graphTransition->contains(type: QGraphAnimation::GraphAnimationType::GraphPoint)) {
208 d->m_graphTransition->stop();
209 d->m_graphTransition->onPointChanged(type: QGraphTransition::TransitionType::PointReplaced,
210 index,
211 point: newPoint);
212 } else {
213 d->m_points[index] = newPoint;
214 emit pointReplaced(index);
215 }
216 }
217}
218
219/*!
220 \qmlmethod XYSeries::replace(list<point> points)
221 Replaces the current points with the points specified by \a points
222 \note This is much faster than replacing data points one by one, or first
223 clearing all data, and then appending the new data. Emits \l pointsReplaced
224 when the points have been replaced.
225*/
226/*!
227 Replaces the current points with the points specified by \a points
228 \note This is much faster than replacing data points one by one, or first
229 clearing all data, and then appending the new data. Emits \l pointsReplaced
230 when the points have been replaced.
231*/
232void QXYSeries::replace(const QList<QPointF> &points)
233{
234 Q_D(QXYSeries);
235 bool hasDifferentSize = d->m_points.size() != points.size();
236 d->m_points = points;
237 emit pointsReplaced();
238 if (hasDifferentSize)
239 emit countChanged();
240}
241
242/*!
243 \qmlmethod XYSeries::remove(real x, real y)
244 Removes the point with the coordinates \a x and \a y from the series. Does
245 nothing if the point does not exist.
246*/
247/*!
248 Removes the point with the coordinates \a x and \a y from the series. Does
249 nothing if the point does not exist.
250*/
251void QXYSeries::remove(qreal x, qreal y)
252{
253 remove(point: QPointF(x, y));
254}
255
256/*!
257 \qmlmethod XYSeries::remove(point point)
258 Removes the point with the coordinates \a point from the series. Does
259 nothing if the point does not exist.
260*/
261/*!
262 Removes the point with the coordinates \a point from the series. Does
263 nothing if the point does not exist.
264*/
265void QXYSeries::remove(QPointF point)
266{
267 Q_D(QXYSeries);
268 qsizetype index = d->m_points.indexOf(t: point);
269 if (index == -1)
270 return;
271 remove(index);
272}
273
274/*!
275 \qmlmethod XYSeries::remove(int index)
276 Removes the point at the position specified by \a index from the series.
277*/
278/*!
279 Removes the point at the position specified by \a index from the series.
280*/
281void QXYSeries::remove(qsizetype index)
282{
283 Q_D(QXYSeries);
284
285 if (index < 0 || index >= d->m_points.size())
286 return;
287
288 if (d->m_graphTransition && d->m_graphTransition->initialized()
289 && d->m_graphTransition->contains(type: QGraphAnimation::GraphAnimationType::GraphPoint)) {
290 d->m_graphTransition->stop();
291 d->m_graphTransition->onPointChanged(type: QGraphTransition::TransitionType::PointRemoved,
292 index,
293 point: {});
294 } else {
295 d->m_points.remove(i: index);
296 bool callSignal = false;
297 d->setPointSelected(index, selected: false, callSignal);
298
299 emit pointRemoved(index);
300 emit countChanged();
301 if (callSignal)
302 emit selectedPointsChanged();
303 }
304}
305
306/*!
307 \qmlmethod XYSeries::removeMultiple(int index, int count)
308 Removes the number of points specified by \a count from the series starting
309 at the position specified by \a index.
310*/
311/*!
312 Removes the number of points specified by \a count from the series starting
313 at the position specified by \a index.
314*/
315void QXYSeries::removeMultiple(qsizetype index, qsizetype count)
316{
317 // This function doesn't overload remove as there is chance for it to get mixed up with
318 // remove(qreal, qreal) overload in some implicit casting cases.
319 Q_D(QXYSeries);
320
321 if (index < 0 || count < 1 || index + count > d->m_points.size())
322 return;
323
324 if (count > 0) {
325 if (d->m_graphTransition && d->m_graphTransition->initialized()
326 && d->m_graphTransition->contains(type: QGraphAnimation::GraphAnimationType::GraphPoint)) {
327 d->m_graphTransition->stop();
328 }
329
330 d->m_points.remove(i: index, n: count);
331
332 bool callSignal = false;
333 if (!d->m_selectedPoints.empty()) {
334 QSet<qsizetype> selectedAfterRemoving;
335
336 for (const qsizetype &selectedPointIndex : std::as_const(t&: d->m_selectedPoints)) {
337 if (selectedPointIndex < index) {
338 selectedAfterRemoving << selectedPointIndex;
339 } else if (selectedPointIndex >= index + count) {
340 selectedAfterRemoving << selectedPointIndex - int(count);
341 callSignal = true;
342 } else {
343 callSignal = true;
344 }
345 }
346
347 d->m_selectedPoints = selectedAfterRemoving;
348 }
349
350 emit pointsRemoved(index, count);
351 emit countChanged();
352 if (callSignal)
353 emit selectedPointsChanged();
354 }
355}
356
357/*!
358 \qmlmethod bool XYSeries::take(point point)
359 Takes a point, specified by \a point, out of the series if found. Returns \c true if
360 the operation is successful.
361*/
362/*!
363 Takes a point, specified by \a point, out of the series if found. Returns \c true if
364 the operation is successful.
365*/
366bool QXYSeries::take(QPointF point)
367{
368 Q_D(QXYSeries);
369
370 for (int i = 0; i < d->m_points.size(); ++i) {
371 if (d->m_points[i] == point) {
372 d->m_points.removeAt(i);
373 return true;
374 }
375 }
376
377 return false;
378}
379
380/*!
381 \qmlmethod XYSeries::insert(int index, point point)
382 Inserts a point with the coordinates \a point to the position specified
383 by \a index in the series. If the index is 0 or less than 0, the point is
384 prepended to the list of points. If the index is equal to or greater than
385 than the number of points in the series, the point is appended to the
386 list of points.
387*/
388/*!
389 Inserts a point with the coordinates \a point to the position specified
390 by \a index in the series. If the index is 0 or less than 0, the point is
391 prepended to the list of points. If the index is equal to or greater than
392 than the number of points in the series, the point is appended to the
393 list of points.
394*/
395void QXYSeries::insert(qsizetype index, QPointF point)
396{
397 Q_D(QXYSeries);
398
399 if (isValidValue(point)) {
400 index = qMax(a: 0, b: qMin(a: index, b: d->m_points.size()));
401
402 d->m_points.insert(i: index, t: point);
403
404 bool callSignal = false;
405 if (!d->m_selectedPoints.isEmpty()) {
406 // if point was inserted we need to move already selected points by 1
407 QSet<qsizetype> selectedAfterInsert;
408 for (const auto &value : std::as_const(t&: d->m_selectedPoints)) {
409 if (value >= index) {
410 selectedAfterInsert << value + 1;
411 callSignal = true;
412 } else {
413 selectedAfterInsert << value;
414 }
415 }
416 d->m_selectedPoints = selectedAfterInsert;
417 }
418
419 emit pointAdded(index);
420 if (callSignal)
421 emit selectedPointsChanged();
422 }
423}
424
425/*!
426 \qmlmethod XYSeries::clear()
427 Removes all points from the series.
428*/
429/*!
430 Removes all points from the series.
431*/
432void QXYSeries::clear()
433{
434 Q_D(QXYSeries);
435 removeMultiple(index: 0, count: d->m_points.size());
436}
437
438/*!
439 \qmlmethod bool XYSeries::isPointSelected(int index)
440 Returns true if point at given \a index is among selected points and false otherwise.
441 \note Selected points are drawn using the selected color if it was specified.
442 \sa selectedPoints, setPointSelected(), selectedColor
443 */
444/*!
445 Returns true if point at given \a index is among selected points and false otherwise.
446 \note Selected points are drawn using the selected color if it was specified.
447 \sa selectedPoints, setPointSelected(), setSelectedColor()
448 */
449bool QXYSeries::isPointSelected(qsizetype index) const
450{
451 Q_D(const QXYSeries);
452 return d->isPointSelected(index);
453}
454
455/*!
456 \qmlmethod XYSeries::selectPoint(int index)
457 Marks point at \a index as selected.
458 \note Emits QXYSeries::selectedPointsChanged
459 \sa setPointSelected()
460 */
461/*!
462 Marks point at \a index as selected.
463 \note Emits QXYSeries::selectedPointsChanged
464 \sa setPointSelected()
465 */
466void QXYSeries::selectPoint(qsizetype index)
467{
468 setPointSelected(index, selected: true);
469}
470
471/*!
472 \qmlmethod XYSeries::deselectPoint(int index)
473 Deselects point at given \a index.
474 \note Emits QXYSeries::selectedPointsChanged
475 \sa setPointSelected()
476 */
477/*!
478 Deselects point at given \a index.
479 \note Emits QXYSeries::selectedPointsChanged
480 \sa setPointSelected()
481 */
482void QXYSeries::deselectPoint(qsizetype index)
483{
484 setPointSelected(index, selected: false);
485}
486
487/*!
488 \qmlmethod XYSeries::setPointSelected(int index, bool selected)
489 Marks point at given \a index as either selected or deselected as specified by \a selected.
490 \note Selected points are drawn using the selected color if it was specified. Emits QXYSeries::selectedPointsChanged
491 \sa selectAllPoints(), selectedColor
492 */
493/*!
494 Marks point at given \a index as either selected or deselected as specified by \a selected.
495 \note Selected points are drawn using the selected color if it was specified. Emits QXYSeries::selectedPointsChanged
496 \sa selectAllPoints(), setSelectedColor()
497 */
498void QXYSeries::setPointSelected(qsizetype index, bool selected)
499{
500 Q_D(QXYSeries);
501
502 bool callSignal = false;
503 d->setPointSelected(index, selected, callSignal);
504
505 if (callSignal)
506 emit selectedPointsChanged();
507}
508
509/*!
510 \qmlmethod XYSeries::selectAllPoints()
511 Marks all points in the series as selected,
512 \note Emits QXYSeries::selectedPointsChanged
513 \sa setPointSelected()
514 */
515/*!
516 Marks all points in the series as selected,
517 \note Emits QXYSeries::selectedPointsChanged
518 \sa setPointSelected()
519 */
520void QXYSeries::selectAllPoints()
521{
522 Q_D(QXYSeries);
523
524 bool callSignal = false;
525 for (int i = 0; i < d->m_points.size(); ++i)
526 d->setPointSelected(index: i, selected: true, callSignal);
527
528 if (callSignal)
529 emit selectedPointsChanged();
530}
531
532/*!
533 \qmlmethod XYSeries::deselectAllPoints()
534 Deselects all points in the series.
535 \note Emits QXYSeries::selectedPointsChanged
536 \sa setPointSelected()
537 */
538/*!
539 Deselects all points in the series.
540 \note Emits QXYSeries::selectedPointsChanged
541 \sa setPointSelected()
542 */
543void QXYSeries::deselectAllPoints()
544{
545 Q_D(QXYSeries);
546
547 bool callSignal = false;
548 for (int i = 0; i < d->m_points.size(); ++i)
549 d->setPointSelected(index: i, selected: false, callSignal);
550
551 if (callSignal)
552 emit selectedPointsChanged();
553}
554
555/*!
556 \qmlmethod XYSeries::selectPoints(list<int> indexes)
557 Marks multiple points passed in a \a indexes list as selected.
558 \note Emits QXYSeries::selectedPointsChanged
559 \sa setPointSelected()
560 */
561/*!
562 Marks multiple points passed in a \a indexes list as selected.
563 \note Emits QXYSeries::selectedPointsChanged
564 \sa setPointSelected()
565 */
566void QXYSeries::selectPoints(const QList<qsizetype> &indexes)
567{
568 Q_D(QXYSeries);
569
570 bool callSignal = false;
571 for (const qsizetype &index : indexes)
572 d->setPointSelected(index, selected: true, callSignal);
573
574 if (callSignal)
575 emit selectedPointsChanged();
576}
577
578/*!
579 \qmlmethod XYSeries::deselectPoints(list<int> indexes)
580 Marks multiple points passed in a \a indexes list as deselected.
581 \note Emits QXYSeries::selectedPointsChanged
582 \sa setPointSelected()
583 */
584/*!
585 Marks multiple points passed in a \a indexes list as deselected.
586 \note Emits QXYSeries::selectedPointsChanged
587 \sa setPointSelected()
588 */
589void QXYSeries::deselectPoints(const QList<qsizetype> &indexes)
590{
591 Q_D(QXYSeries);
592
593 bool callSignal = false;
594 for (const qsizetype &index : indexes)
595 d->setPointSelected(index, selected: false, callSignal);
596
597 if (callSignal)
598 emit selectedPointsChanged();
599}
600
601/*!
602 \qmlmethod XYSeries::toggleSelection(list<int> indexes)
603 Changes selection state of points at given \a indexes to the opposite one.
604 \note Emits QXYSeries::selectedPointsChanged
605 \sa setPointSelected()
606 */
607/*!
608 Changes selection state of points at given \a indexes to the opposite one.
609 \note Emits QXYSeries::selectedPointsChanged
610 \sa setPointSelected()
611 */
612void QXYSeries::toggleSelection(const QList<qsizetype> &indexes)
613{
614 Q_D(QXYSeries);
615
616 bool callSignal = false;
617 for (const qsizetype &index : indexes)
618 d->setPointSelected(index, selected: !isPointSelected(index), callSignal);
619
620 if (callSignal)
621 emit selectedPointsChanged();
622}
623
624/*!
625 \property QXYSeries::selectedPoints
626 \brief The indexes of the points which are currently selected.
627*/
628/*!
629 \qmlproperty list<int> XYSeries::selectedPoints
630 The indexes of the points which are currently selected.
631*/
632
633/*!
634 Returns a list of points indexes marked as selected.
635 Selected points are visible regardless of points visibility.
636 \sa setPointSelected()
637 */
638QList<qsizetype> QXYSeries::selectedPoints() const
639{
640 Q_D(const QXYSeries);
641 return QList<qsizetype>(d->m_selectedPoints.begin(), d->m_selectedPoints.end());
642}
643
644/*!
645 \property QXYSeries::count
646 \brief Returns the number of data points in a series.
647*/
648/*!
649 \qmlproperty int XYSeries::count
650 Returns the number of data points in a series.
651*/
652qsizetype QXYSeries::count() const
653{
654 Q_D(const QXYSeries);
655 return d->m_points.size();
656}
657
658/*!
659 Returns the points in the series.
660*/
661QList<QPointF> QXYSeries::points() const
662{
663 Q_D(const QXYSeries);
664 return d->m_points;
665}
666
667/*!
668 \qmlmethod point XYSeries::at(int index)
669 Returns the point at the position specified by \a index. Returns (0, 0) if
670 the index is not valid.
671*/
672/*!
673 Returns the point at the position specified by \a index. Returns (0, 0) if
674 the index is not valid.
675*/
676QPointF QXYSeries::at(qsizetype index) const
677{
678 Q_D(const QXYSeries);
679 return d->m_points.at(i: index);
680}
681
682/*!
683 \qmlmethod int XYSeries::find(point point)
684 Finds and returns the index of the first matching point found as defined by \a point.
685 Returns -1 if the point is not found.
686*/
687/*!
688 Finds and returns the index of the first matching point found as defined by \a point.
689 Returns -1 if the point is not found.
690*/
691qsizetype QXYSeries::find(QPointF point) const
692{
693 Q_D(const QXYSeries);
694
695 for (qsizetype i = 0; i < d->m_points.size(); ++i) {
696 if (d->m_points[i] == point)
697 return i;
698 }
699
700 return -1;
701}
702
703QXYSeries::~QXYSeries() {}
704
705/*!
706 \property QXYSeries::color
707 \brief The main color of the series. For QLineSeries this means the line color and
708 for QScatterSeries the color of the point.
709*/
710/*!
711 \qmlproperty color XYSeries::color
712 The main color of the series. For LineSeries this means the line color and
713 for ScatterSeries the color of the point
714*/
715void QXYSeries::setColor(QColor newColor)
716{
717 Q_D(QXYSeries);
718 if (color() != newColor) {
719 d->m_color = newColor;
720 emit colorChanged(color: newColor);
721 }
722}
723
724QColor QXYSeries::color() const
725{
726 Q_D(const QXYSeries);
727 return d->m_color;
728}
729
730/*!
731 \property QXYSeries::selectedColor
732 \brief The color of selected points.
733*/
734/*!
735 \qmlproperty color XYSeries::selectedColor
736 The color of selected points.
737*/
738void QXYSeries::setSelectedColor(QColor color)
739{
740 Q_D(QXYSeries);
741 if (selectedColor() != color) {
742 d->m_selectedColor = color;
743 emit selectedColorChanged(color);
744 }
745}
746
747QColor QXYSeries::selectedColor() const
748{
749 Q_D(const QXYSeries);
750 return d->m_selectedColor;
751}
752
753/*!
754 \property QXYSeries::pointDelegate
755 \brief A custom QML Component used as a marker for data points.
756
757 The dynamic properties available for this component are:
758
759 \table
760 \header
761 \li Type
762 \li Name
763 \li Description
764 \row
765 \li bool
766 \li pointSelected
767 \li This value is true when the point is selected, meaning that the point index
768 is in \l{QXYSeries::selectedPoints}.
769 \row
770 \li QColor
771 \li pointColor
772 \li The color of the series. This value comes either from the \l QGraphsTheme
773 or from \l{QXYSeries::color} if the \l QXYSeries overrides the color.
774 \row
775 \li QColor
776 \li pointBorderColor
777 \li The border color of the series. This value comes from the \l QGraphsTheme.
778 \row
779 \li QColor
780 \li pointSelectedColor
781 \li The selected color of the series. This value comes either from the \l QGraphsTheme
782 or from \l{QXYSeries::selectedColor} if the \l QXYSeries overrides the color.
783 \row
784 \li qreal
785 \li pointBorderWidth
786 \li The border width of the series. This value comes from the \l QGraphsTheme.
787 \row
788 \li qreal
789 \li pointValueX
790 \li The value of the \l{QXYPoint::x} at this position.
791 \row
792 \li qreal
793 \li pointValueY
794 \li The value of the \l{QXYPoint::y} at this position.
795 \endtable
796
797 To use any of these, add property with the defined name into your custom component.
798 For example \c{"property color pointColor"} and \c{"property real pointValueX"}.
799*/
800/*!
801 \qmlproperty Component XYSeries::pointDelegate
802 A custom QML Component used as a marker for data points.
803
804 The dynamic properties available for this component are:
805
806 \table
807 \header
808 \li Type
809 \li Name
810 \li Description
811 \row
812 \li bool
813 \li pointSelected
814 \li This value is true when the point is selected.
815 \row
816 \li Color
817 \li pointColor
818 \li The color of the series. This value comes either from the \l GraphsTheme
819 or from \l{XYSeries::color} if the \l XYSeries overrides the color.
820 \row
821 \li Color
822 \li pointBorderColor
823 \li The border color of the series. This value comes from the \l GraphsTheme.
824 \row
825 \li Color
826 \li pointSelectedColor
827 \li The selected color of the series. This value comes either from the \l GraphsTheme
828 or from \l{XYSeries::selectedColor} if the \l XYSeries overrides the color.
829 \row
830 \li real
831 \li pointBorderWidth
832 \li The border width of the series. This value comes from the \l GraphsTheme.
833 \row
834 \li real
835 \li pointValueX
836 \li The value of the \l{XYPoint::x} at this position.
837 \row
838 \li real
839 \li pointValueY
840 \li The value of the \l{XYPoint::y} at this position.
841 \endtable
842
843 To use any of these, add property with the defined name into your custom component.
844 For example \c{"property color pointColor"} and \c{"property real pointValueX"}.
845*/
846QQmlComponent *QXYSeries::pointDelegate() const
847{
848 Q_D(const QXYSeries);
849 return d->m_pointDelegate;
850}
851
852void QXYSeries::setPointDelegate(QQmlComponent *newPointDelegate)
853{
854 Q_D(QXYSeries);
855 if (d->m_pointDelegate == newPointDelegate)
856 return;
857 d->m_pointDelegate = newPointDelegate;
858 emit pointDelegateChanged();
859 emit update();
860}
861
862/*!
863 \property QXYSeries::draggable
864 \brief Controls if the series is draggable.
865
866 Controls if the series can be dragged with mouse/touch.
867 By default, \a draggable is set to \c false.
868*/
869/*!
870 \qmlproperty bool QXYSeries::draggable
871 Controls if the series can be dragged with mouse/touch.
872 By default, \a draggable is set to \c false.
873*/
874bool QXYSeries::isDraggable() const
875{
876 Q_D(const QXYSeries);
877 return d->m_draggable;
878}
879
880void QXYSeries::setDraggable(bool newDraggable)
881{
882 Q_D(QXYSeries);
883 if (d->m_draggable == newDraggable)
884 return;
885 d->m_draggable = newDraggable;
886 emit draggableChanged();
887}
888
889QXYSeries &QXYSeries::operator<<(QPointF point)
890{
891 append(point);
892 return *this;
893}
894
895QXYSeries &QXYSeries::operator<< (const QList<QPointF>& points)
896{
897 append(points);
898 return *this;
899}
900
901QXYSeriesPrivate::QXYSeriesPrivate() {}
902
903void QXYSeriesPrivate::setPointSelected(qsizetype index, bool selected, bool &callSignal)
904{
905 if (index < 0 || index > m_points.size() - 1)
906 return;
907
908 if (selected) {
909 if (!isPointSelected(index)) {
910 m_selectedPoints << index;
911 callSignal = true;
912 }
913 } else {
914 if (isPointSelected(index)) {
915 m_selectedPoints.remove(value: index);
916 callSignal = true;
917 }
918 }
919}
920
921bool QXYSeriesPrivate::isPointSelected(qsizetype index) const
922{
923 return m_selectedPoints.contains(value: index);
924}
925
926void QXYSeriesPrivate::append(const QList<QPointF> &points)
927{
928 bool anim = m_graphTransition && m_graphTransition->initialized()
929 && m_graphTransition->contains(type: QGraphAnimation::GraphAnimationType::GraphPoint);
930
931 if (anim) {
932 m_graphTransition->stop();
933 qsizetype index = m_points.size();
934
935 for (auto point : points) {
936 if (isValidValue(point)) {
937 m_graphTransition->stop();
938 m_graphTransition->onPointChanged(type: QGraphTransition::TransitionType::PointAdded,
939 index,
940 point);
941 index++;
942 }
943 }
944 } else {
945 m_points.append(l: points);
946 }
947}
948
949QT_END_NAMESPACE
950

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtgraphs/src/graphs2d/xychart/qxyseries.cpp