1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtCharts/QScatterSeries>
5#include <private/qscatterseries_p.h>
6#include <private/scatterchartitem_p.h>
7#include <private/chartdataset_p.h>
8#include <private/charttheme_p.h>
9#include <private/scatteranimation_p.h>
10#include <private/qchart_p.h>
11
12/*!
13 \class QScatterSeries
14 \inmodule QtCharts
15 \brief The QScatterSeries class presents data in scatter charts.
16
17 The scatter data is displayed as a collection of points on the chart. For
18 each point, two values are specified that determine its position on the
19 horizontal axis and the vertical axis.
20
21 \image examples_scatterchart.png
22
23 The following code snippet illustrates how to create a basic scatter chart:
24 \code
25 QScatterSeries* series = new QScatterSeries();
26 series->append(0, 6);
27 series->append(2, 4);
28 ...
29 chart->addSeries(series);
30 \endcode
31
32 For more information, see \l{Charts with Widgets Gallery} and
33 \l {Creating Scatter Charts}.
34*/
35/*!
36 \qmltype ScatterSeries
37 \instantiates QScatterSeries
38 \inqmlmodule QtCharts
39
40 \inherits XYSeries
41
42 \brief The ScatterSeries type presents data in scatter charts.
43
44 The scatter data is displayed as a collection of points on the chart. For
45 each point, two values are specified that determine its position on the
46 horizontal axis and the vertical axis.
47
48 \image examples_qmlchart5.png
49
50 The following QML code shows how to create a chart with two simple scatter
51 series:
52 \snippet qmlchartsgallery/qml/ScatterSeries.qml 1
53
54 For more information, see \l{Charts with QML Gallery}.
55*/
56
57/*!
58 \enum QScatterSeries::MarkerShape
59
60 This enum value describes the shape used when rendering marker items.
61
62 \value MarkerShapeCircle
63 The marker is a circle. This is the default value.
64 \value MarkerShapeRectangle
65 The marker is a rectangle.
66 \value MarkerShapeRotatedRectangle
67 The marker is a rotated rectangle.
68 \value MarkerShapeTriangle
69 The marker is a triangle.
70 \value MarkerShapeStar
71 The marker is a star.
72 \value MarkerShapePentagon
73 The marker is a pentagon.
74*/
75
76/*!
77 \property QScatterSeries::brush
78 \brief The brush used to draw the scatter series markers.
79
80 The brush can be an image that can be created using QPainterPath,
81 for example.
82*/
83
84/*!
85 \qmlproperty brush ScatterSeries::brush
86 The brush used to draw the scatter series markers.
87*/
88
89/*!
90 \property QScatterSeries::color
91 \brief The color used to fill the series markers.
92
93 This is a convenience property for modifying the color of the brush.
94 \sa QScatterSeries::brush()
95*/
96
97/*!
98 \property QScatterSeries::borderColor
99 \brief The color used to draw the marker borders.
100
101 This is a convenience property for modifying the color of the pen.
102 \sa QScatterSeries::pen()
103*/
104
105/*!
106 \qmlproperty int ScatterSeries::count
107 The number of data points in the series.
108*/
109
110/*!
111 \qmlproperty color ScatterSeries::borderColor
112 The color used to draw the marker borders.
113*/
114
115/*!
116 \qmlproperty real ScatterSeries::borderWidth
117 The width of the border line. By default, the width is 2.0.
118*/
119
120/*!
121 \property QScatterSeries::markerShape
122 \brief The shape of the marker used to render the points in the series.
123
124 The default shape is MarkerShapeCircle.
125
126 \sa MarkerShape
127*/
128/*!
129 \qmlproperty enumeration ScatterSeries::markerShape
130
131 The shape used when rendering marker items:
132
133 \value ScatterSeries.MarkerShapeCircle
134 The marker is a circle. This is the default value.
135 \value ScatterSeries.MarkerShapeRectangle
136 The marker is a rectangle.
137*/
138
139/*!
140 \property QScatterSeries::markerSize
141 \brief The size of the marker used to render the points in the series.
142
143 \sa QXYSeries::setMarkerSize
144*/
145/*!
146 \qmlproperty real ScatterSeries::markerSize
147 The size of the marker used to render the points in the series.
148*/
149
150/*!
151 \qmlproperty string ScatterSeries::brushFilename
152 The name of the file used as a brush for the series.
153*/
154
155/*!
156 \fn void QScatterSeries::colorChanged(QColor color)
157 This signal is emitted when the fill (brush) color changes to \a color.
158*/
159
160/*!
161 \fn void QScatterSeries::borderColorChanged(QColor color)
162 This signal is emitted when the line (pen) color changes to \a color.
163*/
164
165/*!
166 \fn void QScatterSeries::markerShapeChanged(MarkerShape shape)
167 This signal is emitted when the marker shape changes to \a shape.
168*/
169
170/*!
171 \fn void QScatterSeries::markerSizeChanged(qreal size)
172 This signal is emitted when the marker size changes to \a size.
173*/
174
175QT_BEGIN_NAMESPACE
176
177/*!
178 Constructs a series object that is a child of \a parent.
179*/
180QScatterSeries::QScatterSeries(QObject *parent)
181 : QXYSeries(*new QScatterSeriesPrivate(this), parent)
182{
183 setPointsVisible(true);
184
185 // Emit QScatterSeries' markerSizeChanged signal as it's not the same as
186 // QXYSeries' markerSizeChanged
187 connect(sender: this, signal: &QXYSeries::markerSizeChanged, context: this, slot: &QScatterSeries::markerSizeChanged);
188}
189
190/*!
191 Deletes the scatter series.
192
193 \note Adding the series to QChart transfers the ownership to the chart.
194*/
195QScatterSeries::~QScatterSeries()
196{
197 Q_D(QScatterSeries);
198 if (d->m_chart)
199 d->m_chart->removeSeries(series: this);
200}
201
202/*!
203 \reimp
204*/
205QAbstractSeries::SeriesType QScatterSeries::type() const
206{
207 return QAbstractSeries::SeriesTypeScatter;
208}
209
210/*!
211 \reimp
212*/
213void QScatterSeries::setPen(const QPen &pen)
214{
215 Q_D(QXYSeries);
216 if (d->m_pen != pen) {
217 bool emitColorChanged = d->m_pen.color() != pen.color();
218 d->m_pen = pen;
219 emit d->seriesUpdated();
220 if (emitColorChanged)
221 emit borderColorChanged(color: pen.color());
222 }
223}
224
225/*!
226 \reimp
227*/
228void QScatterSeries::setBrush(const QBrush &brush)
229{
230 Q_D(QScatterSeries);
231 if (d->m_brush != brush) {
232 bool emitColorChanged = d->m_brush.color() != brush.color();
233 d->m_brush = brush;
234 emit d->seriesUpdated();
235 if (emitColorChanged)
236 emit colorChanged(color: brush.color());
237 }
238}
239
240QBrush QScatterSeries::brush() const
241{
242 Q_D(const QScatterSeries);
243 if (d->m_brush == QChartPrivate::defaultBrush())
244 return QBrush();
245 else
246 return d->m_brush;
247}
248
249void QScatterSeries::setColor(const QColor &color)
250{
251 QBrush b = brush();
252 if (b == QChartPrivate::defaultBrush())
253 b = QBrush();
254 if (b == QBrush())
255 b.setStyle(Qt::SolidPattern);
256 b.setColor(color);
257 setBrush(b);
258}
259
260QColor QScatterSeries::color() const
261{
262 return brush().color();
263}
264
265void QScatterSeries::setBorderColor(const QColor &color)
266{
267 QPen p = pen();
268 if (p == QChartPrivate::defaultPen())
269 p = QPen();
270 p.setColor(color);
271 setPen(p);
272}
273
274QColor QScatterSeries::borderColor() const
275{
276 return pen().color();
277}
278
279QScatterSeries::MarkerShape QScatterSeries::markerShape() const
280{
281 Q_D(const QScatterSeries);
282 return d->m_shape;
283}
284
285void QScatterSeries::setMarkerShape(MarkerShape shape)
286{
287 Q_D(QScatterSeries);
288 if (d->m_shape != shape) {
289 d->m_shape = shape;
290 emit d->seriesUpdated();
291 emit markerShapeChanged(shape);
292 }
293}
294
295qreal QScatterSeries::markerSize() const
296{
297 // markerSize has moved to QXYSeries, but this method needs to remain for API compatibility.
298 return QXYSeries::markerSize();
299}
300void QScatterSeries::setMarkerSize(qreal size)
301{
302 // markerSize has moved to QXYSeries, but this method needs to remain for API compatibility.
303 QXYSeries::setMarkerSize(size);
304}
305
306////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
307
308QScatterSeriesPrivate::QScatterSeriesPrivate(QScatterSeries *q)
309 : QXYSeriesPrivate(q),
310 m_shape(QScatterSeries::MarkerShapeCircle)
311{
312}
313
314void QScatterSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
315{
316 Q_Q(QScatterSeries);
317 ScatterChartItem *scatter = new ScatterChartItem(q,parent);
318 m_item.reset(p: scatter);
319 QAbstractSeriesPrivate::initializeGraphics(parent);
320}
321
322void QScatterSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
323{
324 Q_Q(QScatterSeries);
325 const QList<QColor> colors = theme->seriesColors();
326 const QList<QGradient> gradients = theme->seriesGradients();
327
328 if (forced || QChartPrivate::defaultPen() == m_pen) {
329 QPen pen;
330 pen.setColor(ChartThemeManager::colorAt(gradient: gradients.at(i: index % gradients.size()), pos: 0.0));
331 pen.setWidthF(2);
332 q->setPen(pen);
333 }
334
335 if (forced || QChartPrivate::defaultBrush() == m_brush) {
336 QBrush brush(colors.at(i: index % colors.size()));
337 q->setBrush(brush);
338 }
339
340 if (forced || QChartPrivate::defaultPen().color() == m_pointLabelsColor) {
341 QColor color = theme->labelBrush().color();
342 q->setPointLabelsColor(color);
343 }
344}
345
346void QScatterSeriesPrivate::initializeAnimations(QChart::AnimationOptions options, int duration,
347 QEasingCurve &curve)
348{
349 ScatterChartItem *item = static_cast<ScatterChartItem *>(m_item.get());
350 Q_ASSERT(item);
351
352 if (item->animation())
353 item->animation()->stopAndDestroyLater();
354
355 if (options.testFlag(flag: QChart::SeriesAnimations))
356 item->setAnimation(new ScatterAnimation(item, duration, curve));
357 else
358 item->setAnimation(0);
359
360 QAbstractSeriesPrivate::initializeAnimations(options, duration, curve);
361}
362
363QT_END_NAMESPACE
364
365#include "moc_qscatterseries.cpp"
366

source code of qtcharts/src/charts/scatterchart/qscatterseries.cpp