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