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 | |
8 | QT_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 | |
78 | QXYSeries::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 | */ |
96 | void 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 | */ |
108 | void 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 | */ |
133 | void 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 | */ |
150 | void 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 | */ |
166 | void 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 | */ |
184 | void 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 | */ |
198 | void 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 | */ |
232 | void 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 | */ |
251 | void 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 | */ |
265 | void 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 | */ |
281 | void 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 | */ |
315 | void 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 | */ |
366 | bool 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 | */ |
395 | void 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 | */ |
432 | void 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 | */ |
449 | bool 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 | */ |
466 | void 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 | */ |
482 | void 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 | */ |
498 | void 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 | */ |
520 | void 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 | */ |
543 | void 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 | */ |
566 | void 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 | */ |
589 | void 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 | */ |
612 | void 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 | */ |
638 | QList<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 | */ |
652 | qsizetype 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 | */ |
661 | QList<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 | */ |
676 | QPointF 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 | */ |
691 | qsizetype 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 | |
703 | QXYSeries::~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 | */ |
715 | void 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 | |
724 | QColor 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 | */ |
738 | void 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 | |
747 | QColor 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 | */ |
846 | QQmlComponent *QXYSeries::pointDelegate() const |
847 | { |
848 | Q_D(const QXYSeries); |
849 | return d->m_pointDelegate; |
850 | } |
851 | |
852 | void 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 | */ |
874 | bool QXYSeries::isDraggable() const |
875 | { |
876 | Q_D(const QXYSeries); |
877 | return d->m_draggable; |
878 | } |
879 | |
880 | void 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 | |
889 | QXYSeries &QXYSeries::operator<<(QPointF point) |
890 | { |
891 | append(point); |
892 | return *this; |
893 | } |
894 | |
895 | QXYSeries &QXYSeries::operator<< (const QList<QPointF>& points) |
896 | { |
897 | append(points); |
898 | return *this; |
899 | } |
900 | |
901 | QXYSeriesPrivate::QXYSeriesPrivate() {} |
902 | |
903 | void 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 | |
921 | bool QXYSeriesPrivate::isPointSelected(qsizetype index) const |
922 | { |
923 | return m_selectedPoints.contains(value: index); |
924 | } |
925 | |
926 | void 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 | |
949 | QT_END_NAMESPACE |
950 |
Definitions
- QXYSeries
- append
- append
- append
- replace
- replace
- replace
- replace
- replace
- remove
- remove
- remove
- removeMultiple
- take
- insert
- clear
- isPointSelected
- selectPoint
- deselectPoint
- setPointSelected
- selectAllPoints
- deselectAllPoints
- selectPoints
- deselectPoints
- toggleSelection
- selectedPoints
- count
- points
- at
- find
- ~QXYSeries
- setColor
- color
- setSelectedColor
- selectedColor
- pointDelegate
- setPointDelegate
- isDraggable
- setDraggable
- operator<<
- operator<<
- QXYSeriesPrivate
- setPointSelected
- isPointSelected
Learn to use CMake with our Intro Training
Find out more