summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-08-30 06:56:05 +0200
committerLiang Qi <liang.qi@qt.io>2016-08-30 06:56:12 +0200
commitbf26aa9d15e525fdcf6fd3f59268418533f06790 (patch)
treee1a12cc49f338bd1ac419a4d774d6f4570df3e40
parentd352d707f95c3c4e213585361a3ec737389e301e (diff)
parent8ed3130583510feba58e6f289d1c7b5d051a6663 (diff)
Merge remote-tracking branch 'origin/5.6' into 5.7
-rw-r--r--dist/changes-2.1.21
-rw-r--r--src/charts/areachart/areachartitem.cpp94
-rw-r--r--src/charts/areachart/areachartitem_p.h3
-rw-r--r--src/charts/areachart/qareaseries.cpp16
-rw-r--r--tests/auto/auto.pro1
-rw-r--r--tests/auto/qareaseries/qareaseries.pro4
-rw-r--r--tests/auto/qareaseries/tst_qareaseries.cpp183
7 files changed, 269 insertions, 33 deletions
diff --git a/dist/changes-2.1.2 b/dist/changes-2.1.2
index e73605e6..96ec6710 100644
--- a/dist/changes-2.1.2
+++ b/dist/changes-2.1.2
@@ -19,6 +19,7 @@ Fixed issues
- [QTBUG-53337] Fix setting axis color properties to black for the first time
- [QTBUG-55348] Disconnect a series from ChartItem when it is removed from a chart
- Fix logarithmic axis for area chart
+- [QTBUG-55431] Fix setting area series edge series after area series is shown
Fixed examples
--------------
diff --git a/src/charts/areachart/areachartitem.cpp b/src/charts/areachart/areachartitem.cpp
index a51e46ff..df3cc8af 100644
--- a/src/charts/areachart/areachartitem.cpp
+++ b/src/charts/areachart/areachartitem.cpp
@@ -95,10 +95,39 @@ void AreaChartItem::setPresenter(ChartPresenter *presenter)
{
if (m_upper)
m_upper->setPresenter(presenter);
- if (m_lower) {
+ if (m_lower)
m_lower->setPresenter(presenter);
+ ChartItem::setPresenter(presenter);
+}
+
+void AreaChartItem::setUpperSeries(QLineSeries *series)
+{
+ delete m_upper;
+ if (series)
+ m_upper = new AreaBoundItem(this, series);
+ else
+ m_upper = 0;
+ if (m_upper) {
+ m_upper->setPresenter(presenter());
+ fixEdgeSeriesDomain(m_upper);
+ } else {
+ updatePath();
+ }
+}
+
+void AreaChartItem::setLowerSeries(QLineSeries *series)
+{
+ delete m_lower;
+ if (series)
+ m_lower = new AreaBoundItem(this, series);
+ else
+ m_lower = 0;
+ if (m_lower) {
+ m_lower->setPresenter(presenter());
+ fixEdgeSeriesDomain(m_lower);
+ } else {
+ updatePath();
}
- ChartItem::setPresenter(presenter);
}
QRectF AreaChartItem::boundingRect() const
@@ -116,31 +145,34 @@ void AreaChartItem::updatePath()
QPainterPath path;
QRectF rect(QPointF(0,0),domain()->size());
- path = m_upper->path();
-
- if (m_lower) {
- // Note: Polarcharts always draw area correctly only when both series have equal width or are
- // fully displayed. If one series is partally off-chart, the connecting line between
- // the series does not attach to the end of the partially hidden series but to the point
- // where it intersects the axis line. The problem is especially noticeable when one of the series
- // is entirely off-chart, in which case the connecting line connects two ends of the
- // visible series.
- // This happens because we get the paths from linechart, which omits off-chart segments.
- // To properly fix, linechart would need to provide true full path, in right, left, and the rest
- // portions to enable proper clipping. However, combining those to single visually unified area
- // would be a nightmare, since they would have to be painted separately.
- path.connectPath(m_lower->path().toReversed());
- } else {
- QPointF first = path.pointAtPercent(0);
- QPointF last = path.pointAtPercent(1);
- if (presenter()->chartType() == QChart::ChartTypeCartesian) {
- path.lineTo(last.x(), rect.bottom());
- path.lineTo(first.x(), rect.bottom());
- } else { // polar
- path.lineTo(rect.center());
+ if (m_upper) {
+ path = m_upper->path();
+
+ if (m_lower) {
+ // Note: Polarcharts draw area correctly only when both series have equal width or are
+ // fully displayed. If one series is partally off-chart, the connecting line between
+ // the series does not attach to the end of the partially hidden series but to the point
+ // where it intersects the axis line. The problem is especially noticeable when one of
+ // the series is entirely off-chart, in which case the connecting line connects two
+ // ends of the visible series.
+ // This happens because we get the paths from linechart, which omits off-chart segments.
+ // To properly fix, linechart would need to provide true full path, in right, left,
+ // and the rest portions to enable proper clipping. However, combining those to single
+ // visually unified area would be a nightmare, since they would have to be painted
+ // separately.
+ path.connectPath(m_lower->path().toReversed());
+ } else {
+ QPointF first = path.pointAtPercent(0);
+ QPointF last = path.pointAtPercent(1);
+ if (presenter()->chartType() == QChart::ChartTypeCartesian) {
+ path.lineTo(last.x(), rect.bottom());
+ path.lineTo(first.x(), rect.bottom());
+ } else { // polar
+ path.lineTo(rect.center());
+ }
}
+ path.closeSubpath();
}
- path.closeSubpath();
// Only zoom in if the bounding rect of the path fits inside int limits. QWidget::update() uses
// a region that has to be compatible with QRect.
@@ -199,6 +231,7 @@ void AreaChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
{
Q_UNUSED(widget)
Q_UNUSED(option)
+
painter->save();
painter->setPen(m_linePen);
painter->setBrush(m_brush);
@@ -211,7 +244,8 @@ void AreaChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
painter->drawPath(m_path);
if (m_pointsVisible) {
painter->setPen(m_pointPen);
- painter->drawPoints(m_upper->geometryPoints());
+ if (m_upper)
+ painter->drawPoints(m_upper->geometryPoints());
if (m_lower)
painter->drawPoints(m_lower->geometryPoints());
}
@@ -275,7 +309,7 @@ void AreaChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
void AreaChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
- emit pressed(m_upper->domain()->calculateDomainPoint(event->pos()));
+ emit pressed(domain()->calculateDomainPoint(event->pos()));
m_lastMousePos = event->pos();
m_mousePressed = true;
ChartItem::mousePressEvent(event);
@@ -297,16 +331,16 @@ void AreaChartItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
void AreaChartItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
- emit released(m_upper->domain()->calculateDomainPoint(m_lastMousePos));
+ emit released(domain()->calculateDomainPoint(m_lastMousePos));
if (m_mousePressed)
- emit clicked(m_upper->domain()->calculateDomainPoint(m_lastMousePos));
+ emit clicked(domain()->calculateDomainPoint(m_lastMousePos));
m_mousePressed = false;
ChartItem::mouseReleaseEvent(event);
}
void AreaChartItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
- emit doubleClicked(m_upper->domain()->calculateDomainPoint(m_lastMousePos));
+ emit doubleClicked(domain()->calculateDomainPoint(m_lastMousePos));
ChartItem::mouseDoubleClickEvent(event);
}
diff --git a/src/charts/areachart/areachartitem_p.h b/src/charts/areachart/areachartitem_p.h
index a36315ed..be943877 100644
--- a/src/charts/areachart/areachartitem_p.h
+++ b/src/charts/areachart/areachartitem_p.h
@@ -68,6 +68,9 @@ public:
void setPresenter(ChartPresenter *presenter);
QAreaSeries *series() const { return m_series; }
+ void setUpperSeries(QLineSeries *series);
+ void setLowerSeries(QLineSeries *series);
+
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
diff --git a/src/charts/areachart/qareaseries.cpp b/src/charts/areachart/qareaseries.cpp
index ebff7f0f..739efd71 100644
--- a/src/charts/areachart/qareaseries.cpp
+++ b/src/charts/areachart/qareaseries.cpp
@@ -406,13 +406,18 @@ QAbstractSeries::SeriesType QAreaSeries::type() const
/*!
Sets the \a series that is to be used as the area chart upper series.
+ If the upper series is null, the area chart is not drawn, even if it has a lower series.
*/
void QAreaSeries::setUpperSeries(QLineSeries *series)
{
Q_D(QAreaSeries);
+
if (d->m_upperSeries != series) {
- series->d_ptr->setBlockOpenGL(true);
+ if (series)
+ series->d_ptr->setBlockOpenGL(true);
d->m_upperSeries = series;
+ if (!d->m_item.isNull())
+ static_cast<AreaChartItem *>(d->m_item.data())->setUpperSeries(series);
}
}
@@ -428,8 +433,13 @@ QLineSeries *QAreaSeries::upperSeries() const
void QAreaSeries::setLowerSeries(QLineSeries *series)
{
Q_D(QAreaSeries);
- series->d_ptr->setBlockOpenGL(true);
- d->m_lowerSeries = series;
+ if (d->m_lowerSeries != series) {
+ if (series)
+ series->d_ptr->setBlockOpenGL(true);
+ d->m_lowerSeries = series;
+ if (!d->m_item.isNull())
+ static_cast<AreaChartItem *>(d->m_item.data())->setLowerSeries(series);
+ }
}
QLineSeries *QAreaSeries::lowerSeries() const
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index e8cad75c..35f93556 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -23,6 +23,7 @@ SUBDIRS += \
domain \
chartdataset \
qlegend \
+ qareaseries \
cmake
!contains(QT_COORD_TYPE, float): {
diff --git a/tests/auto/qareaseries/qareaseries.pro b/tests/auto/qareaseries/qareaseries.pro
new file mode 100644
index 00000000..a87857ab
--- /dev/null
+++ b/tests/auto/qareaseries/qareaseries.pro
@@ -0,0 +1,4 @@
+!include( ../auto.pri ) {
+ error( "Couldn't find the auto.pri file!" )
+}
+SOURCES += tst_qareaseries.cpp
diff --git a/tests/auto/qareaseries/tst_qareaseries.cpp b/tests/auto/qareaseries/tst_qareaseries.cpp
new file mode 100644
index 00000000..e03989c0
--- /dev/null
+++ b/tests/auto/qareaseries/tst_qareaseries.cpp
@@ -0,0 +1,183 @@
+/******************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Charts module.
+**
+** $QT_BEGIN_LICENSE:COMM$
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** $QT_END_LICENSE$
+**
+******************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtGui/QImage>
+#include <QtCharts/QChartView>
+#include <QtCharts/QAreaSeries>
+#include <QtCharts/QLineSeries>
+#include <QtCharts/QChartView>
+#include <QtCharts/QValueAxis>
+#include <tst_definitions.h>
+
+QT_CHARTS_USE_NAMESPACE
+
+class tst_QAreaSeries : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void areaSeries();
+ void dynamicEdgeSeriesChange();
+
+protected:
+ QLineSeries *createUpperSeries();
+ QLineSeries *createLowerSeries();
+ void checkPixels(const QColor &upperColor, const QColor &centerColor, const QColor &lowerColor);
+
+ QChartView *m_view;
+ QChart *m_chart;
+ QColor m_brushColor;
+ QColor m_backgroundColor;
+ QValueAxis *m_axisX;
+ QValueAxis *m_axisY;
+};
+
+void tst_QAreaSeries::initTestCase()
+{
+ m_brushColor = QColor("#123456");
+ m_backgroundColor = QColor("#abcfef");
+}
+
+void tst_QAreaSeries::cleanupTestCase()
+{
+ QTest::qWait(1); // Allow final deleteLaters to run
+}
+
+void tst_QAreaSeries::init()
+{
+ m_view = new QChartView(newQChartOrQPolarChart());
+ m_view->setGeometry(0, 0, 400, 400);
+ m_chart = m_view->chart();
+ m_chart->setBackgroundBrush(m_backgroundColor);
+ m_chart->legend()->setVisible(false);
+ m_axisX = new QValueAxis;
+ m_axisY = new QValueAxis;
+ m_axisX->setRange(0, 4);
+ m_axisY->setRange(0, 10);
+ m_chart->addAxis(m_axisX, Qt::AlignBottom);
+ m_chart->addAxis(m_axisY, Qt::AlignRight);
+}
+
+void tst_QAreaSeries::cleanup()
+{
+ delete m_view;
+ m_view = 0;
+ m_chart = 0;
+}
+
+void tst_QAreaSeries::areaSeries()
+{
+ QLineSeries *series0 = createUpperSeries();
+ QLineSeries *series1 = createLowerSeries();
+ QAreaSeries *series = new QAreaSeries(series0, series1);
+
+ QCOMPARE(series->brush(), QBrush());
+ QCOMPARE(series->pen(), QPen());
+ QCOMPARE(series->pointsVisible(), false);
+ QCOMPARE(series->pointLabelsVisible(), false);
+ QCOMPARE(series->pointLabelsFormat(), QLatin1String("@xPoint, @yPoint"));
+ QCOMPARE(series->pointLabelsClipping(), true);
+ QCOMPARE(series->pointLabelsColor(), QPen().color());
+ QCOMPARE(series->upperSeries(), series0);
+ QCOMPARE(series->lowerSeries(), series1);
+ QCOMPARE(series->color(), QPen().color());
+ QCOMPARE(series->borderColor(), QPen().color());
+
+ series->setBrush(QBrush(m_brushColor));
+ m_chart->addSeries(series);
+ series->attachAxis(m_axisX);
+ series->attachAxis(m_axisY);
+ m_view->show();
+ QTest::qWaitForWindowShown(m_view);
+
+ checkPixels(m_backgroundColor, m_brushColor, m_backgroundColor);
+}
+
+void tst_QAreaSeries::dynamicEdgeSeriesChange()
+{
+ QAreaSeries *series = new QAreaSeries;
+ series->setBrush(QBrush(m_brushColor));
+
+ m_chart->addSeries(series);
+ series->attachAxis(m_axisX);
+ series->attachAxis(m_axisY);
+ m_view->show();
+ QTest::qWaitForWindowShown(m_view);
+
+ checkPixels(m_backgroundColor, m_backgroundColor, m_backgroundColor);
+
+ QLineSeries *series0 = createUpperSeries();
+ series->setUpperSeries(series0);
+
+ QApplication::processEvents();
+ checkPixels(m_backgroundColor, m_brushColor, m_brushColor);
+
+ QLineSeries *series1 = createLowerSeries();
+ series->setLowerSeries(series1);
+
+ QApplication::processEvents();
+ checkPixels(m_backgroundColor, m_brushColor, m_backgroundColor);
+
+ series->setLowerSeries(nullptr);
+
+ QApplication::processEvents();
+ checkPixels(m_backgroundColor, m_brushColor, m_brushColor);
+
+ series->setUpperSeries(nullptr);
+
+ QApplication::processEvents();
+ checkPixels(m_backgroundColor, m_backgroundColor, m_backgroundColor);
+}
+
+QLineSeries *tst_QAreaSeries::createUpperSeries()
+{
+ QLineSeries *series = new QLineSeries();
+ *series << QPointF(0, 10) << QPointF(1, 7) << QPointF(2, 6) << QPointF(3, 7) << QPointF(4, 10);
+ return series;
+}
+
+QLineSeries *tst_QAreaSeries::createLowerSeries()
+{
+ QLineSeries *series = new QLineSeries();
+ *series << QPointF(0, 0) << QPointF(1, 3) << QPointF(2, 4) << QPointF(3, 3) << QPointF(4, 0);
+ return series;
+}
+
+void tst_QAreaSeries::checkPixels(const QColor &upperColor,
+ const QColor &centerColor,
+ const QColor &lowerColor)
+{
+ QImage screenGrab = m_view->grab().toImage();
+ QCOMPARE(QColor(screenGrab.pixel(200, 50)), upperColor);
+ QCOMPARE(QColor(screenGrab.pixel(200, 200)), centerColor);
+ QCOMPARE(QColor(screenGrab.pixel(200, 350)), lowerColor);
+}
+
+QTEST_MAIN(tst_QAreaSeries)
+
+#include "tst_qareaseries.moc"
+