qareaseries.cpp
468 lines
| 13.1 KiB
| text/x-c
|
CppLexer
Jani Honkonen
|
r794 | /**************************************************************************** | ||
** | ||||
Miikka Heikkinen
|
r2432 | ** Copyright (C) 2013 Digia Plc | ||
Jani Honkonen
|
r794 | ** All rights reserved. | ||
** For any questions to Digia, please use contact form at http://qt.digia.com | ||||
** | ||||
Miikka Heikkinen
|
r2574 | ** This file is part of the Qt Enterprise Charts Add-on. | ||
Jani Honkonen
|
r794 | ** | ||
** $QT_BEGIN_LICENSE$ | ||||
Miikka Heikkinen
|
r2574 | ** Licensees holding valid Qt Enterprise licenses may use this file in | ||
** accordance with the Qt Enterprise License Agreement provided with the | ||||
Jani Honkonen
|
r794 | ** Software or, alternatively, in accordance with the terms contained in | ||
** a written agreement between you and Digia. | ||||
** | ||||
** If you have questions regarding the use of this file, please use | ||||
** contact form at http://qt.digia.com | ||||
** $QT_END_LICENSE$ | ||||
** | ||||
****************************************************************************/ | ||||
Michal Klocek
|
r421 | #include "qareaseries.h" | ||
Michal Klocek
|
r938 | #include "qareaseries_p.h" | ||
Michal Klocek
|
r421 | #include "qlineseries.h" | ||
Michal Klocek
|
r943 | #include "areachartitem_p.h" | ||
Marek Rosa
|
r2275 | #include "abstractdomain_p.h" | ||
Michal Klocek
|
r943 | #include "chartdataset_p.h" | ||
#include "charttheme_p.h" | ||||
Marek Rosa
|
r1805 | #include "qvalueaxis.h" | ||
sauimone
|
r2177 | #include "qarealegendmarker.h" | ||
Michal Klocek
|
r2273 | #include "qchart_p.h" | ||
sauimone
|
r2177 | |||
Michal Klocek
|
r421 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | ||
/*! | ||||
\class QAreaSeries | ||||
\brief The QAreaSeries class is used for making area charts. | ||||
\mainclass | ||||
Jani Honkonen
|
r2097 | An area chart is used to show quantitative data. It is based on line chart, in the way that area between axis and the line | ||
is emphasized with color. Since the area chart is based on line chart, QAreaSeries constructor needs QLineSeries instance, | ||||
which defines "upper" boundary of the area. "Lower" boundary is defined by default by axis X. Instead of axis X "lower" boundary can be specified by other line. | ||||
Marek Rosa
|
r1515 | In that case QAreaSeries should be initiated with two QLineSeries instances. Please note terms "upper" and "lower" boundary can be misleading in cases | ||
Jani Honkonen
|
r2097 | where "lower" boundary had bigger values than the "upper" one, however the main point that area between these two boundary lines will be filled. | ||
Michal Klocek
|
r421 | |||
Tero Ahola
|
r995 | See the \l {AreaChart Example} {area chart example} to learn how to create a simple area chart. | ||
\image examples_areachart.png | ||||
Michal Klocek
|
r421 | */ | ||
Tero Ahola
|
r1491 | /*! | ||
\qmlclass AreaSeries QAreaSeries | ||||
The following QML shows how to create a simple area chart: | ||||
\snippet ../demos/qmlchart/qml/qmlchart/View4.qml 1 | ||||
\beginfloatleft | ||||
\image demos_qmlchart4.png | ||||
\endfloat | ||||
\clearfloat | ||||
*/ | ||||
Michal Klocek
|
r421 | |||
/*! | ||||
Tero Ahola
|
r1462 | \property QAreaSeries::upperSeries | ||
\brief The upper one of the two line series used to define area series boundaries. | ||||
Michal Klocek
|
r421 | */ | ||
Tero Ahola
|
r1491 | /*! | ||
\qmlproperty LineSeries AreaSeries::upperSeries | ||||
The upper one of the two line series used to define area series boundaries. | ||||
*/ | ||||
Michal Klocek
|
r421 | |||
/*! | ||||
Tero Ahola
|
r1462 | \property QAreaSeries::lowerSeries | ||
The lower one of the two line series used to define are series boundaries. Note if | ||||
Miikka Heikkinen
|
r2494 | QAreaSeries was constructed without a\ lowerSeries this is null. | ||
Michal Klocek
|
r421 | */ | ||
Tero Ahola
|
r1491 | /*! | ||
\qmlproperty LineSeries AreaSeries::lowerSeries | ||||
The lower one of the two line series used to define are series boundaries. Note if | ||||
Miikka Heikkinen
|
r2494 | AreaSeries was constructed without a\ lowerSeries this is null. | ||
Tero Ahola
|
r1491 | */ | ||
Michal Klocek
|
r421 | |||
Tero Ahola
|
r1481 | /*! | ||
\property QAreaSeries::color | ||||
Fill (brush) color of the series. This is a convenience property for modifying the color of brush. | ||||
\sa QAreaSeries::brush() | ||||
*/ | ||||
Tero Ahola
|
r1491 | /*! | ||
\qmlproperty color AreaSeries::color | ||||
Fill (brush) color of the series. | ||||
*/ | ||||
Tero Ahola
|
r1481 | |||
/*! | ||||
\property QAreaSeries::borderColor | ||||
Line (pen) color of the series. This is a convenience property for modifying the color of pen. | ||||
\sa QAreaSeries::pen() | ||||
*/ | ||||
Tero Ahola
|
r1491 | /*! | ||
\qmlproperty color AreaSeries::borderColor | ||||
Line (pen) color of the series. | ||||
*/ | ||||
Tero Ahola
|
r1481 | |||
Tero Ahola
|
r1906 | /*! | ||
\qmlproperty real AreaSeries::borderWidth | ||||
The width of the border line. By default the width is 2.0. | ||||
*/ | ||||
Michal Klocek
|
r421 | /*! | ||
\fn QPen QAreaSeries::pen() const | ||||
\brief Returns the pen used to draw line for this series. | ||||
\sa setPen() | ||||
*/ | ||||
/*! | ||||
\fn QPen QAreaSeries::brush() const | ||||
\brief Returns the brush used to draw line for this series. | ||||
\sa setBrush() | ||||
*/ | ||||
Tero Ahola
|
r1481 | /*! | ||
\fn void QAreaSeries::colorChanged(QColor color) | ||||
\brief Signal is emitted when the fill (brush) color has changed to \a color. | ||||
*/ | ||||
Tero Ahola
|
r1491 | /*! | ||
Tero Ahola
|
r1531 | \qmlsignal AreaSeries::onColorChanged(color color) | ||
Tero Ahola
|
r1491 | Signal is emitted when the fill (brush) color has changed to \a color. | ||
*/ | ||||
Tero Ahola
|
r1481 | |||
/*! | ||||
\fn void QAreaSeries::borderColorChanged(QColor color) | ||||
\brief Signal is emitted when the line (pen) color has changed to \a color. | ||||
*/ | ||||
Michal Klocek
|
r421 | /*! | ||
Tero Ahola
|
r1531 | \qmlsignal AreaSeries::onBorderColorChanged(color color) | ||
Tero Ahola
|
r1491 | Signal is emitted when the line (pen) color has changed to \a color. | ||
Michal Klocek
|
r421 | */ | ||
Michal Klocek
|
r574 | /*! | ||
\fn void QAreaSeries::clicked(const QPointF& point) | ||||
\brief Signal is emitted when user clicks the \a point on area chart. | ||||
*/ | ||||
Tero Ahola
|
r1491 | /*! | ||
Tero Ahola
|
r1531 | \qmlsignal AreaSeries::onClicked(QPointF point) | ||
Tero Ahola
|
r1491 | Signal is emitted when user clicks the \a point on area chart. | ||
*/ | ||||
Michal Klocek
|
r574 | |||
Tero Ahola
|
r2362 | /*! | ||
\fn void QAreaSeries::hovered(const QPointF &point, bool state) | ||||
This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate) | ||||
of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from | ||||
the series. | ||||
*/ | ||||
/*! | ||||
\qmlsignal AreaSeries::onHovered(point point, bool state) | ||||
This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate) | ||||
of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from | ||||
the series. | ||||
*/ | ||||
Tero Ahola
|
r973 | /*! | ||
\fn void QAreaSeries::selected() | ||||
The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be | ||||
implemented by the user of QAreaSeries API. | ||||
*/ | ||||
Tero Ahola
|
r1491 | /*! | ||
Tero Ahola
|
r1531 | \qmlsignal AreaSeries::onSelected() | ||
Tero Ahola
|
r1491 | The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be | ||
implemented by the user of AreaSeries API. | ||||
*/ | ||||
Tero Ahola
|
r973 | |||
Michal Klocek
|
r421 | /*! | ||
Marek Rosa
|
r940 | \fn void QAreaSeriesPrivate::updated() | ||
Michal Klocek
|
r421 | \brief \internal | ||
*/ | ||||
/*! | ||||
Constructs area series object which is a child of \a upperSeries. Area will be spanned between \a | ||||
upperSeries line and \a lowerSeries line. If no \a lowerSeries is passed to constructor, area is specified by axis x (y=0) instead. | ||||
Michal Klocek
|
r974 | When series object is added to QChartView or QChart instance ownerships is transferred. | ||
Michal Klocek
|
r421 | */ | ||
Tero Ahola
|
r761 | QAreaSeries::QAreaSeries(QLineSeries *upperSeries, QLineSeries *lowerSeries) | ||
Jani Honkonen
|
r2097 | : QAbstractSeries(*new QAreaSeriesPrivate(upperSeries, lowerSeries, this), upperSeries) | ||
Michal Klocek
|
r421 | { | ||
} | ||||
Tero Ahola
|
r761 | |||
Tero Ahola
|
r1202 | /*! | ||
Jani Honkonen
|
r1351 | Constructs area series object without upper or lower series with \a parent object. | ||
Tero Ahola
|
r1202 | */ | ||
QAreaSeries::QAreaSeries(QObject *parent) | ||||
: QAbstractSeries(*new QAreaSeriesPrivate(0, 0, this), parent) | ||||
{ | ||||
} | ||||
Michal Klocek
|
r421 | /*! | ||
Marek Rosa
|
r1515 | Destroys the object. | ||
Michal Klocek
|
r421 | */ | ||
QAreaSeries::~QAreaSeries() | ||||
{ | ||||
Michal Klocek
|
r1727 | Q_D(QAreaSeries); | ||
Michal Klocek
|
r2273 | if (d->m_chart) | ||
d->m_chart->removeSeries(this); | ||||
Michal Klocek
|
r421 | } | ||
Jani Honkonen
|
r1345 | /*! | ||
Miikka Heikkinen
|
r2520 | Returns QAbstractSeries::SeriesTypeArea. | ||
Jani Honkonen
|
r1345 | */ | ||
Michal Klocek
|
r1107 | QAbstractSeries::SeriesType QAreaSeries::type() const | ||
Michal Klocek
|
r938 | { | ||
Tero Ahola
|
r988 | return QAbstractSeries::SeriesTypeArea; | ||
Michal Klocek
|
r938 | } | ||
Marek Rosa
|
r1369 | /*! | ||
Sets the \a series that is to be used as the area chart upper series. | ||||
*/ | ||||
Jani Honkonen
|
r2104 | void QAreaSeries::setUpperSeries(QLineSeries *series) | ||
Tero Ahola
|
r1202 | { | ||
Q_D(QAreaSeries); | ||||
Miikka Heikkinen
|
r2439 | if (d->m_upperSeries != series) | ||
Michal Klocek
|
r2407 | d->m_upperSeries = series; | ||
Tero Ahola
|
r1202 | } | ||
Jani Honkonen
|
r2104 | QLineSeries *QAreaSeries::upperSeries() const | ||
Michal Klocek
|
r938 | { | ||
Q_D(const QAreaSeries); | ||||
return d->m_upperSeries; | ||||
} | ||||
Marek Rosa
|
r1369 | /*! | ||
Sets the \a series that is to be used as the area chart lower series. | ||||
*/ | ||||
Jani Honkonen
|
r2104 | void QAreaSeries::setLowerSeries(QLineSeries *series) | ||
Tero Ahola
|
r1202 | { | ||
Q_D(QAreaSeries); | ||||
d->m_lowerSeries = series; | ||||
} | ||||
Jani Honkonen
|
r2104 | QLineSeries *QAreaSeries::lowerSeries() const | ||
Michal Klocek
|
r938 | { | ||
Q_D(const QAreaSeries); | ||||
return d->m_lowerSeries; | ||||
} | ||||
Michal Klocek
|
r421 | /*! | ||
Sets \a pen used for drawing area outline. | ||||
*/ | ||||
Tero Ahola
|
r761 | void QAreaSeries::setPen(const QPen &pen) | ||
Michal Klocek
|
r421 | { | ||
Michal Klocek
|
r938 | Q_D(QAreaSeries); | ||
if (d->m_pen != pen) { | ||||
d->m_pen = pen; | ||||
emit d->updated(); | ||||
Michal Klocek
|
r571 | } | ||
Michal Klocek
|
r421 | } | ||
Miikka Heikkinen
|
r2519 | QPen QAreaSeries::pen() const | ||
Michal Klocek
|
r938 | { | ||
Q_D(const QAreaSeries); | ||||
Miikka Heikkinen
|
r2519 | if (d->m_pen == QChartPrivate::defaultPen()) | ||
return QPen(); | ||||
else | ||||
return d->m_pen; | ||||
Michal Klocek
|
r938 | } | ||
Michal Klocek
|
r421 | /*! | ||
Sets \a brush used for filling the area. | ||||
*/ | ||||
sauimone
|
r743 | void QAreaSeries::setBrush(const QBrush &brush) | ||
Michal Klocek
|
r421 | { | ||
Michal Klocek
|
r938 | Q_D(QAreaSeries); | ||
if (d->m_brush != brush) { | ||||
Tero Ahola
|
r1933 | bool emitColorChanged = brush.color() != d->m_brush.color(); | ||
Michal Klocek
|
r938 | d->m_brush = brush; | ||
emit d->updated(); | ||||
Tero Ahola
|
r1933 | if (emitColorChanged) | ||
emit colorChanged(brush.color()); | ||||
Michal Klocek
|
r571 | } | ||
Michal Klocek
|
r421 | } | ||
Michal Klocek
|
r938 | |||
QBrush QAreaSeries::brush() const | ||||
{ | ||||
Q_D(const QAreaSeries); | ||||
Miikka Heikkinen
|
r2519 | if (d->m_brush == QChartPrivate::defaultBrush()) | ||
return QBrush(); | ||||
else | ||||
return d->m_brush; | ||||
Michal Klocek
|
r938 | } | ||
Tero Ahola
|
r1481 | |||
void QAreaSeries::setColor(const QColor &color) | ||||
{ | ||||
QBrush b = brush(); | ||||
Tero Ahola
|
r1933 | if (b == QBrush()) | ||
b.setStyle(Qt::SolidPattern); | ||||
b.setColor(color); | ||||
setBrush(b); | ||||
Tero Ahola
|
r1481 | } | ||
QColor QAreaSeries::color() const | ||||
{ | ||||
return brush().color(); | ||||
} | ||||
void QAreaSeries::setBorderColor(const QColor &color) | ||||
{ | ||||
QPen p = pen(); | ||||
if (p.color() != color) { | ||||
p.setColor(color); | ||||
setPen(p); | ||||
emit borderColorChanged(color); | ||||
} | ||||
} | ||||
QColor QAreaSeries::borderColor() const | ||||
{ | ||||
return pen().color(); | ||||
} | ||||
Michal Klocek
|
r421 | /*! | ||
Sets if data points are \a visible and should be drawn on line. | ||||
*/ | ||||
void QAreaSeries::setPointsVisible(bool visible) | ||||
{ | ||||
Michal Klocek
|
r938 | Q_D(QAreaSeries); | ||
if (d->m_pointsVisible != visible) { | ||||
d->m_pointsVisible = visible; | ||||
emit d->updated(); | ||||
Michal Klocek
|
r571 | } | ||
Michal Klocek
|
r421 | } | ||
Tero Ahola
|
r1491 | /*! | ||
Returns if the points are drawn for this series. | ||||
\sa setPointsVisible() | ||||
*/ | ||||
Michal Klocek
|
r938 | bool QAreaSeries::pointsVisible() const | ||
{ | ||||
Q_D(const QAreaSeries); | ||||
return d->m_pointsVisible; | ||||
} | ||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
Jani Honkonen
|
r2104 | QAreaSeriesPrivate::QAreaSeriesPrivate(QLineSeries *upperSeries, QLineSeries *lowerSeries, QAreaSeries *q) | ||
Jani Honkonen
|
r2097 | : QAbstractSeriesPrivate(q), | ||
Miikka Heikkinen
|
r2516 | m_brush(QChartPrivate::defaultBrush()), | ||
m_pen(QChartPrivate::defaultPen()), | ||||
Jani Honkonen
|
r2097 | m_upperSeries(upperSeries), | ||
m_lowerSeries(lowerSeries), | ||||
m_pointsVisible(false) | ||||
Michal Klocek
|
r938 | { | ||
Tero Ahola
|
r973 | } | ||
Michal Klocek
|
r938 | |||
Michal Klocek
|
r2273 | void QAreaSeriesPrivate::initializeDomain() | ||
Michal Klocek
|
r943 | { | ||
Q_Q(QAreaSeries); | ||||
Michal Klocek
|
r2273 | qreal minX(domain()->minX()); | ||
qreal minY(domain()->minY()); | ||||
qreal maxX(domain()->maxX()); | ||||
qreal maxY(domain()->maxY()); | ||||
Michal Klocek
|
r943 | |||
Jani Honkonen
|
r2104 | QLineSeries *upperSeries = q->upperSeries(); | ||
QLineSeries *lowerSeries = q->lowerSeries(); | ||||
Michal Klocek
|
r943 | |||
Titta Heikkala
|
r2601 | if (upperSeries) { | ||
const QList<QPointF>& points = upperSeries->points(); | ||||
for (int i = 0; i < points.count(); i++) { | ||||
qreal x = points[i].x(); | ||||
qreal y = points[i].y(); | ||||
minX = qMin(minX, x); | ||||
minY = qMin(minY, y); | ||||
maxX = qMax(maxX, x); | ||||
maxY = qMax(maxY, y); | ||||
} | ||||
Michal Klocek
|
r943 | } | ||
Jani Honkonen
|
r2097 | if (lowerSeries) { | ||
Michal Klocek
|
r1057 | |||
Michal Klocek
|
r1059 | const QList<QPointF>& points = lowerSeries->points(); | ||
Michal Klocek
|
r1057 | |||
Jani Honkonen
|
r2097 | for (int i = 0; i < points.count(); i++) { | ||
Michal Klocek
|
r1057 | qreal x = points[i].x(); | ||
qreal y = points[i].y(); | ||||
Michal Klocek
|
r943 | minX = qMin(minX, x); | ||
minY = qMin(minY, y); | ||||
maxX = qMax(maxX, x); | ||||
maxY = qMax(maxY, y); | ||||
Jani Honkonen
|
r2097 | } | ||
} | ||||
Michal Klocek
|
r943 | |||
Michal Klocek
|
r2273 | domain()->setRange(minX, maxX, minY, maxY); | ||
Michal Klocek
|
r943 | } | ||
Michal Klocek
|
r2273 | void QAreaSeriesPrivate::initializeGraphics(QGraphicsItem* parent) | ||
Michal Klocek
|
r943 | { | ||
Q_Q(QAreaSeries); | ||||
Michal Klocek
|
r2273 | AreaChartItem *area = new AreaChartItem(q,parent); | ||
m_item.reset(area); | ||||
QAbstractSeriesPrivate::initializeGraphics(parent); | ||||
} | ||||
void QAreaSeriesPrivate::initializeAnimations(QChart::AnimationOptions options) | ||||
{ | ||||
Q_Q(QAreaSeries); | ||||
AreaChartItem *area = static_cast<AreaChartItem *>(m_item.data()); | ||||
Miikka Heikkinen
|
r2555 | |||
Titta Heikkala
|
r2601 | if (q->upperSeries() && area->upperLineItem()->animation()) | ||
Miikka Heikkinen
|
r2555 | area->upperLineItem()->animation()->stopAndDestroyLater(); | ||
if (q->lowerSeries() && area->lowerLineItem()->animation()) | ||||
area->lowerLineItem()->animation()->stopAndDestroyLater(); | ||||
Michal Klocek
|
r2273 | if (options.testFlag(QChart::SeriesAnimations)) { | ||
Michal Klocek
|
r1217 | area->upperLineItem()->setAnimation(new XYAnimation(area->upperLineItem())); | ||
Jani Honkonen
|
r2097 | if (q->lowerSeries()) | ||
Miikka Heikkinen
|
r2555 | area->lowerLineItem()->setAnimation(new XYAnimation(area->lowerLineItem())); | ||
} else { | ||||
Titta Heikkala
|
r2601 | if (q->upperSeries()) | ||
area->upperLineItem()->setAnimation(0); | ||||
Michal Klocek
|
r2273 | if (q->lowerSeries()) | ||
area->lowerLineItem()->setAnimation(0); | ||||
Michal Klocek
|
r943 | } | ||
Michal Klocek
|
r2273 | QAbstractSeriesPrivate::initializeAnimations(options); | ||
Michal Klocek
|
r943 | } | ||
sauimone
|
r2163 | QList<QLegendMarker*> QAreaSeriesPrivate::createLegendMarkers(QLegend* legend) | ||
{ | ||||
sauimone
|
r2177 | Q_Q(QAreaSeries); | ||
sauimone
|
r2163 | QList<QLegendMarker*> list; | ||
sauimone
|
r2177 | return list << new QAreaLegendMarker(q,legend); | ||
sauimone
|
r2163 | } | ||
sauimone
|
r1545 | |||
Michal Klocek
|
r2273 | |||
void QAreaSeriesPrivate::initializeAxes() | ||||
sauimone
|
r1545 | { | ||
Michal Klocek
|
r2273 | |||
sauimone
|
r1545 | } | ||
Michal Klocek
|
r1695 | QAbstractAxis::AxisType QAreaSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const | ||
Michal Klocek
|
r1588 | { | ||
Michal Klocek
|
r1695 | Q_UNUSED(orientation); | ||
Marek Rosa
|
r1818 | return QAbstractAxis::AxisTypeValue; | ||
sauimone
|
r1545 | } | ||
Michal Klocek
|
r2273 | QAbstractAxis* QAreaSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const | ||
{ | ||||
Q_UNUSED(orientation); | ||||
Titta Heikkala
|
r2614 | return new QValueAxis; | ||
Michal Klocek
|
r2273 | } | ||
void QAreaSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced) | ||||
{ | ||||
Q_Q(QAreaSeries); | ||||
const QList<QGradient> gradients = theme->seriesGradients(); | ||||
const QList<QColor> colors = theme->seriesColors(); | ||||
Miikka Heikkinen
|
r2516 | if (forced || QChartPrivate::defaultPen() == m_pen) { | ||
QPen pen; | ||||
Michal Klocek
|
r2273 | pen.setColor(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0)); | ||
pen.setWidthF(2); | ||||
q->setPen(pen); | ||||
} | ||||
Miikka Heikkinen
|
r2516 | if (forced || QChartPrivate::defaultBrush() == m_brush) { | ||
Michal Klocek
|
r2273 | QBrush brush(colors.at(index % colors.size())); | ||
q->setBrush(brush); | ||||
} | ||||
} | ||||
Michal Klocek
|
r421 | #include "moc_qareaseries.cpp" | ||
Michal Klocek
|
r938 | #include "moc_qareaseries_p.cpp" | ||
Michal Klocek
|
r421 | |||
QTCOMMERCIALCHART_END_NAMESPACE | ||||