##// END OF EJS Templates
Accelerating lineseries with OpenGL...
Miikka Heikkinen -
r2820:79a856530b69
parent child
Show More
@@ -0,0 +1,118
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
7 ** This file is part of the Qt Charts module.
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
13 **
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
16 **
17 ****************************************************************************/
18
19 #include "datasource.h"
20 #include <QtCore/QtMath>
21
22 QT_CHARTS_USE_NAMESPACE
23
24 DataSource::DataSource(QObject *parent) :
25 QObject(parent),
26 m_index(-1)
27 {
28 generateData(0, 0, 0);
29 }
30
31 void DataSource::update(QAbstractSeries *series, int seriesIndex)
32 {
33 if (series) {
34 QXYSeries *xySeries = static_cast<QXYSeries *>(series);
35 const QVector<QVector<QPointF> > &seriesData = m_data.at(seriesIndex);
36 if (seriesIndex == 0)
37 m_index++;
38 if (m_index > seriesData.count() - 1)
39 m_index = 0;
40
41 QVector<QPointF> points = seriesData.at(m_index);
42 // Use replace instead of clear + append, it's optimized for performance
43 xySeries->replace(points);
44 }
45 }
46
47 void DataSource::handleSceneChanged()
48 {
49 m_dataUpdater.start();
50 }
51
52 void DataSource::updateAllSeries()
53 {
54 static int frameCount = 0;
55 static QString labelText = QStringLiteral("FPS: %1");
56
57 for (int i = 0; i < m_seriesList.size(); i++)
58 update(m_seriesList[i], i);
59
60 frameCount++;
61 int elapsed = m_fpsTimer.elapsed();
62 if (elapsed >= 1000) {
63 elapsed = m_fpsTimer.restart();
64 qreal fps = qreal(0.1 * int(10000.0 * (qreal(frameCount) / qreal(elapsed))));
65 m_fpsLabel->setText(labelText.arg(QString::number(fps, 'f', 1)));
66 frameCount = 0;
67 }
68 }
69
70 void DataSource::startUpdates(const QList<QXYSeries *> &seriesList, QLabel *fpsLabel)
71 {
72 m_seriesList = seriesList;
73 m_fpsLabel = fpsLabel;
74
75 m_dataUpdater.setInterval(0);
76 m_dataUpdater.setSingleShot(true);
77 QObject::connect(&m_dataUpdater, &QTimer::timeout,
78 this, &DataSource::updateAllSeries);
79
80 m_fpsTimer.start();
81 updateAllSeries();
82 }
83
84 void DataSource::generateData(int seriesCount, int rowCount, int colCount)
85 {
86 // Remove previous data
87 foreach (QVector<QVector<QPointF> > seriesData, m_data) {
88 foreach (QVector<QPointF> row, seriesData)
89 row.clear();
90 }
91
92 m_data.clear();
93
94 qreal xAdjustment = 20.0 / (colCount * rowCount);
95 qreal yMultiplier = 3.0 / qreal(seriesCount);
96
97 // Append the new data depending on the type
98 for (int k(0); k < seriesCount; k++) {
99 QVector<QVector<QPointF> > seriesData;
100 qreal height = qreal(k) * (10.0 / qreal(seriesCount)) + 0.3;
101 for (int i(0); i < rowCount; i++) {
102 QVector<QPointF> points;
103 points.reserve(colCount);
104 for (int j(0); j < colCount; j++) {
105 qreal x(0);
106 qreal y(0);
107 // data with sin + random component
108 y = height + (yMultiplier * qSin(3.14159265358979 / 50 * j)
109 + (yMultiplier * (qreal) rand() / (qreal) RAND_MAX));
110 // 0.000001 added to make values logaxis compatible
111 x = 0.000001 + 20.0 * (qreal(j) / qreal(colCount)) + (xAdjustment * qreal(i));
112 points.append(QPointF(x, y));
113 }
114 seriesData.append(points);
115 }
116 m_data.append(seriesData);
117 }
118 }
@@ -0,0 +1,53
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
7 ** This file is part of the Qt Charts module.
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
13 **
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
16 **
17 ****************************************************************************/
18
19 #ifndef DATASOURCE_H
20 #define DATASOURCE_H
21
22 #include <QtCore/QObject>
23 #include <QtCharts/QXYSeries>
24 #include <QtWidgets/QLabel>
25 #include <QtCore/QElapsedTimer>
26 #include <QtCore/QTimer>
27
28 QT_CHARTS_USE_NAMESPACE
29
30 class DataSource : public QObject
31 {
32 Q_OBJECT
33 public:
34 explicit DataSource(QObject *parent = 0);
35
36 void startUpdates(const QList<QXYSeries *> &seriesList, QLabel *fpsLabel);
37
38 public slots:
39 void generateData(int seriesCount, int rowCount, int colCount);
40 void update(QAbstractSeries *series, int seriesIndex);
41 void handleSceneChanged();
42 void updateAllSeries();
43
44 private:
45 QVector<QVector<QVector<QPointF> > > m_data;
46 int m_index;
47 QList<QXYSeries *> m_seriesList;
48 QLabel *m_fpsLabel;
49 QElapsedTimer m_fpsTimer;
50 QTimer m_dataUpdater;
51 };
52
53 #endif // DATASOURCE_H
@@ -0,0 +1,167
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
7 ** This file is part of the Qt Charts module.
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
13 **
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
16 **
17 ****************************************************************************/
18
19 #include "datasource.h"
20 #include <QtWidgets/QApplication>
21 #include <QtWidgets/QMainWindow>
22 #include <QtCharts/QChartView>
23 #include <QtCharts/QLineSeries>
24 #include <QtCharts/QScatterSeries>
25 #include <QtCharts/QValueAxis>
26 #include <QtCharts/QLogValueAxis>
27 #include <QtWidgets/QLabel>
28
29 // Uncomment to use logarithmic axes instead of regular value axes
30 //#define USE_LOG_AXIS
31
32 // Uncomment to use regular series instead of OpenGL accelerated series
33 //#define DONT_USE_GL_SERIES
34
35 // Uncomment to add a simple regular series (thick line) and a matching OpenGL series (thinner line)
36 // to verify the series have same visible geometry.
37 //#define ADD_SIMPLE_SERIES
38
39 QT_CHARTS_USE_NAMESPACE
40
41 int main(int argc, char *argv[])
42 {
43 QApplication a(argc, argv);
44 QStringList colors;
45 colors << "red" << "blue" << "green" << "black";
46
47 QChart *chart = new QChart();
48 chart->legend()->hide();
49
50 #ifdef USE_LOG_AXIS
51 QLogValueAxis *axisX = new QLogValueAxis;
52 QLogValueAxis *axisY = new QLogValueAxis;
53 #else
54 QValueAxis *axisX = new QValueAxis;
55 QValueAxis *axisY = new QValueAxis;
56 #endif
57
58 chart->addAxis(axisX, Qt::AlignBottom);
59 chart->addAxis(axisY, Qt::AlignLeft);
60
61 const int seriesCount = 10;
62 #ifdef DONT_USE_GL_SERIES
63 const int pointCount = 100;
64 chart->setTitle("Unaccelerated Series");
65 #else
66 const int pointCount = 10000;
67 chart->setTitle("OpenGL Accelerated Series");
68 #endif
69
70 QList<QXYSeries *> seriesList;
71 for (int i = 0; i < seriesCount; i++) {
72 QXYSeries *series = 0;
73 int colorIndex = i % colors.size();
74 if (i % 2) {
75 series = new QScatterSeries;
76 QScatterSeries *scatter = static_cast<QScatterSeries *>(series);
77 scatter->setColor(QColor(colors.at(colorIndex)));
78 scatter->setMarkerSize(qreal(colorIndex + 2) / 2.0);
79 // Scatter pen doesn't have affect in OpenGL drawing, but if you disable OpenGL drawing
80 // this makes the marker border visible and gives comparable marker size to OpenGL
81 // scatter points.
82 scatter->setPen(QPen("black"));
83 } else {
84 series = new QLineSeries;
85 series->setPen(QPen(QBrush(QColor(colors.at(colorIndex))),
86 qreal(colorIndex + 2) / 2.0));
87 }
88 seriesList.append(series);
89 #ifdef DONT_USE_GL_SERIES
90 series->setUseOpenGL(false);
91 #else
92 //![1]
93 series->setUseOpenGL(true);
94 //![1]
95 #endif
96 chart->addSeries(series);
97 series->attachAxis(axisX);
98 series->attachAxis(axisY);
99 }
100
101 if (axisX->type() == QAbstractAxis::AxisTypeLogValue)
102 axisX->setRange(0.1, 20.0);
103 else
104 axisX->setRange(0, 20.0);
105
106 if (axisY->type() == QAbstractAxis::AxisTypeLogValue)
107 axisY->setRange(0.1, 10.0);
108 else
109 axisY->setRange(0, 10.0);
110
111 #ifdef ADD_SIMPLE_SERIES
112 QLineSeries *simpleRasterSeries = new QLineSeries;
113 *simpleRasterSeries << QPointF(0.001, 0.001)
114 << QPointF(2.5, 8.0)
115 << QPointF(5.0, 4.0)
116 << QPointF(7.5, 9.0)
117 << QPointF(10.0, 0.001)
118 << QPointF(12.5, 2.0)
119 << QPointF(15.0, 1.0)
120 << QPointF(17.5, 6.0)
121 << QPointF(20.0, 10.0);
122 simpleRasterSeries->setUseOpenGL(false);
123 simpleRasterSeries->setPen(QPen(QBrush("magenta"), 8));
124 chart->addSeries(simpleRasterSeries);
125 simpleRasterSeries->attachAxis(axisX);
126 simpleRasterSeries->attachAxis(axisY);
127
128 QLineSeries *simpleGLSeries = new QLineSeries;
129 simpleGLSeries->setUseOpenGL(true);
130 simpleGLSeries->setPen(QPen(QBrush("black"), 2));
131 simpleGLSeries->replace(simpleRasterSeries->points());
132 chart->addSeries(simpleGLSeries);
133 simpleGLSeries->attachAxis(axisX);
134 simpleGLSeries->attachAxis(axisY);
135 #endif
136
137 QChartView *chartView = new QChartView(chart);
138
139 QMainWindow window;
140 window.setCentralWidget(chartView);
141 window.resize(600, 400);
142 window.show();
143
144 DataSource dataSource;
145 dataSource.generateData(seriesCount, 10, pointCount);
146
147 QLabel *fpsLabel = new QLabel(&window);
148 QLabel *countLabel = new QLabel(&window);
149 QString countText = QStringLiteral("Total point count: %1");
150 countLabel->setText(countText.arg(pointCount * seriesCount));
151 countLabel->resize(window.width(), countLabel->height());
152 fpsLabel->move(10,2);
153 fpsLabel->raise();
154 fpsLabel->show();
155 countLabel->move(10, 14);
156 fpsLabel->raise();
157 countLabel->show();
158
159 // We can get more than one changed event per frame, so do async update.
160 // This also allows the application to be responsive.
161 QObject::connect(chart->scene(), &QGraphicsScene::changed,
162 &dataSource, &DataSource::handleSceneChanged);
163
164 dataSource.startUpdates(seriesList, fpsLabel);
165
166 return a.exec();
167 }
@@ -0,0 +1,9
1 !include( ../examples.pri ) {
2 error( "Couldn't find the examples.pri file!" )
3 }
4
5 TARGET = openglseries
6 SOURCES += main.cpp \
7 datasource.cpp
8 HEADERS += datasource.h
9
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,37
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
7 ** This file is part of the Qt Charts module.
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
13 **
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
16 **
17 ****************************************************************************/
18
19 /*!
20 \example openglseries
21 \title OpenGL Accelerated Series Example
22 \ingroup qtcharts_examples
23
24 \brief The example shows how to enable OpenGL acceleration for QLineSeries and QScatterSeries.
25
26 \image examples_openglseries.png
27
28 To create an OpenGL accelerated series, all you have to do compared to a regular
29 series is to set QAbstractSeries::useOpenGL property to \c{true}:
30
31 \snippet openglseries/main.cpp 1
32
33 This makes the chart to instantiate a transparent QOpenGLWidget that is used to draw
34 the accelerated series on top of the chart.
35
36 \note The OpenGL acceleration is only supported for QLineSeries and QScatterSeries.
37 */
@@ -0,0 +1,222
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
7 ** This file is part of the Qt Charts module.
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
13 **
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
16 **
17 ****************************************************************************/
18
19 #ifndef QT_NO_OPENGL
20
21 #include "private/glwidget_p.h"
22 #include "private/glxyseriesdata_p.h"
23 #include <QtGui/QOpenGLShaderProgram>
24 #include <QtGui/QOpenGLContext>
25 #include <QtGui/QOpenGLBuffer>
26
27 //#define QDEBUG_TRACE_GL_FPS
28 #ifdef QDEBUG_TRACE_GL_FPS
29 # include <QElapsedTimer>
30 #endif
31
32 QT_CHARTS_BEGIN_NAMESPACE
33
34 GLWidget::GLWidget(GLXYSeriesDataManager *xyDataManager, QWidget *parent)
35 : QOpenGLWidget(parent),
36 m_program(0),
37 m_shaderAttribLoc(-1),
38 m_colorUniformLoc(-1),
39 m_minUniformLoc(-1),
40 m_deltaUniformLoc(-1),
41 m_pointSizeUniformLoc(-1),
42 m_xyDataManager(xyDataManager)
43 {
44 setAttribute(Qt::WA_TranslucentBackground);
45 setAttribute(Qt::WA_AlwaysStackOnTop);
46 setAttribute(Qt::WA_TransparentForMouseEvents);
47
48 QSurfaceFormat surfaceFormat;
49 surfaceFormat.setDepthBufferSize(0);
50 surfaceFormat.setStencilBufferSize(0);
51 surfaceFormat.setRedBufferSize(8);
52 surfaceFormat.setGreenBufferSize(8);
53 surfaceFormat.setBlueBufferSize(8);
54 surfaceFormat.setAlphaBufferSize(8);
55 surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
56 surfaceFormat.setRenderableType(QSurfaceFormat::DefaultRenderableType);
57 setFormat(surfaceFormat);
58
59 connect(xyDataManager, &GLXYSeriesDataManager::seriesRemoved,
60 this, &GLWidget::cleanXYSeriesResources);
61 }
62
63 GLWidget::~GLWidget()
64 {
65 cleanup();
66 }
67
68 void GLWidget::cleanup()
69 {
70 makeCurrent();
71
72 delete m_program;
73 m_program = 0;
74
75 foreach (QOpenGLBuffer *buffer, m_seriesBufferMap.values())
76 delete buffer;
77 m_seriesBufferMap.clear();
78
79 doneCurrent();
80 }
81
82 void GLWidget::cleanXYSeriesResources(const QXYSeries *series)
83 {
84 makeCurrent();
85 if (series) {
86 delete m_seriesBufferMap.take(series);
87 } else {
88 // Null series means all series were removed
89 foreach (QOpenGLBuffer *buffer, m_seriesBufferMap.values())
90 delete buffer;
91 m_seriesBufferMap.clear();
92 }
93 doneCurrent();
94 }
95
96 static const char *vertexSource =
97 "attribute highp vec2 points;\n"
98 "uniform highp vec2 min;\n"
99 "uniform highp vec2 delta;\n"
100 "uniform highp float pointSize;\n"
101 "void main() {\n"
102 " vec2 normalPoint = vec2(-1, -1) + ((points - min) / delta);\n"
103 " gl_Position = vec4(normalPoint, 0, 1);\n"
104 " gl_PointSize = pointSize;\n"
105 "}";
106 static const char *fragmentSource =
107 "uniform highp vec3 color;\n"
108 "void main() {\n"
109 " gl_FragColor = vec4(color,1);\n"
110 "}\n";
111
112 void GLWidget::initializeGL()
113 {
114 connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::cleanup);
115
116 initializeOpenGLFunctions();
117 glClearColor(0, 0, 0, 0);
118
119 m_program = new QOpenGLShaderProgram;
120 m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource);
121 m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentSource);
122 m_program->bindAttributeLocation("points", 0);
123 m_program->link();
124
125 m_program->bind();
126 m_colorUniformLoc = m_program->uniformLocation("color");
127 m_minUniformLoc = m_program->uniformLocation("min");
128 m_deltaUniformLoc = m_program->uniformLocation("delta");
129 m_pointSizeUniformLoc = m_program->uniformLocation("pointSize");
130
131
132 // Create a vertex array object. In OpenGL ES 2.0 and OpenGL 2.x
133 // implementations this is optional and support may not be present
134 // at all. Nonetheless the below code works in all cases and makes
135 // sure there is a VAO when one is needed.
136 m_vao.create();
137 QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
138
139 glEnableVertexAttribArray(0);
140
141 glDisable(GL_DEPTH_TEST);
142 glDisable(GL_STENCIL_TEST);
143
144 #if !defined(QT_OPENGL_ES_2)
145 if (!QOpenGLContext::currentContext()->isOpenGLES()) {
146 // Make it possible to change point primitive size and use textures with them in
147 // the shaders. These are implicitly enabled in ES2.
148 glEnable(GL_PROGRAM_POINT_SIZE);
149 }
150 #endif
151
152 m_program->release();
153 }
154
155 void GLWidget::paintGL()
156 {
157 glClear(GL_COLOR_BUFFER_BIT);
158
159 QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
160 m_program->bind();
161
162 GLXYDataMapIterator i(m_xyDataManager->dataMap());
163 while (i.hasNext()) {
164 i.next();
165 QOpenGLBuffer *vbo = m_seriesBufferMap.value(i.key());
166 GLXYSeriesData *data = i.value();
167
168 m_program->setUniformValue(m_colorUniformLoc, data->color);
169 m_program->setUniformValue(m_minUniformLoc, data->min);
170 m_program->setUniformValue(m_deltaUniformLoc, data->delta);
171
172 if (!vbo) {
173 vbo = new QOpenGLBuffer;
174 m_seriesBufferMap.insert(i.key(), vbo);
175 vbo->create();
176 }
177 vbo->bind();
178 if (data->dirty) {
179 vbo->allocate(data->array.constData(), data->array.count() * sizeof(GLfloat));
180 data->dirty = false;
181 }
182
183 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
184 if (data->type == QAbstractSeries::SeriesTypeLine) {
185 glLineWidth(data->width);
186 glDrawArrays(GL_LINE_STRIP, 0, data->array.size() / 2);
187 } else { // Scatter
188 m_program->setUniformValue(m_pointSizeUniformLoc, data->width);
189 glDrawArrays(GL_POINTS, 0, data->array.size() / 2);
190 }
191 vbo->release();
192 }
193
194 #ifdef QDEBUG_TRACE_GL_FPS
195 static QElapsedTimer stopWatch;
196 static int frameCount = -1;
197 if (frameCount == -1) {
198 stopWatch.start();
199 frameCount = 0;
200 }
201 frameCount++;
202 int elapsed = stopWatch.elapsed();
203 if (elapsed >= 1000) {
204 elapsed = stopWatch.restart();
205 qreal fps = qreal(0.1 * int(10000.0 * (qreal(frameCount) / qreal(elapsed))));
206 qDebug() << "FPS:" << fps;
207 frameCount = 0;
208 }
209 #endif
210
211 m_program->release();
212 }
213
214 void GLWidget::resizeGL(int w, int h)
215 {
216 Q_UNUSED(w)
217 Q_UNUSED(h)
218 }
219
220 QT_CHARTS_END_NAMESPACE
221
222 #endif
@@ -0,0 +1,80
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
7 ** This file is part of the Qt Charts module.
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
13 **
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
16 **
17 ****************************************************************************/
18
19 // W A R N I N G
20 // -------------
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
25 //
26 // We mean it.
27
28 #ifndef GLWIDGET_H
29 #define GLWIDGET_H
30
31 #ifndef QT_NO_OPENGL
32
33 #include <QtWidgets/QOpenGLWidget>
34 #include <QtGui/QOpenGLFunctions>
35 #include <QtGui/QOpenGLVertexArrayObject>
36 #include <QtCore/QHash>
37 #include <QtCharts/QAbstractSeries>
38 #include <QtCharts/QXYSeries>
39
40 QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram)
41
42 class QOpenGLBuffer;
43
44 QT_CHARTS_BEGIN_NAMESPACE
45
46 class GLXYSeriesDataManager;
47
48 class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions
49 {
50 Q_OBJECT
51
52 public:
53 GLWidget(GLXYSeriesDataManager *xyDataManager, QWidget *parent = 0);
54 ~GLWidget();
55
56 public Q_SLOTS:
57 void cleanup();
58 void cleanXYSeriesResources(const QXYSeries *series);
59
60 protected:
61 void initializeGL() Q_DECL_OVERRIDE;
62 void paintGL() Q_DECL_OVERRIDE;
63 void resizeGL(int width, int height) Q_DECL_OVERRIDE;
64
65 private:
66 QOpenGLShaderProgram *m_program;
67 int m_shaderAttribLoc;
68 int m_colorUniformLoc;
69 int m_minUniformLoc;
70 int m_deltaUniformLoc;
71 int m_pointSizeUniformLoc;
72 QOpenGLVertexArrayObject m_vao;
73
74 QHash<const QAbstractSeries *, QOpenGLBuffer *> m_seriesBufferMap;
75 GLXYSeriesDataManager *m_xyDataManager;
76 };
77
78 QT_CHARTS_END_NAMESPACE
79 #endif
80 #endif
@@ -0,0 +1,147
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
7 ** This file is part of the Qt Charts module.
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
13 **
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
16 **
17 ****************************************************************************/
18
19 #include "private/glxyseriesdata_p.h"
20 #include "private/abstractdomain_p.h"
21 #include <QtCharts/QScatterSeries>
22
23 QT_CHARTS_BEGIN_NAMESPACE
24
25 GLXYSeriesDataManager::GLXYSeriesDataManager(QObject *parent)
26 : QObject(parent),
27 m_mapDirty(false)
28 {
29 }
30
31 GLXYSeriesDataManager::~GLXYSeriesDataManager()
32 {
33 cleanup();
34 }
35
36 void GLXYSeriesDataManager::setPoints(QXYSeries *series, const AbstractDomain *domain)
37 {
38 GLXYSeriesData *data = m_seriesDataMap.value(series);
39 if (!data) {
40 data = new GLXYSeriesData;
41 data->type = series->type();
42 QColor sc;
43 if (data->type == QAbstractSeries::SeriesTypeScatter) {
44 QScatterSeries *scatter = static_cast<QScatterSeries *>(series);
45 data->width = float(scatter->markerSize());
46 sc = scatter->color(); // Scatter overwrites color property
47 } else {
48 data->width = float(series->pen().widthF());
49 sc = series->color();
50 }
51 data->color = QVector3D(float(sc.redF()), float(sc.greenF()), float(sc.blueF()));
52 connect(series, &QXYSeries::penChanged, this,
53 &GLXYSeriesDataManager::handleSeriesPenChange);
54 connect(series, &QXYSeries::useOpenGLChanged, this,
55 &GLXYSeriesDataManager::handleSeriesOpenGLChange);
56 m_seriesDataMap.insert(series, data);
57 m_mapDirty = true;
58 }
59 QVector<float> &array = data->array;
60
61 bool logAxis = false;
62 foreach (QAbstractAxis* axis, series->attachedAxes()) {
63 if (axis->type() == QAbstractAxis::AxisTypeLogValue) {
64 logAxis = true;
65 break;
66 }
67 }
68
69 int count = series->count();
70 int index = 0;
71 array.resize(count * 2);
72 if (logAxis) {
73 // Use domain to resolve geometry points. Not as fast as shaders, but simpler that way
74 QVector<QPointF> geometryPoints = domain->calculateGeometryPoints(series->pointsVector());
75 const float height = domain->size().height();
76 if (geometryPoints.size()) {
77 for (int i = 0; i < count; i++) {
78 const QPointF &point = geometryPoints.at(i);
79 array[index++] = float(point.x());
80 array[index++] = float(height - point.y());
81 }
82 } else {
83 // If there are invalid log values, geometry points generation fails
84 for (int i = 0; i < count; i++) {
85 array[index++] = 0.0f;
86 array[index++] = 0.0f;
87 }
88 }
89 data->min = QVector2D(0, 0);
90 data->delta = QVector2D(domain->size().width() / 2.0f, domain->size().height() / 2.0f);
91 } else {
92 // Regular value axes, so we can do the math easily on shaders.
93 QVector<QPointF> seriesPoints = series->pointsVector();
94 for (int i = 0; i < count; i++) {
95 const QPointF &point = seriesPoints.at(i);
96 array[index++] = float(point.x());
97 array[index++] = float(point.y());
98 }
99 data->min = QVector2D(domain->minX(), domain->minY());
100 data->delta = QVector2D((domain->maxX() - domain->minX()) / 2.0f,
101 (domain->maxY() - domain->minY()) / 2.0f);
102 }
103 data->dirty = true;
104 }
105
106 void GLXYSeriesDataManager::removeSeries(const QXYSeries *series)
107 {
108 GLXYSeriesData *data = m_seriesDataMap.take(series);
109 if (data) {
110 disconnect(series, 0, this, 0);
111 delete data;
112 emit seriesRemoved(series);
113 m_mapDirty = true;
114 }
115 }
116
117 void GLXYSeriesDataManager::cleanup()
118 {
119 foreach (GLXYSeriesData *data, m_seriesDataMap.values())
120 delete data;
121 m_seriesDataMap.clear();
122 m_mapDirty = true;
123 // Signal all series removal by using zero as parameter
124 emit seriesRemoved(0);
125 }
126
127 void GLXYSeriesDataManager::handleSeriesPenChange()
128 {
129 QXYSeries *series = qobject_cast<QXYSeries *>(sender());
130 if (series) {
131 GLXYSeriesData *data = m_seriesDataMap.value(series);
132 if (data) {
133 QColor sc = series->color();
134 data->color = QVector3D(float(sc.redF()), float(sc.greenF()), float(sc.blueF()));
135 data->width = float(series->pen().widthF());
136 }
137 }
138 }
139
140 void GLXYSeriesDataManager::handleSeriesOpenGLChange()
141 {
142 QXYSeries *series = qobject_cast<QXYSeries *>(sender());
143 if (!series->useOpenGL())
144 removeSeries(series);
145 }
146
147 QT_CHARTS_END_NAMESPACE
@@ -0,0 +1,91
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
7 ** This file is part of the Qt Charts module.
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
13 **
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
16 **
17 ****************************************************************************/
18
19 // W A R N I N G
20 // -------------
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
25 //
26 // We mean it.
27
28 #ifndef GLXYSERIESDATA_H
29 #define GLXYSERIESDATA_H
30
31 #include <QtCore/QMap>
32 #include <QtCharts/QAbstractSeries>
33 #include <QtCharts/QXYSeries>
34 #include <QtGui/QVector3D>
35 #include <QtGui/QVector2D>
36
37 QT_CHARTS_BEGIN_NAMESPACE
38
39 class AbstractDomain;
40
41 struct GLXYSeriesData {
42 QVector<float> array;
43 bool dirty;
44 QVector3D color;
45 float width;
46 QAbstractSeries::SeriesType type;
47 QVector2D min;
48 QVector2D delta;
49 };
50
51 typedef QMap<const QXYSeries *, GLXYSeriesData *> GLXYDataMap;
52 typedef QMapIterator<const QXYSeries *, GLXYSeriesData *> GLXYDataMapIterator;
53
54 class GLXYSeriesDataManager : public QObject
55 {
56 Q_OBJECT
57
58 public:
59 GLXYSeriesDataManager(QObject *parent = 0);
60 ~GLXYSeriesDataManager();
61
62 void setPoints(QXYSeries *series, const AbstractDomain *domain);
63
64 void removeSeries(const QXYSeries *series);
65
66 GLXYDataMap &dataMap() { return m_seriesDataMap; }
67
68 // These functions are needed by qml side, so they must be inline
69 bool mapDirty() const { return m_mapDirty; }
70 void clearAllDirty() {
71 m_mapDirty = false;
72 foreach (GLXYSeriesData *data, m_seriesDataMap.values())
73 data->dirty = false;
74 }
75
76 public Q_SLOTS:
77 void cleanup();
78 void handleSeriesPenChange();
79 void handleSeriesOpenGLChange();
80
81 Q_SIGNALS:
82 void seriesRemoved(const QXYSeries *series);
83
84 private:
85 GLXYDataMap m_seriesDataMap;
86 bool m_mapDirty;
87 };
88
89 QT_CHARTS_END_NAMESPACE
90
91 #endif
@@ -0,0 +1,78
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
7 ** This file is part of the Qt Charts module.
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
13 **
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
16 **
17 ****************************************************************************/
18
19 #include "declarativechartnode.h"
20 #include "declarativerendernode.h"
21 #include <QtGui/QOpenGLContext>
22 #include <QtGui/QOpenGLFunctions>
23 #include <QtGui/QOpenGLFramebufferObjectFormat>
24 #include <QtGui/QOpenGLFramebufferObject>
25 #include <QOpenGLShaderProgram>
26 #include <QtGui/QOpenGLBuffer>
27
28 QT_CHARTS_BEGIN_NAMESPACE
29
30 // This node handles displaying of the chart itself
31 DeclarativeChartNode::DeclarativeChartNode(QQuickWindow *window) :
32 QSGSimpleTextureNode(),
33 m_texture(0),
34 m_window(window),
35 m_textureOptions(0),
36 m_textureSize(1, 1),
37 m_glRenderNode(0)
38 {
39 initializeOpenGLFunctions();
40
41 // Our texture node must have a texture, so use a default one pixel texture
42 GLuint defaultTexture = 0;
43 glGenTextures(1, &defaultTexture);
44 glBindTexture(GL_TEXTURE_2D, defaultTexture);
45 uchar buf[4] = { 0, 0, 0, 0 };
46 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &buf);
47
48 QQuickWindow::CreateTextureOptions defaultTextureOptions = QQuickWindow::CreateTextureOptions(
49 QQuickWindow::TextureHasAlphaChannel | QQuickWindow::TextureOwnsGLTexture);
50 m_texture = m_window->createTextureFromId(defaultTexture, QSize(1, 1), defaultTextureOptions);
51
52 setTexture(m_texture);
53 setFiltering(QSGTexture::Linear);
54
55 // Create child node for rendering GL graphics
56 m_glRenderNode = new DeclarativeRenderNode(m_window);
57 m_glRenderNode->setFlag(OwnedByParent);
58 appendChildNode(m_glRenderNode);
59 m_glRenderNode->setRect(0, 0, 0, 0); // Hide child node by default
60 }
61
62 DeclarativeChartNode::~DeclarativeChartNode()
63 {
64 delete m_texture;
65 }
66
67 // Must be called on render thread and in context
68 void DeclarativeChartNode::createTextureFromImage(const QImage &chartImage)
69 {
70 if (chartImage.size() != m_textureSize)
71 m_textureSize = chartImage.size();
72
73 delete m_texture;
74 m_texture = m_window->createTextureFromImage(chartImage, m_textureOptions);
75 setTexture(m_texture);
76 }
77
78 QT_CHARTS_END_NAMESPACE
@@ -0,0 +1,50
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
7 ** This file is part of the Qt Charts module.
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
13 **
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
16 **
17 ****************************************************************************/
18
19 #ifndef DECLARATIVECHARTNODE_P_H
20 #define DECLARATIVECHARTNODE_P_H
21
22 #include <QtCharts/QChartGlobal>
23 #include <QtQuick/QSGSimpleTextureNode>
24 #include <QtQuick/QQuickWindow>
25 #include <QtGui/QOpenGLFunctions>
26
27 QT_CHARTS_BEGIN_NAMESPACE
28
29 class DeclarativeRenderNode;
30
31 class DeclarativeChartNode : public QSGSimpleTextureNode, QOpenGLFunctions
32 {
33 public:
34 DeclarativeChartNode(QQuickWindow *window);
35 ~DeclarativeChartNode();
36
37 void createTextureFromImage(const QImage &chartImage);
38 DeclarativeRenderNode *glRenderNode() const { return m_glRenderNode; }
39
40 private:
41 QSGTexture *m_texture;
42 QQuickWindow *m_window;
43 QQuickWindow::CreateTextureOptions m_textureOptions;
44 QSize m_textureSize;
45 DeclarativeRenderNode *m_glRenderNode;
46 };
47
48 QT_CHARTS_END_NAMESPACE
49
50 #endif // DECLARATIVECHARTNODE_P_H
@@ -0,0 +1,317
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
7 ** This file is part of the Qt Charts module.
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
13 **
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
16 **
17 ****************************************************************************/
18
19 #include "declarativerendernode.h"
20
21 #include <QtGui/QOpenGLContext>
22 #include <QtGui/QOpenGLFunctions>
23 #include <QtGui/QOpenGLFramebufferObjectFormat>
24 #include <QtGui/QOpenGLFramebufferObject>
25 #include <QOpenGLShaderProgram>
26 #include <QtGui/QOpenGLBuffer>
27
28 //#define QDEBUG_TRACE_GL_FPS
29 #ifdef QDEBUG_TRACE_GL_FPS
30 # include <QElapsedTimer>
31 #endif
32
33 QT_CHARTS_BEGIN_NAMESPACE
34
35 // This node draws the xy series data on a transparent background using OpenGL.
36 // It is used as a child node of the chart node.
37 DeclarativeRenderNode::DeclarativeRenderNode(QQuickWindow *window) :
38 QObject(),
39 QSGSimpleTextureNode(),
40 m_texture(0),
41 m_window(window),
42 m_textureOptions(QQuickWindow::TextureHasAlphaChannel),
43 m_textureSize(1, 1),
44 m_recreateFbo(false),
45 m_fbo(0),
46 m_program(0),
47 m_shaderAttribLoc(-1),
48 m_colorUniformLoc(-1),
49 m_minUniformLoc(-1),
50 m_deltaUniformLoc(-1),
51 m_pointSizeUniformLoc(-1),
52 m_renderNeeded(true)
53 {
54 initializeOpenGLFunctions();
55
56 // Our texture node must have a texture, so use a default one pixel texture
57 GLuint defaultTexture = 0;
58 glGenTextures(1, &defaultTexture);
59 glBindTexture(GL_TEXTURE_2D, defaultTexture);
60 uchar buf[4] = { 0, 0, 0, 0 };
61 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &buf);
62
63 QQuickWindow::CreateTextureOptions defaultTextureOptions = QQuickWindow::CreateTextureOptions(
64 QQuickWindow::TextureHasAlphaChannel | QQuickWindow::TextureOwnsGLTexture);
65 m_texture = m_window->createTextureFromId(defaultTexture, QSize(1, 1), defaultTextureOptions);
66
67 setTexture(m_texture);
68 setFiltering(QSGTexture::Linear);
69 setTextureCoordinatesTransform(QSGSimpleTextureNode::MirrorVertically);
70 }
71
72 DeclarativeRenderNode::~DeclarativeRenderNode()
73 {
74 delete m_texture;
75 delete m_fbo;
76
77 delete m_program;
78 m_program = 0;
79
80 cleanXYSeriesResources(0);
81 }
82
83 static const char *vertexSource =
84 "attribute highp vec2 points;\n"
85 "uniform highp vec2 min;\n"
86 "uniform highp vec2 delta;\n"
87 "uniform highp float pointSize;\n"
88 "void main() {\n"
89 " vec2 normalPoint = vec2(-1, -1) + ((points - min) / delta);\n"
90 " gl_Position = vec4(normalPoint, 0, 1);\n"
91 " gl_PointSize = pointSize;\n"
92 "}";
93 static const char *fragmentSource =
94 "uniform highp vec3 color;\n"
95 "void main() {\n"
96 " gl_FragColor = vec4(color,1);\n"
97 "}\n";
98
99 // Must be called on render thread and in context
100 void DeclarativeRenderNode::initGL()
101 {
102 recreateFBO();
103
104 m_program = new QOpenGLShaderProgram;
105 m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource);
106 m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentSource);
107 m_program->bindAttributeLocation("points", 0);
108 m_program->link();
109
110 m_program->bind();
111 m_colorUniformLoc = m_program->uniformLocation("color");
112 m_minUniformLoc = m_program->uniformLocation("min");
113 m_deltaUniformLoc = m_program->uniformLocation("delta");
114 m_pointSizeUniformLoc = m_program->uniformLocation("pointSize");
115
116 // Create a vertex array object. In OpenGL ES 2.0 and OpenGL 2.x
117 // implementations this is optional and support may not be present
118 // at all. Nonetheless the below code works in all cases and makes
119 // sure there is a VAO when one is needed.
120 m_vao.create();
121 QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
122
123 #if !defined(QT_OPENGL_ES_2)
124 if (!QOpenGLContext::currentContext()->isOpenGLES()) {
125 // Make it possible to change point primitive size and use textures with them in
126 // the shaders. These are implicitly enabled in ES2.
127 // Qt Quick doesn't change these flags, so it should be safe to just enable them
128 // at initialization.
129 glEnable(GL_PROGRAM_POINT_SIZE);
130 }
131 #endif
132
133 m_program->release();
134 }
135
136 void DeclarativeRenderNode::recreateFBO()
137 {
138 QOpenGLFramebufferObjectFormat fboFormat;
139 fboFormat.setAttachment(QOpenGLFramebufferObject::NoAttachment);
140 delete m_fbo;
141 m_fbo = new QOpenGLFramebufferObject(m_textureSize.width(),
142 m_textureSize.height(),
143 fboFormat);
144
145 delete m_texture;
146 m_texture = m_window->createTextureFromId(m_fbo->texture(), m_textureSize, m_textureOptions);
147 setTexture(m_texture);
148
149 m_recreateFbo = false;
150 }
151
152 // Must be called on render thread and in context
153 void DeclarativeRenderNode::setTextureSize(const QSize &size)
154 {
155 m_textureSize = size;
156 m_recreateFbo = true;
157 m_renderNeeded = true;
158 }
159
160 // Must be called on render thread while gui thread is blocked, and in context
161 void DeclarativeRenderNode::setSeriesData(bool mapDirty, const GLXYDataMap &dataMap)
162 {
163 if (mapDirty) {
164 // Series have changed, recreate map, but utilize old data where feasible
165 GLXYDataMap oldMap = m_xyDataMap;
166 m_xyDataMap.clear();
167
168 GLXYDataMapIterator i(dataMap);
169 while (i.hasNext()) {
170 i.next();
171 GLXYSeriesData *data = oldMap.take(i.key());
172 const GLXYSeriesData *newData = i.value();
173 if (!data || newData->dirty) {
174 data = new GLXYSeriesData;
175 data->array = newData->array;
176 data->color = newData->color;
177 data->dirty = newData->dirty;
178 data->width = newData->width;
179 data->type = newData->type;
180 data->min = newData->min;
181 data->delta = newData->delta;
182 }
183 m_xyDataMap.insert(i.key(), data);
184 }
185 // Delete remaining old data
186 i = oldMap;
187 while (i.hasNext()) {
188 i.next();
189 delete i.value();
190 cleanXYSeriesResources(i.key());
191 }
192 } else {
193 // Series have not changed, so just copy dirty data over
194 GLXYDataMapIterator i(dataMap);
195 while (i.hasNext()) {
196 i.next();
197 const GLXYSeriesData *newData = i.value();
198 if (i.value()->dirty) {
199 GLXYSeriesData *data = m_xyDataMap.value(i.key());
200 if (data) {
201 data->array = newData->array;
202 data->color = newData->color;
203 data->dirty = newData->dirty;
204 data->width = newData->width;
205 data->type = newData->type;
206 data->min = newData->min;
207 data->delta = newData->delta;
208 }
209 }
210 }
211 }
212 markDirty(DirtyMaterial);
213 m_renderNeeded = true;
214 }
215
216 void DeclarativeRenderNode::renderGL()
217 {
218 glClearColor(0, 0, 0, 0);
219
220 QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
221 m_program->bind();
222 m_fbo->bind();
223
224 glClear(GL_COLOR_BUFFER_BIT);
225 glEnableVertexAttribArray(0);
226
227 glViewport(0, 0, m_textureSize.width(), m_textureSize.height());
228
229 GLXYDataMapIterator i(m_xyDataMap);
230 while (i.hasNext()) {
231 i.next();
232 QOpenGLBuffer *vbo = m_seriesBufferMap.value(i.key());
233 GLXYSeriesData *data = i.value();
234
235 m_program->setUniformValue(m_colorUniformLoc, data->color);
236 m_program->setUniformValue(m_minUniformLoc, data->min);
237 m_program->setUniformValue(m_deltaUniformLoc, data->delta);
238
239 if (!vbo) {
240 vbo = new QOpenGLBuffer;
241 m_seriesBufferMap.insert(i.key(), vbo);
242 vbo->create();
243 }
244 vbo->bind();
245 if (data->dirty) {
246 vbo->allocate(data->array.constData(), data->array.count() * sizeof(GLfloat));
247 data->dirty = false;
248 }
249
250 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
251 if (data->type == QAbstractSeries::SeriesTypeLine) {
252 glLineWidth(data->width);
253 glDrawArrays(GL_LINE_STRIP, 0, data->array.size() / 2);
254 } else { // Scatter
255 m_program->setUniformValue(m_pointSizeUniformLoc, data->width);
256 glDrawArrays(GL_POINTS, 0, data->array.size() / 2);
257 }
258 vbo->release();
259 }
260
261 #ifdef QDEBUG_TRACE_GL_FPS
262 static QElapsedTimer stopWatch;
263 static int frameCount = -1;
264 if (frameCount == -1) {
265 stopWatch.start();
266 frameCount = 0;
267 }
268 frameCount++;
269 int elapsed = stopWatch.elapsed();
270 if (elapsed >= 1000) {
271 elapsed = stopWatch.restart();
272 qreal fps = qreal(0.1 * int(10000.0 * (qreal(frameCount) / qreal(elapsed))));
273 qDebug() << "FPS:" << fps;
274 frameCount = 0;
275 }
276 #endif
277
278 markDirty(DirtyMaterial);
279 m_window->resetOpenGLState();
280 }
281
282 // Must be called on render thread as response to beforeRendering signal
283 void DeclarativeRenderNode::render()
284 {
285 if (m_renderNeeded) {
286 if (m_xyDataMap.size()) {
287 if (!m_program)
288 initGL();
289 if (m_recreateFbo)
290 recreateFBO();
291 renderGL();
292 } else {
293 if (rect() != QRectF()) {
294 glClearColor(0, 0, 0, 0);
295 m_fbo->bind();
296 glClear(GL_COLOR_BUFFER_BIT);
297
298 // If last series was removed, zero out the node rect
299 setRect(QRectF());
300 }
301 }
302 m_renderNeeded = false;
303 }
304 }
305
306 void DeclarativeRenderNode::cleanXYSeriesResources(const QXYSeries *series)
307 {
308 if (series) {
309 delete m_seriesBufferMap.take(series);
310 } else {
311 foreach (QOpenGLBuffer *buffer, m_seriesBufferMap.values())
312 delete buffer;
313 m_seriesBufferMap.clear();
314 }
315 }
316
317 QT_CHARTS_END_NAMESPACE
@@ -0,0 +1,74
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
7 ** This file is part of the Qt Charts module.
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
13 **
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
16 **
17 ****************************************************************************/
18
19 #ifndef DECLARATIVERENDERNODE_P_H
20 #define DECLARATIVERENDERNODE_P_H
21
22 #include <QtCharts/QChartGlobal>
23 #include <private/glxyseriesdata_p.h>
24 #include <QtQuick/QSGSimpleTextureNode>
25 #include <QtQuick/QQuickWindow>
26 #include <QtGui/QOpenGLVertexArrayObject>
27 #include <QtGui/QOpenGLFunctions>
28
29 class QOpenGLFramebufferObject;
30 class QOpenGLBuffer;
31
32 QT_CHARTS_BEGIN_NAMESPACE
33
34 class DeclarativeRenderNode : public QObject, public QSGSimpleTextureNode, QOpenGLFunctions
35 {
36 Q_OBJECT
37 public:
38 DeclarativeRenderNode(QQuickWindow *window);
39 ~DeclarativeRenderNode();
40
41 void initGL();
42 QSize textureSize() const { return m_textureSize; }
43 void setTextureSize(const QSize &size);
44 void setSeriesData(bool mapDirty, const GLXYDataMap &dataMap);
45
46 public Q_SLOTS:
47 void render();
48
49 private:
50 void renderGL();
51 void recreateFBO();
52 void cleanXYSeriesResources(const QXYSeries *series);
53
54 QSGTexture *m_texture;
55 QQuickWindow *m_window;
56 QQuickWindow::CreateTextureOptions m_textureOptions;
57 QSize m_textureSize;
58 bool m_recreateFbo;
59 GLXYDataMap m_xyDataMap;
60 QOpenGLFramebufferObject *m_fbo;
61 QOpenGLShaderProgram *m_program;
62 int m_shaderAttribLoc;
63 int m_colorUniformLoc;
64 int m_minUniformLoc;
65 int m_deltaUniformLoc;
66 int m_pointSizeUniformLoc;
67 QOpenGLVertexArrayObject m_vao;
68 QHash<const QAbstractSeries *, QOpenGLBuffer *> m_seriesBufferMap;
69 bool m_renderNeeded;
70 };
71
72 QT_CHARTS_END_NAMESPACE
73
74 #endif // DECLARATIVERENDERNODE_P_H
@@ -1,55 +1,55
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include "xyseriesiodevice.h"
19 #include "xyseriesiodevice.h"
20 #include <QtCharts/QXYSeries>
20 #include <QtCharts/QXYSeries>
21
21
22 XYSeriesIODevice::XYSeriesIODevice(QXYSeries * series, QObject *parent) :
22 XYSeriesIODevice::XYSeriesIODevice(QXYSeries * series, QObject *parent) :
23 QIODevice(parent),
23 QIODevice(parent),
24 m_series(series)
24 m_series(series)
25 {
25 {
26 }
26 }
27
27
28 qint64 XYSeriesIODevice::readData(char * data, qint64 maxSize)
28 qint64 XYSeriesIODevice::readData(char * data, qint64 maxSize)
29 {
29 {
30 Q_UNUSED(data)
30 Q_UNUSED(data)
31 Q_UNUSED(maxSize)
31 Q_UNUSED(maxSize)
32 return -1;
32 return -1;
33 }
33 }
34
34
35 qint64 XYSeriesIODevice::writeData(const char * data, qint64 maxSize)
35 qint64 XYSeriesIODevice::writeData(const char * data, qint64 maxSize)
36 {
36 {
37 qint64 range = 2000;
37 qint64 range = 2000;
38 QList<QPointF> oldPoints = m_series->points();
38 QVector<QPointF> oldPoints = m_series->pointsVector();
39 QList<QPointF> points;
39 QVector<QPointF> points;
40 int resolution = 4;
40 int resolution = 4;
41
41
42 if (oldPoints.count() < range) {
42 if (oldPoints.count() < range) {
43 points = m_series->points();
43 points = m_series->pointsVector();
44 } else {
44 } else {
45 for (int i = maxSize/resolution; i < oldPoints.count(); i++)
45 for (int i = maxSize/resolution; i < oldPoints.count(); i++)
46 points.append(QPointF(i - maxSize/resolution, oldPoints.at(i).y()));
46 points.append(QPointF(i - maxSize/resolution, oldPoints.at(i).y()));
47 }
47 }
48
48
49 qint64 size = points.count();
49 qint64 size = points.count();
50 for (int k = 0; k < maxSize/resolution; k++)
50 for (int k = 0; k < maxSize/resolution; k++)
51 points.append(QPointF(k + size, ((quint8)data[resolution * k] - 128)/128.0));
51 points.append(QPointF(k + size, ((quint8)data[resolution * k] - 128)/128.0));
52
52
53 m_series->replace(points);
53 m_series->replace(points);
54 return maxSize;
54 return maxSize;
55 }
55 }
@@ -1,60 +1,66
1 TEMPLATE = subdirs
1 TEMPLATE = subdirs
2 SUBDIRS += areachart \
2 SUBDIRS += areachart \
3 customchart \
3 customchart \
4 linechart \
4 linechart \
5 percentbarchart \
5 percentbarchart \
6 piechart \
6 piechart \
7 piechartdrilldown \
7 piechartdrilldown \
8 scatterchart \
8 scatterchart \
9 scatterinteractions \
9 scatterinteractions \
10 splinechart \
10 splinechart \
11 stackedbarchart \
11 stackedbarchart \
12 stackedbarchartdrilldown \
12 stackedbarchartdrilldown \
13 zoomlinechart \
13 zoomlinechart \
14 modeldata \
14 modeldata \
15 barchart \
15 barchart \
16 boxplotchart \
16 boxplotchart \
17 legend \
17 legend \
18 barmodelmapper \
18 barmodelmapper \
19 lineandbar \
19 lineandbar \
20 horizontalbarchart \
20 horizontalbarchart \
21 horizontalstackedbarchart \
21 horizontalstackedbarchart \
22 horizontalpercentbarchart \
22 horizontalpercentbarchart \
23 donutbreakdown \
23 donutbreakdown \
24 temperaturerecords \
24 temperaturerecords \
25 donutchart \
25 donutchart \
26 multiaxis \
26 multiaxis \
27 legendmarkers \
27 legendmarkers \
28 logvalueaxis \
28 logvalueaxis \
29 polarchart \
29 polarchart \
30 piechartcustomization \
30 piechartcustomization \
31 dynamicspline \
31 dynamicspline \
32 nesteddonuts \
32 nesteddonuts \
33 chartinteractions \
33 chartinteractions \
34 callout \
34 callout \
35 chartthemes
35 chartthemes
36
36
37 qtHaveModule(quick) {
37 qtHaveModule(quick) {
38 SUBDIRS += qmlboxplot \
38 SUBDIRS += qmlboxplot \
39 qmlpiechart \
39 qmlpiechart \
40 qmlweather \
40 qmlweather \
41 qmlf1legends \
41 qmlf1legends \
42 qmlcustomizations \
42 qmlcustomizations \
43 qmlaxes \
43 qmlaxes \
44 qmlcustomlegend \
44 qmlcustomlegend \
45 qmlpolarchart \
45 qmlpolarchart \
46 qmlchart \
46 qmlchart \
47 qmloscilloscope
47 qmloscilloscope
48 }
48 }
49
49
50 qtHaveModule(multimedia) {
50 qtHaveModule(multimedia) {
51 SUBDIRS += audio
51 SUBDIRS += audio
52 } else {
52 } else {
53 message("QtMultimedia library not available. Some examples are disabled")
53 message("QtMultimedia library not available. Some examples are disabled.")
54 }
55
56 contains(QT_CONFIG, opengl) {
57 SUBDIRS += openglseries
58 } else {
59 message("OpenGL not available. Some examples are disabled.")
54 }
60 }
55
61
56 !linux-arm*: {
62 !linux-arm*: {
57 SUBDIRS += \
63 SUBDIRS += \
58 datetimeaxis
64 datetimeaxis
59 }
65 }
60
66
@@ -1,370 +1,370
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include "themewidget.h"
19 #include "themewidget.h"
20
20
21 #include <QtCharts/QChartView>
21 #include <QtCharts/QChartView>
22 #include <QtCharts/QPieSeries>
22 #include <QtCharts/QPieSeries>
23 #include <QtCharts/QPieSlice>
23 #include <QtCharts/QPieSlice>
24 #include <QtCharts/QAbstractBarSeries>
24 #include <QtCharts/QAbstractBarSeries>
25 #include <QtCharts/QPercentBarSeries>
25 #include <QtCharts/QPercentBarSeries>
26 #include <QtCharts/QStackedBarSeries>
26 #include <QtCharts/QStackedBarSeries>
27 #include <QtCharts/QBarSeries>
27 #include <QtCharts/QBarSeries>
28 #include <QtCharts/QBarSet>
28 #include <QtCharts/QBarSet>
29 #include <QtCharts/QLineSeries>
29 #include <QtCharts/QLineSeries>
30 #include <QtCharts/QSplineSeries>
30 #include <QtCharts/QSplineSeries>
31 #include <QtCharts/QScatterSeries>
31 #include <QtCharts/QScatterSeries>
32 #include <QtCharts/QAreaSeries>
32 #include <QtCharts/QAreaSeries>
33 #include <QtCharts/QLegend>
33 #include <QtCharts/QLegend>
34 #include <QtWidgets/QGridLayout>
34 #include <QtWidgets/QGridLayout>
35 #include <QtWidgets/QFormLayout>
35 #include <QtWidgets/QFormLayout>
36 #include <QtWidgets/QComboBox>
36 #include <QtWidgets/QComboBox>
37 #include <QtWidgets/QSpinBox>
37 #include <QtWidgets/QSpinBox>
38 #include <QtWidgets/QCheckBox>
38 #include <QtWidgets/QCheckBox>
39 #include <QtWidgets/QGroupBox>
39 #include <QtWidgets/QGroupBox>
40 #include <QtWidgets/QLabel>
40 #include <QtWidgets/QLabel>
41 #include <QtCore/QTime>
41 #include <QtCore/QTime>
42 #include <QtCharts/QBarCategoryAxis>
42 #include <QtCharts/QBarCategoryAxis>
43
43
44 ThemeWidget::ThemeWidget(QWidget *parent) :
44 ThemeWidget::ThemeWidget(QWidget *parent) :
45 QWidget(parent),
45 QWidget(parent),
46 m_listCount(3),
46 m_listCount(3),
47 m_valueMax(10),
47 m_valueMax(10),
48 m_valueCount(7),
48 m_valueCount(7),
49 m_dataTable(generateRandomData(m_listCount, m_valueMax, m_valueCount)),
49 m_dataTable(generateRandomData(m_listCount, m_valueMax, m_valueCount)),
50 m_themeComboBox(createThemeBox()),
50 m_themeComboBox(createThemeBox()),
51 m_antialiasCheckBox(new QCheckBox("Anti-aliasing")),
51 m_antialiasCheckBox(new QCheckBox("Anti-aliasing")),
52 m_animatedComboBox(createAnimationBox()),
52 m_animatedComboBox(createAnimationBox()),
53 m_legendComboBox(createLegendBox())
53 m_legendComboBox(createLegendBox())
54 {
54 {
55 connectSignals();
55 connectSignals();
56 // create layout
56 // create layout
57 QGridLayout *baseLayout = new QGridLayout();
57 QGridLayout *baseLayout = new QGridLayout();
58 QHBoxLayout *settingsLayout = new QHBoxLayout();
58 QHBoxLayout *settingsLayout = new QHBoxLayout();
59 settingsLayout->addWidget(new QLabel("Theme:"));
59 settingsLayout->addWidget(new QLabel("Theme:"));
60 settingsLayout->addWidget(m_themeComboBox);
60 settingsLayout->addWidget(m_themeComboBox);
61 settingsLayout->addWidget(new QLabel("Animation:"));
61 settingsLayout->addWidget(new QLabel("Animation:"));
62 settingsLayout->addWidget(m_animatedComboBox);
62 settingsLayout->addWidget(m_animatedComboBox);
63 settingsLayout->addWidget(new QLabel("Legend:"));
63 settingsLayout->addWidget(new QLabel("Legend:"));
64 settingsLayout->addWidget(m_legendComboBox);
64 settingsLayout->addWidget(m_legendComboBox);
65 settingsLayout->addWidget(m_antialiasCheckBox);
65 settingsLayout->addWidget(m_antialiasCheckBox);
66 settingsLayout->addStretch();
66 settingsLayout->addStretch();
67 baseLayout->addLayout(settingsLayout, 0, 0, 1, 3);
67 baseLayout->addLayout(settingsLayout, 0, 0, 1, 3);
68
68
69 //create charts
69 //create charts
70
70
71 QChartView *chartView;
71 QChartView *chartView;
72
72
73 chartView = new QChartView(createAreaChart());
73 chartView = new QChartView(createAreaChart());
74 baseLayout->addWidget(chartView, 1, 0);
74 baseLayout->addWidget(chartView, 1, 0);
75 m_charts << chartView;
75 m_charts << chartView;
76
76
77 chartView = new QChartView(createBarChart(m_valueCount));
77 chartView = new QChartView(createBarChart(m_valueCount));
78 baseLayout->addWidget(chartView, 1, 1);
78 baseLayout->addWidget(chartView, 1, 1);
79 m_charts << chartView;
79 m_charts << chartView;
80
80
81 chartView = new QChartView(createLineChart());
81 chartView = new QChartView(createLineChart());
82 baseLayout->addWidget(chartView, 1, 2);
82 baseLayout->addWidget(chartView, 1, 2);
83 m_charts << chartView;
83 m_charts << chartView;
84
84
85 chartView = new QChartView(createPieChart());
85 chartView = new QChartView(createPieChart());
86 chartView->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); // funny things happen if the pie slice labels no not fit the screen...
86 chartView->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); // funny things happen if the pie slice labels no not fit the screen...
87 baseLayout->addWidget(chartView, 2, 0);
87 baseLayout->addWidget(chartView, 2, 0);
88 m_charts << chartView;
88 m_charts << chartView;
89
89
90 chartView = new QChartView(createSplineChart());
90 chartView = new QChartView(createSplineChart());
91 baseLayout->addWidget(chartView, 2, 1);
91 baseLayout->addWidget(chartView, 2, 1);
92 m_charts << chartView;
92 m_charts << chartView;
93
93
94 chartView = new QChartView(createScatterChart());
94 chartView = new QChartView(createScatterChart());
95 baseLayout->addWidget(chartView, 2, 2);
95 baseLayout->addWidget(chartView, 2, 2);
96 m_charts << chartView;
96 m_charts << chartView;
97
97
98 setLayout(baseLayout);
98 setLayout(baseLayout);
99
99
100 // Set defaults
100 // Set defaults
101 m_antialiasCheckBox->setChecked(true);
101 m_antialiasCheckBox->setChecked(true);
102 updateUI();
102 updateUI();
103 }
103 }
104
104
105 ThemeWidget::~ThemeWidget()
105 ThemeWidget::~ThemeWidget()
106 {
106 {
107 }
107 }
108
108
109 void ThemeWidget::connectSignals()
109 void ThemeWidget::connectSignals()
110 {
110 {
111 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
111 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
112 connect(m_antialiasCheckBox, SIGNAL(toggled(bool)), this, SLOT(updateUI()));
112 connect(m_antialiasCheckBox, SIGNAL(toggled(bool)), this, SLOT(updateUI()));
113 connect(m_animatedComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
113 connect(m_animatedComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
114 connect(m_legendComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
114 connect(m_legendComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
115 }
115 }
116
116
117 DataTable ThemeWidget::generateRandomData(int listCount, int valueMax, int valueCount) const
117 DataTable ThemeWidget::generateRandomData(int listCount, int valueMax, int valueCount) const
118 {
118 {
119 DataTable dataTable;
119 DataTable dataTable;
120
120
121 // set seed for random stuff
121 // set seed for random stuff
122 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
122 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
123
123
124 // generate random data
124 // generate random data
125 for (int i(0); i < listCount; i++) {
125 for (int i(0); i < listCount; i++) {
126 DataList dataList;
126 DataList dataList;
127 qreal yValue(0);
127 qreal yValue(0);
128 for (int j(0); j < valueCount; j++) {
128 for (int j(0); j < valueCount; j++) {
129 yValue = yValue + (qreal)(qrand() % valueMax) / (qreal) valueCount;
129 yValue = yValue + (qreal)(qrand() % valueMax) / (qreal) valueCount;
130 QPointF value((j + (qreal) rand() / (qreal) RAND_MAX) * ((qreal) m_valueMax / (qreal) valueCount),
130 QPointF value((j + (qreal) rand() / (qreal) RAND_MAX) * ((qreal) m_valueMax / (qreal) valueCount),
131 yValue);
131 yValue);
132 QString label = "Slice " + QString::number(i) + ":" + QString::number(j);
132 QString label = "Slice " + QString::number(i) + ":" + QString::number(j);
133 dataList << Data(value, label);
133 dataList << Data(value, label);
134 }
134 }
135 dataTable << dataList;
135 dataTable << dataList;
136 }
136 }
137
137
138 return dataTable;
138 return dataTable;
139 }
139 }
140
140
141 QComboBox *ThemeWidget::createThemeBox() const
141 QComboBox *ThemeWidget::createThemeBox() const
142 {
142 {
143 // settings layout
143 // settings layout
144 QComboBox *themeComboBox = new QComboBox();
144 QComboBox *themeComboBox = new QComboBox();
145 themeComboBox->addItem("Light", QChart::ChartThemeLight);
145 themeComboBox->addItem("Light", QChart::ChartThemeLight);
146 themeComboBox->addItem("Blue Cerulean", QChart::ChartThemeBlueCerulean);
146 themeComboBox->addItem("Blue Cerulean", QChart::ChartThemeBlueCerulean);
147 themeComboBox->addItem("Dark", QChart::ChartThemeDark);
147 themeComboBox->addItem("Dark", QChart::ChartThemeDark);
148 themeComboBox->addItem("Brown Sand", QChart::ChartThemeBrownSand);
148 themeComboBox->addItem("Brown Sand", QChart::ChartThemeBrownSand);
149 themeComboBox->addItem("Blue NCS", QChart::ChartThemeBlueNcs);
149 themeComboBox->addItem("Blue NCS", QChart::ChartThemeBlueNcs);
150 themeComboBox->addItem("High Contrast", QChart::ChartThemeHighContrast);
150 themeComboBox->addItem("High Contrast", QChart::ChartThemeHighContrast);
151 themeComboBox->addItem("Blue Icy", QChart::ChartThemeBlueIcy);
151 themeComboBox->addItem("Blue Icy", QChart::ChartThemeBlueIcy);
152 themeComboBox->addItem("Qt", QChart::ChartThemeQt);
152 themeComboBox->addItem("Qt", QChart::ChartThemeQt);
153 return themeComboBox;
153 return themeComboBox;
154 }
154 }
155
155
156 QComboBox *ThemeWidget::createAnimationBox() const
156 QComboBox *ThemeWidget::createAnimationBox() const
157 {
157 {
158 // settings layout
158 // settings layout
159 QComboBox *animationComboBox = new QComboBox();
159 QComboBox *animationComboBox = new QComboBox();
160 animationComboBox->addItem("No Animations", QChart::NoAnimation);
160 animationComboBox->addItem("No Animations", QChart::NoAnimation);
161 animationComboBox->addItem("GridAxis Animations", QChart::GridAxisAnimations);
161 animationComboBox->addItem("GridAxis Animations", QChart::GridAxisAnimations);
162 animationComboBox->addItem("Series Animations", QChart::SeriesAnimations);
162 animationComboBox->addItem("Series Animations", QChart::SeriesAnimations);
163 animationComboBox->addItem("All Animations", QChart::AllAnimations);
163 animationComboBox->addItem("All Animations", QChart::AllAnimations);
164 return animationComboBox;
164 return animationComboBox;
165 }
165 }
166
166
167 QComboBox *ThemeWidget::createLegendBox() const
167 QComboBox *ThemeWidget::createLegendBox() const
168 {
168 {
169 QComboBox *legendComboBox = new QComboBox();
169 QComboBox *legendComboBox = new QComboBox();
170 legendComboBox->addItem("No Legend ", 0);
170 legendComboBox->addItem("No Legend ", 0);
171 legendComboBox->addItem("Legend Top", Qt::AlignTop);
171 legendComboBox->addItem("Legend Top", Qt::AlignTop);
172 legendComboBox->addItem("Legend Bottom", Qt::AlignBottom);
172 legendComboBox->addItem("Legend Bottom", Qt::AlignBottom);
173 legendComboBox->addItem("Legend Left", Qt::AlignLeft);
173 legendComboBox->addItem("Legend Left", Qt::AlignLeft);
174 legendComboBox->addItem("Legend Right", Qt::AlignRight);
174 legendComboBox->addItem("Legend Right", Qt::AlignRight);
175 return legendComboBox;
175 return legendComboBox;
176 }
176 }
177
177
178 QChart *ThemeWidget::createAreaChart() const
178 QChart *ThemeWidget::createAreaChart() const
179 {
179 {
180 QChart *chart = new QChart();
180 QChart *chart = new QChart();
181 chart->setTitle("Area chart");
181 chart->setTitle("Area chart");
182
182
183 // The lower series initialized to zero values
183 // The lower series initialized to zero values
184 QLineSeries *lowerSeries = 0;
184 QLineSeries *lowerSeries = 0;
185 QString name("Series ");
185 QString name("Series ");
186 int nameIndex = 0;
186 int nameIndex = 0;
187 for (int i(0); i < m_dataTable.count(); i++) {
187 for (int i(0); i < m_dataTable.count(); i++) {
188 QLineSeries *upperSeries = new QLineSeries(chart);
188 QLineSeries *upperSeries = new QLineSeries(chart);
189 for (int j(0); j < m_dataTable[i].count(); j++) {
189 for (int j(0); j < m_dataTable[i].count(); j++) {
190 Data data = m_dataTable[i].at(j);
190 Data data = m_dataTable[i].at(j);
191 if (lowerSeries) {
191 if (lowerSeries) {
192 const QList<QPointF>& points = lowerSeries->points();
192 const QVector<QPointF>& points = lowerSeries->pointsVector();
193 upperSeries->append(QPointF(j, points[i].y() + data.first.y()));
193 upperSeries->append(QPointF(j, points[i].y() + data.first.y()));
194 } else {
194 } else {
195 upperSeries->append(QPointF(j, data.first.y()));
195 upperSeries->append(QPointF(j, data.first.y()));
196 }
196 }
197 }
197 }
198 QAreaSeries *area = new QAreaSeries(upperSeries, lowerSeries);
198 QAreaSeries *area = new QAreaSeries(upperSeries, lowerSeries);
199 area->setName(name + QString::number(nameIndex));
199 area->setName(name + QString::number(nameIndex));
200 nameIndex++;
200 nameIndex++;
201 chart->addSeries(area);
201 chart->addSeries(area);
202 chart->createDefaultAxes();
202 chart->createDefaultAxes();
203 lowerSeries = upperSeries;
203 lowerSeries = upperSeries;
204 }
204 }
205
205
206 return chart;
206 return chart;
207 }
207 }
208
208
209 QChart *ThemeWidget::createBarChart(int valueCount) const
209 QChart *ThemeWidget::createBarChart(int valueCount) const
210 {
210 {
211 Q_UNUSED(valueCount);
211 Q_UNUSED(valueCount);
212 QChart *chart = new QChart();
212 QChart *chart = new QChart();
213 chart->setTitle("Bar chart");
213 chart->setTitle("Bar chart");
214
214
215 QStackedBarSeries *series = new QStackedBarSeries(chart);
215 QStackedBarSeries *series = new QStackedBarSeries(chart);
216 for (int i(0); i < m_dataTable.count(); i++) {
216 for (int i(0); i < m_dataTable.count(); i++) {
217 QBarSet *set = new QBarSet("Bar set " + QString::number(i));
217 QBarSet *set = new QBarSet("Bar set " + QString::number(i));
218 foreach (Data data, m_dataTable[i])
218 foreach (Data data, m_dataTable[i])
219 *set << data.first.y();
219 *set << data.first.y();
220 series->append(set);
220 series->append(set);
221 }
221 }
222 chart->addSeries(series);
222 chart->addSeries(series);
223 chart->createDefaultAxes();
223 chart->createDefaultAxes();
224
224
225 return chart;
225 return chart;
226 }
226 }
227
227
228 QChart *ThemeWidget::createLineChart() const
228 QChart *ThemeWidget::createLineChart() const
229 {
229 {
230 QChart *chart = new QChart();
230 QChart *chart = new QChart();
231 chart->setTitle("Line chart");
231 chart->setTitle("Line chart");
232
232
233 QString name("Series ");
233 QString name("Series ");
234 int nameIndex = 0;
234 int nameIndex = 0;
235 foreach (DataList list, m_dataTable) {
235 foreach (DataList list, m_dataTable) {
236 QLineSeries *series = new QLineSeries(chart);
236 QLineSeries *series = new QLineSeries(chart);
237 foreach (Data data, list)
237 foreach (Data data, list)
238 series->append(data.first);
238 series->append(data.first);
239 series->setName(name + QString::number(nameIndex));
239 series->setName(name + QString::number(nameIndex));
240 nameIndex++;
240 nameIndex++;
241 chart->addSeries(series);
241 chart->addSeries(series);
242 }
242 }
243 chart->createDefaultAxes();
243 chart->createDefaultAxes();
244
244
245 return chart;
245 return chart;
246 }
246 }
247
247
248 QChart *ThemeWidget::createPieChart() const
248 QChart *ThemeWidget::createPieChart() const
249 {
249 {
250 QChart *chart = new QChart();
250 QChart *chart = new QChart();
251 chart->setTitle("Pie chart");
251 chart->setTitle("Pie chart");
252
252
253 qreal pieSize = 1.0 / m_dataTable.count();
253 qreal pieSize = 1.0 / m_dataTable.count();
254 for (int i = 0; i < m_dataTable.count(); i++) {
254 for (int i = 0; i < m_dataTable.count(); i++) {
255 QPieSeries *series = new QPieSeries(chart);
255 QPieSeries *series = new QPieSeries(chart);
256 foreach (Data data, m_dataTable[i]) {
256 foreach (Data data, m_dataTable[i]) {
257 QPieSlice *slice = series->append(data.second, data.first.y());
257 QPieSlice *slice = series->append(data.second, data.first.y());
258 if (data == m_dataTable[i].first()) {
258 if (data == m_dataTable[i].first()) {
259 slice->setLabelVisible();
259 slice->setLabelVisible();
260 slice->setExploded();
260 slice->setExploded();
261 }
261 }
262 }
262 }
263 qreal hPos = (pieSize / 2) + (i / (qreal) m_dataTable.count());
263 qreal hPos = (pieSize / 2) + (i / (qreal) m_dataTable.count());
264 series->setPieSize(pieSize);
264 series->setPieSize(pieSize);
265 series->setHorizontalPosition(hPos);
265 series->setHorizontalPosition(hPos);
266 series->setVerticalPosition(0.5);
266 series->setVerticalPosition(0.5);
267 chart->addSeries(series);
267 chart->addSeries(series);
268 }
268 }
269
269
270 return chart;
270 return chart;
271 }
271 }
272
272
273 QChart *ThemeWidget::createSplineChart() const
273 QChart *ThemeWidget::createSplineChart() const
274 {
274 {
275 // spine chart
275 // spine chart
276 QChart *chart = new QChart();
276 QChart *chart = new QChart();
277 chart->setTitle("Spline chart");
277 chart->setTitle("Spline chart");
278 QString name("Series ");
278 QString name("Series ");
279 int nameIndex = 0;
279 int nameIndex = 0;
280 foreach (DataList list, m_dataTable) {
280 foreach (DataList list, m_dataTable) {
281 QSplineSeries *series = new QSplineSeries(chart);
281 QSplineSeries *series = new QSplineSeries(chart);
282 foreach (Data data, list)
282 foreach (Data data, list)
283 series->append(data.first);
283 series->append(data.first);
284 series->setName(name + QString::number(nameIndex));
284 series->setName(name + QString::number(nameIndex));
285 nameIndex++;
285 nameIndex++;
286 chart->addSeries(series);
286 chart->addSeries(series);
287 }
287 }
288 chart->createDefaultAxes();
288 chart->createDefaultAxes();
289 return chart;
289 return chart;
290 }
290 }
291
291
292 QChart *ThemeWidget::createScatterChart() const
292 QChart *ThemeWidget::createScatterChart() const
293 {
293 {
294 // scatter chart
294 // scatter chart
295 QChart *chart = new QChart();
295 QChart *chart = new QChart();
296 chart->setTitle("Scatter chart");
296 chart->setTitle("Scatter chart");
297 QString name("Series ");
297 QString name("Series ");
298 int nameIndex = 0;
298 int nameIndex = 0;
299 foreach (DataList list, m_dataTable) {
299 foreach (DataList list, m_dataTable) {
300 QScatterSeries *series = new QScatterSeries(chart);
300 QScatterSeries *series = new QScatterSeries(chart);
301 foreach (Data data, list)
301 foreach (Data data, list)
302 series->append(data.first);
302 series->append(data.first);
303 series->setName(name + QString::number(nameIndex));
303 series->setName(name + QString::number(nameIndex));
304 nameIndex++;
304 nameIndex++;
305 chart->addSeries(series);
305 chart->addSeries(series);
306 }
306 }
307 chart->createDefaultAxes();
307 chart->createDefaultAxes();
308 return chart;
308 return chart;
309 }
309 }
310
310
311 void ThemeWidget::updateUI()
311 void ThemeWidget::updateUI()
312 {
312 {
313 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
313 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
314
314
315 if (m_charts.at(0)->chart()->theme() != theme) {
315 if (m_charts.at(0)->chart()->theme() != theme) {
316 foreach (QChartView *chartView, m_charts)
316 foreach (QChartView *chartView, m_charts)
317 chartView->chart()->setTheme(theme);
317 chartView->chart()->setTheme(theme);
318
318
319 QPalette pal = window()->palette();
319 QPalette pal = window()->palette();
320 if (theme == QChart::ChartThemeLight) {
320 if (theme == QChart::ChartThemeLight) {
321 pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
321 pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
322 pal.setColor(QPalette::WindowText, QRgb(0x404044));
322 pal.setColor(QPalette::WindowText, QRgb(0x404044));
323 } else if (theme == QChart::ChartThemeDark) {
323 } else if (theme == QChart::ChartThemeDark) {
324 pal.setColor(QPalette::Window, QRgb(0x121218));
324 pal.setColor(QPalette::Window, QRgb(0x121218));
325 pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
325 pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
326 } else if (theme == QChart::ChartThemeBlueCerulean) {
326 } else if (theme == QChart::ChartThemeBlueCerulean) {
327 pal.setColor(QPalette::Window, QRgb(0x40434a));
327 pal.setColor(QPalette::Window, QRgb(0x40434a));
328 pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
328 pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
329 } else if (theme == QChart::ChartThemeBrownSand) {
329 } else if (theme == QChart::ChartThemeBrownSand) {
330 pal.setColor(QPalette::Window, QRgb(0x9e8965));
330 pal.setColor(QPalette::Window, QRgb(0x9e8965));
331 pal.setColor(QPalette::WindowText, QRgb(0x404044));
331 pal.setColor(QPalette::WindowText, QRgb(0x404044));
332 } else if (theme == QChart::ChartThemeBlueNcs) {
332 } else if (theme == QChart::ChartThemeBlueNcs) {
333 pal.setColor(QPalette::Window, QRgb(0x018bba));
333 pal.setColor(QPalette::Window, QRgb(0x018bba));
334 pal.setColor(QPalette::WindowText, QRgb(0x404044));
334 pal.setColor(QPalette::WindowText, QRgb(0x404044));
335 } else if (theme == QChart::ChartThemeHighContrast) {
335 } else if (theme == QChart::ChartThemeHighContrast) {
336 pal.setColor(QPalette::Window, QRgb(0xffab03));
336 pal.setColor(QPalette::Window, QRgb(0xffab03));
337 pal.setColor(QPalette::WindowText, QRgb(0x181818));
337 pal.setColor(QPalette::WindowText, QRgb(0x181818));
338 } else if (theme == QChart::ChartThemeBlueIcy) {
338 } else if (theme == QChart::ChartThemeBlueIcy) {
339 pal.setColor(QPalette::Window, QRgb(0xcee7f0));
339 pal.setColor(QPalette::Window, QRgb(0xcee7f0));
340 pal.setColor(QPalette::WindowText, QRgb(0x404044));
340 pal.setColor(QPalette::WindowText, QRgb(0x404044));
341 } else {
341 } else {
342 pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
342 pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
343 pal.setColor(QPalette::WindowText, QRgb(0x404044));
343 pal.setColor(QPalette::WindowText, QRgb(0x404044));
344 }
344 }
345 window()->setPalette(pal);
345 window()->setPalette(pal);
346 }
346 }
347
347
348 bool checked = m_antialiasCheckBox->isChecked();
348 bool checked = m_antialiasCheckBox->isChecked();
349 foreach (QChartView *chart, m_charts)
349 foreach (QChartView *chart, m_charts)
350 chart->setRenderHint(QPainter::Antialiasing, checked);
350 chart->setRenderHint(QPainter::Antialiasing, checked);
351
351
352 QChart::AnimationOptions options(m_animatedComboBox->itemData(m_animatedComboBox->currentIndex()).toInt());
352 QChart::AnimationOptions options(m_animatedComboBox->itemData(m_animatedComboBox->currentIndex()).toInt());
353 if (m_charts.at(0)->chart()->animationOptions() != options) {
353 if (m_charts.at(0)->chart()->animationOptions() != options) {
354 foreach (QChartView *chartView, m_charts)
354 foreach (QChartView *chartView, m_charts)
355 chartView->chart()->setAnimationOptions(options);
355 chartView->chart()->setAnimationOptions(options);
356 }
356 }
357
357
358 Qt::Alignment alignment(m_legendComboBox->itemData(m_legendComboBox->currentIndex()).toInt());
358 Qt::Alignment alignment(m_legendComboBox->itemData(m_legendComboBox->currentIndex()).toInt());
359
359
360 if (!alignment) {
360 if (!alignment) {
361 foreach (QChartView *chartView, m_charts)
361 foreach (QChartView *chartView, m_charts)
362 chartView->chart()->legend()->hide();
362 chartView->chart()->legend()->hide();
363 } else {
363 } else {
364 foreach (QChartView *chartView, m_charts) {
364 foreach (QChartView *chartView, m_charts) {
365 chartView->chart()->legend()->setAlignment(alignment);
365 chartView->chart()->legend()->setAlignment(alignment);
366 chartView->chart()->legend()->show();
366 chartView->chart()->legend()->show();
367 }
367 }
368 }
368 }
369 }
369 }
370
370
@@ -1,86 +1,96
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 import QtQuick 2.0
19 import QtQuick 2.1
20 import QtQuick.Layouts 1.0
20 import QtQuick.Layouts 1.0
21
21
22 ColumnLayout {
22 ColumnLayout {
23 property alias openGLButton: openGLButton
23 spacing: 8
24 spacing: 8
24 Layout.fillHeight: true
25 Layout.fillHeight: true
25 signal animationsEnabled(bool enabled)
26 signal animationsEnabled(bool enabled)
26 signal seriesTypeChanged(string type)
27 signal seriesTypeChanged(string type)
27 signal refreshRateChanged(variant rate);
28 signal refreshRateChanged(variant rate);
28 signal signalSourceChanged(string source, int signalCount, int sampleCount);
29 signal signalSourceChanged(string source, int signalCount, int sampleCount);
29 signal antialiasingEnabled(bool enabled)
30 signal antialiasingEnabled(bool enabled)
31 signal openGlChanged(bool enabled)
30
32
31 Text {
33 Text {
32 text: "Scope"
34 text: "Scope"
33 font.pointSize: 18
35 font.pointSize: 18
34 color: "white"
36 color: "white"
35 }
37 }
36
38
37 MultiButton {
39 MultiButton {
40 id: openGLButton
41 text: "OpenGL: "
42 items: ["false", "true"]
43 currentSelection: 0
44 onSelectionChanged: openGlChanged(currentSelection == 1);
45 }
46
47 MultiButton {
38 text: "Graph: "
48 text: "Graph: "
39 items: ["line", "spline", "scatter"]
49 items: ["line", "spline", "scatter"]
40 currentSelection: 0
50 currentSelection: 0
41 onSelectionChanged: seriesTypeChanged(items[currentSelection]);
51 onSelectionChanged: seriesTypeChanged(items[currentSelection]);
42 }
52 }
43
53
44 MultiButton {
54 MultiButton {
45 id: signalSourceButton
55 id: signalSourceButton
46 text: "Source: "
56 text: "Source: "
47 items: ["sin", "linear"]
57 items: ["sin", "linear"]
48 currentSelection: 0
58 currentSelection: 0
49 onSelectionChanged: signalSourceChanged(
59 onSelectionChanged: signalSourceChanged(
50 selection,
60 selection,
51 5,
61 5,
52 sampleCountButton.items[sampleCountButton.currentSelection]);
62 sampleCountButton.items[sampleCountButton.currentSelection]);
53 }
63 }
54
64
55 MultiButton {
65 MultiButton {
56 id: sampleCountButton
66 id: sampleCountButton
57 text: "Samples: "
67 text: "Samples: "
58 items: [6, 128, 1024, 10000]
68 items: [6, 128, 1024, 10000]
59 currentSelection: 2
69 currentSelection: 2
60 onSelectionChanged: signalSourceChanged(
70 onSelectionChanged: signalSourceChanged(
61 signalSourceButton.items[signalSourceButton.currentSelection],
71 signalSourceButton.items[signalSourceButton.currentSelection],
62 5,
72 5,
63 selection);
73 selection);
64 }
74 }
65
75
66 MultiButton {
76 MultiButton {
67 text: "Refresh rate: "
77 text: "Refresh rate: "
68 items: [1, 24, 60, 100]
78 items: [1, 24, 60, 100]
69 currentSelection: 2
79 currentSelection: 2
70 onSelectionChanged: refreshRateChanged(items[currentSelection]);
80 onSelectionChanged: refreshRateChanged(items[currentSelection]);
71 }
81 }
72
82
73 MultiButton {
83 MultiButton {
74 text: "Animations: "
84 text: "Animations: "
75 items: ["OFF", "ON"]
85 items: ["OFF", "ON"]
76 currentSelection: 0
86 currentSelection: 0
77 onSelectionChanged: animationsEnabled(currentSelection == 1);
87 onSelectionChanged: animationsEnabled(currentSelection == 1);
78 }
88 }
79
89
80 MultiButton {
90 MultiButton {
81 text: "Antialias: "
91 text: "Antialias: "
82 items: ["OFF", "ON"]
92 items: ["OFF", "ON"]
83 currentSelection: 0
93 currentSelection: 0
84 onSelectionChanged: antialiasingEnabled(currentSelection == 1);
94 onSelectionChanged: antialiasingEnabled(currentSelection == 1);
85 }
95 }
86 }
96 }
@@ -1,113 +1,130
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 import QtQuick 2.0
19 import QtQuick 2.0
20 import QtCharts 2.0
20 import QtCharts 2.1
21
21
22 //![1]
22 //![1]
23 ChartView {
23 ChartView {
24 id: chartView
24 id: chartView
25 animationOptions: ChartView.NoAnimation
25 animationOptions: ChartView.NoAnimation
26 theme: ChartView.ChartThemeDark
26 theme: ChartView.ChartThemeDark
27 property bool openGL: false
28 onOpenGLChanged: {
29 series("signal 1").useOpenGL = openGL;
30 series("signal 2").useOpenGL = openGL;
31 }
27
32
28 ValueAxis {
33 ValueAxis {
29 id: axisY1
34 id: axisY1
30 min: -1
35 min: -1
31 max: 4
36 max: 4
32 }
37 }
33
38
34 ValueAxis {
39 ValueAxis {
35 id: axisY2
40 id: axisY2
36 min: -10
41 min: -10
37 max: 5
42 max: 5
38 }
43 }
39
44
40 ValueAxis {
45 ValueAxis {
41 id: axisX
46 id: axisX
42 min: 0
47 min: 0
43 max: 1000
48 max: 1024
44 }
49 }
45
50
46 LineSeries {
51 LineSeries {
47 id: lineSeries1
52 id: lineSeries1
48 name: "signal 1"
53 name: "signal 1"
49 axisX: axisX
54 axisX: axisX
50 axisY: axisY1
55 axisY: axisY1
56 useOpenGL: chartView.openGL
51 }
57 }
52 LineSeries {
58 LineSeries {
53 id: lineSeries2
59 id: lineSeries2
54 name: "signal 2"
60 name: "signal 2"
55 axisX: axisX
61 axisX: axisX
56 axisYRight: axisY2
62 axisYRight: axisY2
63 useOpenGL: chartView.openGL
57 }
64 }
58 //![1]
65 //![1]
59
66
60 //![2]
67 //![2]
61 Timer {
68 Timer {
62 id: refreshTimer
69 id: refreshTimer
63 interval: 1 / 60 * 1000 // 60 Hz
70 interval: 1 / 60 * 1000 // 60 Hz
64 running: true
71 running: true
65 repeat: true
72 repeat: true
66 onTriggered: {
73 onTriggered: {
67 dataSource.update(chartView.series(0));
74 dataSource.update(chartView.series(0));
68 dataSource.update(chartView.series(1));
75 dataSource.update(chartView.series(1));
69 }
76 }
70 }
77 }
71 //![2]
78 //![2]
72
79
73 //![3]
80 //![3]
74 function changeSeriesType(type) {
81 function changeSeriesType(type) {
75 chartView.removeAllSeries();
82 chartView.removeAllSeries();
76
83
77 // Create two new series of the correct type. Axis x is the same for both of the series,
84 // Create two new series of the correct type. Axis x is the same for both of the series,
78 // but the series have their own y-axes to make it possible to control the y-offset
85 // but the series have their own y-axes to make it possible to control the y-offset
79 // of the "signal sources".
86 // of the "signal sources".
80 if (type == "line") {
87 if (type == "line") {
81 chartView.createSeries(ChartView.SeriesTypeLine, "signal 1", axisX, axisY1);
88 var series1 = chartView.createSeries(ChartView.SeriesTypeLine, "signal 1",
82 chartView.createSeries(ChartView.SeriesTypeLine, "signal 2", axisX, axisY2);
89 axisX, axisY1);
90 series1.useOpenGL = chartView.openGL
91
92 var series2 = chartView.createSeries(ChartView.SeriesTypeLine, "signal 2",
93 axisX, axisY2);
94 series2.useOpenGL = chartView.openGL
83 } else if (type == "spline") {
95 } else if (type == "spline") {
84 chartView.createSeries(ChartView.SeriesTypeSpline, "signal 1", axisX, axisY1);
96 chartView.createSeries(ChartView.SeriesTypeSpline, "signal 1", axisX, axisY1);
85 chartView.createSeries(ChartView.SeriesTypeSpline, "signal 2", axisX, axisY2);
97 chartView.createSeries(ChartView.SeriesTypeSpline, "signal 2", axisX, axisY2);
86 } else {
98 } else {
87 var series1 = chartView.createSeries(ChartView.SeriesTypeScatter, "signal 1", axisX, axisY1);
99 var series1 = chartView.createSeries(ChartView.SeriesTypeScatter, "signal 1",
100 axisX, axisY1);
88 series1.markerSize = 3;
101 series1.markerSize = 3;
89 series1.borderColor = "transparent";
102 series1.borderColor = "transparent";
90 var series2 = chartView.createSeries(ChartView.SeriesTypeScatter, "signal 2", axisX, axisY2);
103 series1.useOpenGL = chartView.openGL
104
105 var series2 = chartView.createSeries(ChartView.SeriesTypeScatter, "signal 2",
106 axisX, axisY2);
91 series2.markerSize = 3;
107 series2.markerSize = 3;
92 series2.borderColor = "transparent";
108 series2.borderColor = "transparent";
109 series2.useOpenGL = chartView.openGL
93 }
110 }
94 }
111 }
95
112
96 function createAxis(min, max) {
113 function createAxis(min, max) {
97 // The following creates a ValueAxis object that can be then set as a x or y axis for a series
114 // The following creates a ValueAxis object that can be then set as a x or y axis for a series
98 return Qt.createQmlObject("import QtQuick 2.0; import QtCharts 2.0; ValueAxis { min: "
115 return Qt.createQmlObject("import QtQuick 2.0; import QtCharts 2.0; ValueAxis { min: "
99 + min + "; max: " + max + " }", chartView);
116 + min + "; max: " + max + " }", chartView);
100 }
117 }
101 //![3]
118 //![3]
102
119
103 function setAnimations(enabled) {
120 function setAnimations(enabled) {
104 if (enabled)
121 if (enabled)
105 chartView.animationOptions = ChartView.SeriesAnimations;
122 chartView.animationOptions = ChartView.SeriesAnimations;
106 else
123 else
107 chartView.animationOptions = ChartView.NoAnimation;
124 chartView.animationOptions = ChartView.NoAnimation;
108 }
125 }
109
126
110 function changeRefreshRate(rate) {
127 function changeRefreshRate(rate) {
111 refreshTimer.interval = 1 / Number(rate) * 1000;
128 refreshTimer.interval = 1 / Number(rate) * 1000;
112 }
129 }
113 }
130 }
@@ -1,59 +1,71
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 import QtQuick 2.0
19 import QtQuick 2.0
20
20
21 //![1]
21 //![1]
22 Rectangle {
22 Rectangle {
23 id: main
23 id: main
24 width: 400
24 width: 600
25 height: 300
25 height: 400
26 color: "#404040"
26 color: "#404040"
27
27
28 ControlPanel {
28 ControlPanel {
29 id: controlPanel
29 id: controlPanel
30 anchors.top: parent.top
30 anchors.top: parent.top
31 anchors.topMargin: 10
31 anchors.topMargin: 10
32 anchors.bottom: parent.bottom
32 anchors.bottom: parent.bottom
33 anchors.left: parent.left
33 anchors.left: parent.left
34 anchors.leftMargin: 10
34 anchors.leftMargin: 10
35 //![1]
35 //![1]
36
36
37 onSignalSourceChanged: {
37 onSignalSourceChanged: {
38 if (source == "sin")
38 if (source == "sin")
39 dataSource.generateData(0, signalCount, sampleCount);
39 dataSource.generateData(0, signalCount, sampleCount);
40 else
40 else
41 dataSource.generateData(1, signalCount, sampleCount);
41 dataSource.generateData(1, signalCount, sampleCount);
42 scopeView.axisX().max = sampleCount;
42 }
43 }
43 onAnimationsEnabled: scopeView.setAnimations(enabled);
44 onAnimationsEnabled: scopeView.setAnimations(enabled);
44 onSeriesTypeChanged: scopeView.changeSeriesType(type);
45 onSeriesTypeChanged: {
46 scopeView.changeSeriesType(type);
47 if (type === "spline") {
48 controlPanel.openGLButton.currentSelection = 0;
49 controlPanel.openGLButton.enabled = false;
50 scopeView.openGL = false;
51 } else {
52 controlPanel.openGLButton.enabled = true;
53 }
54 }
45 onRefreshRateChanged: scopeView.changeRefreshRate(rate);
55 onRefreshRateChanged: scopeView.changeRefreshRate(rate);
46 onAntialiasingEnabled: scopeView.antialiasing = enabled;
56 onAntialiasingEnabled: scopeView.antialiasing = enabled;
57 onOpenGlChanged: scopeView.openGL = enabled;
47 }
58 }
48
59
49 //![2]
60 //![2]
50 ScopeView {
61 ScopeView {
51 id: scopeView
62 id: scopeView
52 anchors.top: parent.top
63 anchors.top: parent.top
53 anchors.bottom: parent.bottom
64 anchors.bottom: parent.bottom
54 anchors.right: parent.right
65 anchors.right: parent.right
55 anchors.left: controlPanel.right
66 anchors.left: controlPanel.right
56 height: main.height
67 height: main.height
57 }
68 }
58 //![2]
69 //![2]
70
59 }
71 }
@@ -1,742 +1,744
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <QtCharts/QAreaSeries>
19 #include <QtCharts/QAreaSeries>
20 #include <private/qareaseries_p.h>
20 #include <private/qareaseries_p.h>
21 #include <QtCharts/QLineSeries>
21 #include <QtCharts/QLineSeries>
22 #include <private/areachartitem_p.h>
22 #include <private/areachartitem_p.h>
23 #include <private/abstractdomain_p.h>
23 #include <private/abstractdomain_p.h>
24 #include <private/chartdataset_p.h>
24 #include <private/chartdataset_p.h>
25 #include <private/charttheme_p.h>
25 #include <private/charttheme_p.h>
26 #include <QtCharts/QValueAxis>
26 #include <QtCharts/QValueAxis>
27 #include <QtCharts/QAreaLegendMarker>
27 #include <QtCharts/QAreaLegendMarker>
28 #include <private/qchart_p.h>
28 #include <private/qchart_p.h>
29
29
30 QT_CHARTS_BEGIN_NAMESPACE
30 QT_CHARTS_BEGIN_NAMESPACE
31
31
32 /*!
32 /*!
33 \class QAreaSeries
33 \class QAreaSeries
34 \inmodule Qt Charts
34 \inmodule Qt Charts
35 \brief The QAreaSeries class is used for making area charts.
35 \brief The QAreaSeries class is used for making area charts.
36
36
37 An area series is used to show quantitative data. It is based on line series, in the way that
37 An area series is used to show quantitative data. It is based on line series, in the way that
38 the area between the boundary lines is emphasized with color. Since the area series is based on
38 the area between the boundary lines is emphasized with color. Since the area series is based on
39 line series, QAreaSeries constructor needs a QLineSeries instance, which defines "upper"
39 line series, QAreaSeries constructor needs a QLineSeries instance, which defines "upper"
40 boundary of the area. The area chart is drawn using the bottom of the plot area as the "lower"
40 boundary of the area. The area chart is drawn using the bottom of the plot area as the "lower"
41 boundary by default. Instead of the bottom of the plot area, the "lower" boundary can be
41 boundary by default. Instead of the bottom of the plot area, the "lower" boundary can be
42 specified by another line. In that case QAreaSeries should be initialized with two QLineSeries
42 specified by another line. In that case QAreaSeries should be initialized with two QLineSeries
43 instances. Please note that the terms "upper" and "lower" boundary can be misleading in cases
43 instances. Please note that the terms "upper" and "lower" boundary can be misleading in cases
44 where the "lower" boundary has bigger values than the "upper" one. The main point is that the
44 where the "lower" boundary has bigger values than the "upper" one. The main point is that the
45 area between these two boundary lines will be filled.
45 area between these two boundary lines will be filled.
46
46
47 See the \l {AreaChart Example} {area chart example} to learn how to create a simple area chart.
47 See the \l {AreaChart Example} {area chart example} to learn how to create a simple area chart.
48 \image examples_areachart.png
48 \image examples_areachart.png
49 */
49 */
50
50
51 /*!
51 /*!
52 \qmltype AreaSeries
52 \qmltype AreaSeries
53 \instantiates QAreaSeries
53 \instantiates QAreaSeries
54 \inqmlmodule QtCharts
54 \inqmlmodule QtCharts
55
55
56 \inherits AbstractSeries
56 \inherits AbstractSeries
57
57
58 \brief The AreaSeries type is used for making area charts.
58 \brief The AreaSeries type is used for making area charts.
59
59
60 The following QML shows how to create a simple area chart:
60 The following QML shows how to create a simple area chart:
61 \snippet qmlchart/qml/qmlchart/View4.qml 1
61 \snippet qmlchart/qml/qmlchart/View4.qml 1
62 \beginfloatleft
62 \beginfloatleft
63 \image examples_qmlchart4.png
63 \image examples_qmlchart4.png
64 \endfloat
64 \endfloat
65 \clearfloat
65 \clearfloat
66
66
67 \note Adding the same line series to chart and area series is not supported. The series used as
67 \note Adding the same line series to chart and area series is not supported. The series used as
68 boundary lines should be defined only for the area series.
68 boundary lines should be defined only for the area series.
69 */
69 */
70
70
71 /*!
71 /*!
72 \property QAreaSeries::upperSeries
72 \property QAreaSeries::upperSeries
73 \brief The upper one of the two line series used to define area series boundaries.
73 \brief The upper one of the two line series used to define area series boundaries.
74 */
74 */
75 /*!
75 /*!
76 \qmlproperty LineSeries AreaSeries::upperSeries
76 \qmlproperty LineSeries AreaSeries::upperSeries
77 The upper one of the two line series used to define area series boundaries.
77 The upper one of the two line series used to define area series boundaries.
78 */
78 */
79
79
80 /*!
80 /*!
81 \property QAreaSeries::lowerSeries
81 \property QAreaSeries::lowerSeries
82 The lower one of the two line series used to define are series boundaries. Note if
82 The lower one of the two line series used to define are series boundaries. Note if
83 QAreaSeries was constructed without a\ lowerSeries this is null.
83 QAreaSeries was constructed without a\ lowerSeries this is null.
84 */
84 */
85 /*!
85 /*!
86 \qmlproperty LineSeries AreaSeries::lowerSeries
86 \qmlproperty LineSeries AreaSeries::lowerSeries
87 The lower one of the two line series used to define are series boundaries. Note if
87 The lower one of the two line series used to define are series boundaries. Note if
88 AreaSeries was constructed without a\ lowerSeries this is null.
88 AreaSeries was constructed without a\ lowerSeries this is null.
89 */
89 */
90
90
91 /*!
91 /*!
92 \property QAreaSeries::color
92 \property QAreaSeries::color
93 Fill (brush) color of the series. This is a convenience property for modifying the color of brush.
93 Fill (brush) color of the series. This is a convenience property for modifying the color of brush.
94 \sa QAreaSeries::brush()
94 \sa QAreaSeries::brush()
95 */
95 */
96 /*!
96 /*!
97 \qmlproperty color AreaSeries::color
97 \qmlproperty color AreaSeries::color
98 Fill (brush) color of the series.
98 Fill (brush) color of the series.
99 */
99 */
100
100
101 /*!
101 /*!
102 \property QAreaSeries::borderColor
102 \property QAreaSeries::borderColor
103 Line (pen) color of the series. This is a convenience property for modifying the color of pen.
103 Line (pen) color of the series. This is a convenience property for modifying the color of pen.
104 \sa QAreaSeries::pen()
104 \sa QAreaSeries::pen()
105 */
105 */
106 /*!
106 /*!
107 \qmlproperty color AreaSeries::borderColor
107 \qmlproperty color AreaSeries::borderColor
108 Line (pen) color of the series.
108 Line (pen) color of the series.
109 */
109 */
110
110
111 /*!
111 /*!
112 \qmlproperty real AreaSeries::borderWidth
112 \qmlproperty real AreaSeries::borderWidth
113 The width of the border line. By default the width is 2.0.
113 The width of the border line. By default the width is 2.0.
114 */
114 */
115
115
116 /*!
116 /*!
117 \fn QPen QAreaSeries::pen() const
117 \fn QPen QAreaSeries::pen() const
118 \brief Returns the pen used to draw line for this series.
118 \brief Returns the pen used to draw line for this series.
119 \sa setPen()
119 \sa setPen()
120 */
120 */
121
121
122 /*!
122 /*!
123 \fn QPen QAreaSeries::brush() const
123 \fn QPen QAreaSeries::brush() const
124 \brief Returns the brush used to draw line for this series.
124 \brief Returns the brush used to draw line for this series.
125 \sa setBrush()
125 \sa setBrush()
126 */
126 */
127
127
128 /*!
128 /*!
129 \qmlproperty QString AreaSeries::brushFilename
129 \qmlproperty QString AreaSeries::brushFilename
130 The name of the file used as a brush image for the series.
130 The name of the file used as a brush image for the series.
131 */
131 */
132
132
133 /*!
133 /*!
134 \fn void QAreaSeries::colorChanged(QColor color)
134 \fn void QAreaSeries::colorChanged(QColor color)
135 \brief Signal is emitted when the fill (brush) color has changed to \a color.
135 \brief Signal is emitted when the fill (brush) color has changed to \a color.
136 */
136 */
137 /*!
137 /*!
138 \qmlsignal AreaSeries::onColorChanged(color color)
138 \qmlsignal AreaSeries::onColorChanged(color color)
139 Signal is emitted when the fill (brush) color has changed to \a color.
139 Signal is emitted when the fill (brush) color has changed to \a color.
140 */
140 */
141
141
142 /*!
142 /*!
143 \fn void QAreaSeries::borderColorChanged(QColor color)
143 \fn void QAreaSeries::borderColorChanged(QColor color)
144 \brief Signal is emitted when the line (pen) color has changed to \a color.
144 \brief Signal is emitted when the line (pen) color has changed to \a color.
145 */
145 */
146 /*!
146 /*!
147 \qmlsignal AreaSeries::onBorderColorChanged(color color)
147 \qmlsignal AreaSeries::onBorderColorChanged(color color)
148 Signal is emitted when the line (pen) color has changed to \a color.
148 Signal is emitted when the line (pen) color has changed to \a color.
149 */
149 */
150
150
151 /*!
151 /*!
152 \fn void QAreaSeries::clicked(const QPointF& point)
152 \fn void QAreaSeries::clicked(const QPointF& point)
153 \brief Signal is emitted when user clicks the \a point on area chart. The \a point is the point
153 \brief Signal is emitted when user clicks the \a point on area chart. The \a point is the point
154 where the press was triggered.
154 where the press was triggered.
155 \sa pressed, released, doubleClicked
155 \sa pressed, released, doubleClicked
156 */
156 */
157 /*!
157 /*!
158 \qmlsignal AreaSeries::onClicked(QPointF point)
158 \qmlsignal AreaSeries::onClicked(QPointF point)
159 Signal is emitted when user clicks the \a point on area chart. The \a point is the point where
159 Signal is emitted when user clicks the \a point on area chart. The \a point is the point where
160 the press was triggered.
160 the press was triggered.
161 \sa onPressed, onReleased, onDoubleClicked
161 \sa onPressed, onReleased, onDoubleClicked
162 */
162 */
163
163
164 /*!
164 /*!
165 \fn void QAreaSeries::hovered(const QPointF &point, bool state)
165 \fn void QAreaSeries::hovered(const QPointF &point, bool state)
166 This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
166 This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
167 of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
167 of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
168 the series.
168 the series.
169 */
169 */
170 /*!
170 /*!
171 \qmlsignal AreaSeries::onHovered(point point, bool state)
171 \qmlsignal AreaSeries::onHovered(point point, bool state)
172 This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
172 This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
173 of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
173 of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
174 the series.
174 the series.
175 */
175 */
176
176
177 /*!
177 /*!
178 \fn void QAreaSeries::pressed(const QPointF& point)
178 \fn void QAreaSeries::pressed(const QPointF& point)
179 \brief Signal is emitted when user presses the \a point on area chart.
179 \brief Signal is emitted when user presses the \a point on area chart.
180 \sa clicked, released, doubleClicked
180 \sa clicked, released, doubleClicked
181 */
181 */
182 /*!
182 /*!
183 \qmlsignal AreaSeries::onPressed(QPointF point)
183 \qmlsignal AreaSeries::onPressed(QPointF point)
184 Signal is emitted when user presses the \a point on area chart.
184 Signal is emitted when user presses the \a point on area chart.
185 \sa onClicked, onReleased, onDoubleClicked
185 \sa onClicked, onReleased, onDoubleClicked
186 */
186 */
187
187
188 /*!
188 /*!
189 \fn void QAreaSeries::released(const QPointF& point)
189 \fn void QAreaSeries::released(const QPointF& point)
190 \brief Signal is emitted when user releases a press that was triggered on a \a point on area
190 \brief Signal is emitted when user releases a press that was triggered on a \a point on area
191 chart.
191 chart.
192 \sa pressed, clicked, doubleClicked
192 \sa pressed, clicked, doubleClicked
193 */
193 */
194 /*!
194 /*!
195 \qmlsignal AreaSeries::onReleased(QPointF point)
195 \qmlsignal AreaSeries::onReleased(QPointF point)
196 Signal is emitted when user releases a press that was triggered on a \a point on area chart.
196 Signal is emitted when user releases a press that was triggered on a \a point on area chart.
197 \sa onPressed, onClicked, onDoubleClicked
197 \sa onPressed, onClicked, onDoubleClicked
198 */
198 */
199
199
200 /*!
200 /*!
201 \fn void QAreaSeries::doubleClicked(const QPointF& point)
201 \fn void QAreaSeries::doubleClicked(const QPointF& point)
202 \brief Signal is emitted when user doubleclicks the \a point on area chart. The \a point is the
202 \brief Signal is emitted when user doubleclicks the \a point on area chart. The \a point is the
203 point where the first press was triggered.
203 point where the first press was triggered.
204 \sa pressed, released, clicked
204 \sa pressed, released, clicked
205 */
205 */
206 /*!
206 /*!
207 \qmlsignal AreaSeries::onDoubleClicked(QPointF point)
207 \qmlsignal AreaSeries::onDoubleClicked(QPointF point)
208 Signal is emitted when user doubleclicks the \a point on area chart. The \a point is the point
208 Signal is emitted when user doubleclicks the \a point on area chart. The \a point is the point
209 where the first press was triggered.
209 where the first press was triggered.
210 \sa onPressed, onReleased, onClicked
210 \sa onPressed, onReleased, onClicked
211 */
211 */
212
212
213 /*!
213 /*!
214 \fn void QAreaSeries::selected()
214 \fn void QAreaSeries::selected()
215 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
215 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
216 implemented by the user of QAreaSeries API.
216 implemented by the user of QAreaSeries API.
217 */
217 */
218 /*!
218 /*!
219 \qmlsignal AreaSeries::onSelected()
219 \qmlsignal AreaSeries::onSelected()
220 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
220 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
221 implemented by the user of AreaSeries API.
221 implemented by the user of AreaSeries API.
222 */
222 */
223
223
224 /*!
224 /*!
225 \fn void QAreaSeriesPrivate::updated()
225 \fn void QAreaSeriesPrivate::updated()
226 \brief \internal
226 \brief \internal
227 */
227 */
228
228
229 /*!
229 /*!
230 \property QAreaSeries::pointLabelsFormat
230 \property QAreaSeries::pointLabelsFormat
231 The \a format used for showing labels with series points.
231 The \a format used for showing labels with series points.
232
232
233 QAreaSeries supports the following format tags:
233 QAreaSeries supports the following format tags:
234 \table
234 \table
235 \row
235 \row
236 \li @xPoint \li The x value of the data point
236 \li @xPoint \li The x value of the data point
237 \row
237 \row
238 \li @yPoint \li The y value of the data point
238 \li @yPoint \li The y value of the data point
239 \endtable
239 \endtable
240
240
241 For example, the following usage of the format tags would produce labels that have the data
241 For example, the following usage of the format tags would produce labels that have the data
242 point (x, y) shown inside brackets separated by a comma:
242 point (x, y) shown inside brackets separated by a comma:
243 \code
243 \code
244 series->setPointLabelsFormat("(@xPoint, @yPoint)");
244 series->setPointLabelsFormat("(@xPoint, @yPoint)");
245 \endcode
245 \endcode
246
246
247 By default, the labels format is set to '@xPoint, @yPoint'. The labels are shown on the plot
247 By default, the labels format is set to '@xPoint, @yPoint'. The labels are shown on the plot
248 area, labels on the edge of the plot area are cut. If the points are close to each other the
248 area, labels on the edge of the plot area are cut. If the points are close to each other the
249 labels may overlap.
249 labels may overlap.
250
250
251 \sa QAreaSeries::pointLabelsVisible, QAreaSeries::pointLabelsFont, QAreaSeries::pointLabelsColor
251 \sa QAreaSeries::pointLabelsVisible, QAreaSeries::pointLabelsFont, QAreaSeries::pointLabelsColor
252 */
252 */
253 /*!
253 /*!
254 \qmlproperty string AreaSeries::pointLabelsFormat
254 \qmlproperty string AreaSeries::pointLabelsFormat
255 The \a format used for showing labels with series points.
255 The \a format used for showing labels with series points.
256
256
257 \sa QAreaSeries::pointLabelsFormat, pointLabelsVisible, pointLabelsFont, pointLabelsColor
257 \sa QAreaSeries::pointLabelsFormat, pointLabelsVisible, pointLabelsFont, pointLabelsColor
258 */
258 */
259 /*!
259 /*!
260 \fn void QAreaSeries::pointLabelsFormatChanged(const QString &format)
260 \fn void QAreaSeries::pointLabelsFormatChanged(const QString &format)
261 Signal is emitted when the \a format of data point labels is changed.
261 Signal is emitted when the \a format of data point labels is changed.
262 */
262 */
263 /*!
263 /*!
264 \qmlsignal AreaSeries::onPointLabelsFormatChanged(string format)
264 \qmlsignal AreaSeries::onPointLabelsFormatChanged(string format)
265 Signal is emitted when the \a format of data point labels is changed.
265 Signal is emitted when the \a format of data point labels is changed.
266 */
266 */
267
267
268 /*!
268 /*!
269 \property QAreaSeries::pointLabelsVisible
269 \property QAreaSeries::pointLabelsVisible
270 Defines the visibility for data point labels. False by default.
270 Defines the visibility for data point labels. False by default.
271
271
272 \sa QAreaSeries::pointLabelsFormat, QAreaSeries::pointLabelsClipping
272 \sa QAreaSeries::pointLabelsFormat, QAreaSeries::pointLabelsClipping
273 */
273 */
274 /*!
274 /*!
275 \qmlproperty bool AreaSeries::pointLabelsVisible
275 \qmlproperty bool AreaSeries::pointLabelsVisible
276 Defines the visibility for data point labels.
276 Defines the visibility for data point labels.
277
277
278 \sa pointLabelsFormat, pointLabelsClipping
278 \sa pointLabelsFormat, pointLabelsClipping
279 */
279 */
280 /*!
280 /*!
281 \fn void QAreaSeries::pointLabelsVisibilityChanged(bool visible)
281 \fn void QAreaSeries::pointLabelsVisibilityChanged(bool visible)
282 The visibility of the data point labels is changed to \a visible.
282 The visibility of the data point labels is changed to \a visible.
283 */
283 */
284 /*!
284 /*!
285 \qmlsignal AreaSeries::onPointLabelsVisibilityChanged(bool visible)
285 \qmlsignal AreaSeries::onPointLabelsVisibilityChanged(bool visible)
286 The visibility of the data point labels is changed to \a visible.
286 The visibility of the data point labels is changed to \a visible.
287 */
287 */
288
288
289 /*!
289 /*!
290 \property QAreaSeries::pointLabelsFont
290 \property QAreaSeries::pointLabelsFont
291 Defines the font used for data point labels.
291 Defines the font used for data point labels.
292
292
293 \sa QAreaSeries::pointLabelsFormat
293 \sa QAreaSeries::pointLabelsFormat
294 */
294 */
295 /*!
295 /*!
296 \qmlproperty font AreaSeries::pointLabelsFont
296 \qmlproperty font AreaSeries::pointLabelsFont
297 Defines the font used for data point labels.
297 Defines the font used for data point labels.
298
298
299 \sa pointLabelsFormat
299 \sa pointLabelsFormat
300 */
300 */
301 /*!
301 /*!
302 \fn void QAreaSeries::pointLabelsFontChanged(const QFont &font);
302 \fn void QAreaSeries::pointLabelsFontChanged(const QFont &font);
303 The font used for data point labels is changed to \a font.
303 The font used for data point labels is changed to \a font.
304 */
304 */
305 /*!
305 /*!
306 \qmlsignal AreaSeries::onPointLabelsFontChanged(Font font)
306 \qmlsignal AreaSeries::onPointLabelsFontChanged(Font font)
307 The font used for data point labels is changed to \a font.
307 The font used for data point labels is changed to \a font.
308 */
308 */
309
309
310 /*!
310 /*!
311 \property QAreaSeries::pointLabelsColor
311 \property QAreaSeries::pointLabelsColor
312 Defines the color used for data point labels. By default, the color is the color of the brush
312 Defines the color used for data point labels. By default, the color is the color of the brush
313 defined in theme for labels.
313 defined in theme for labels.
314
314
315 \sa QAreaSeries::pointLabelsFormat
315 \sa QAreaSeries::pointLabelsFormat
316 */
316 */
317 /*!
317 /*!
318 \qmlproperty font AreaSeries::pointLabelsColor
318 \qmlproperty font AreaSeries::pointLabelsColor
319 Defines the color used for data point labels. By default, the color is the color of the brush
319 Defines the color used for data point labels. By default, the color is the color of the brush
320 defined in theme for labels.
320 defined in theme for labels.
321
321
322 \sa pointLabelsFormat
322 \sa pointLabelsFormat
323 */
323 */
324 /*!
324 /*!
325 \fn void QAreaSeries::pointLabelsColorChanged(const QColor &color);
325 \fn void QAreaSeries::pointLabelsColorChanged(const QColor &color);
326 The color used for data point labels is changed to \a color.
326 The color used for data point labels is changed to \a color.
327 */
327 */
328 /*!
328 /*!
329 \qmlsignal AreaSeries::onPointLabelsColorChanged(Color color)
329 \qmlsignal AreaSeries::onPointLabelsColorChanged(Color color)
330 The color used for data point labels is changed to \a color.
330 The color used for data point labels is changed to \a color.
331 */
331 */
332
332
333 /*!
333 /*!
334 \property QAreaSeries::pointLabelsClipping
334 \property QAreaSeries::pointLabelsClipping
335 Defines the clipping for data point labels. True by default. The labels on the edge of the plot
335 Defines the clipping for data point labels. True by default. The labels on the edge of the plot
336 area are cut when clipping is enabled.
336 area are cut when clipping is enabled.
337
337
338 \sa pointLabelsVisible
338 \sa pointLabelsVisible
339 */
339 */
340 /*!
340 /*!
341 \qmlproperty bool AreaSeries::pointLabelsClipping
341 \qmlproperty bool AreaSeries::pointLabelsClipping
342 Defines the clipping for data point labels. True by default. The labels on the edge of the plot
342 Defines the clipping for data point labels. True by default. The labels on the edge of the plot
343 area are cut when clipping is enabled.
343 area are cut when clipping is enabled.
344
344
345 \sa pointLabelsVisible
345 \sa pointLabelsVisible
346 */
346 */
347 /*!
347 /*!
348 \fn void QAreaSeries::pointLabelsClippintChanged(bool clipping)
348 \fn void QAreaSeries::pointLabelsClippingChanged(bool clipping)
349 The clipping of the data point labels is changed to \a clipping.
349 The clipping of the data point labels is changed to \a clipping.
350 */
350 */
351 /*!
351 /*!
352 \qmlsignal AreaSeries::onPointLabelsClippingChanged(bool clipping)
352 \qmlsignal AreaSeries::onPointLabelsClippingChanged(bool clipping)
353 The clipping of the data point labels is changed to \a clipping.
353 The clipping of the data point labels is changed to \a clipping.
354 */
354 */
355
355
356 /*!
356 /*!
357 Constructs area series object which is a child of \a upperSeries. Area will be spanned between \a
357 Constructs area series object which is a child of \a upperSeries. Area will be spanned between \a
358 upperSeries line and \a lowerSeries line. If no \a lowerSeries is passed to constructor, area is specified by axis x (y=0) instead.
358 upperSeries line and \a lowerSeries line. If no \a lowerSeries is passed to constructor, area is specified by axis x (y=0) instead.
359 When series object is added to QChartView or QChart instance ownerships is transferred.
359 When series object is added to QChartView or QChart instance ownerships is transferred.
360 */
360 */
361 QAreaSeries::QAreaSeries(QLineSeries *upperSeries, QLineSeries *lowerSeries)
361 QAreaSeries::QAreaSeries(QLineSeries *upperSeries, QLineSeries *lowerSeries)
362 : QAbstractSeries(*new QAreaSeriesPrivate(upperSeries, lowerSeries, this), upperSeries)
362 : QAbstractSeries(*new QAreaSeriesPrivate(upperSeries, lowerSeries, this), upperSeries)
363 {
363 {
364 }
364 }
365
365
366 /*!
366 /*!
367 Constructs area series object without upper or lower series with \a parent object.
367 Constructs area series object without upper or lower series with \a parent object.
368 */
368 */
369 QAreaSeries::QAreaSeries(QObject *parent)
369 QAreaSeries::QAreaSeries(QObject *parent)
370 : QAbstractSeries(*new QAreaSeriesPrivate(0, 0, this), parent)
370 : QAbstractSeries(*new QAreaSeriesPrivate(0, 0, this), parent)
371 {
371 {
372 }
372 }
373
373
374 /*!
374 /*!
375 Destroys the object.
375 Destroys the object.
376 */
376 */
377 QAreaSeries::~QAreaSeries()
377 QAreaSeries::~QAreaSeries()
378 {
378 {
379 Q_D(QAreaSeries);
379 Q_D(QAreaSeries);
380 if (d->m_chart)
380 if (d->m_chart)
381 d->m_chart->removeSeries(this);
381 d->m_chart->removeSeries(this);
382 }
382 }
383
383
384 /*!
384 /*!
385 Returns QAbstractSeries::SeriesTypeArea.
385 Returns QAbstractSeries::SeriesTypeArea.
386 */
386 */
387 QAbstractSeries::SeriesType QAreaSeries::type() const
387 QAbstractSeries::SeriesType QAreaSeries::type() const
388 {
388 {
389 return QAbstractSeries::SeriesTypeArea;
389 return QAbstractSeries::SeriesTypeArea;
390 }
390 }
391
391
392 /*!
392 /*!
393 Sets the \a series that is to be used as the area chart upper series.
393 Sets the \a series that is to be used as the area chart upper series.
394 */
394 */
395 void QAreaSeries::setUpperSeries(QLineSeries *series)
395 void QAreaSeries::setUpperSeries(QLineSeries *series)
396 {
396 {
397 Q_D(QAreaSeries);
397 Q_D(QAreaSeries);
398 if (d->m_upperSeries != series)
398 if (d->m_upperSeries != series) {
399 series->d_ptr->setBlockOpenGL(true);
399 d->m_upperSeries = series;
400 d->m_upperSeries = series;
401 }
400 }
402 }
401
403
402 QLineSeries *QAreaSeries::upperSeries() const
404 QLineSeries *QAreaSeries::upperSeries() const
403 {
405 {
404 Q_D(const QAreaSeries);
406 Q_D(const QAreaSeries);
405 return d->m_upperSeries;
407 return d->m_upperSeries;
406 }
408 }
407
409
408 /*!
410 /*!
409 Sets the \a series that is to be used as the area chart lower series.
411 Sets the \a series that is to be used as the area chart lower series.
410 */
412 */
411 void QAreaSeries::setLowerSeries(QLineSeries *series)
413 void QAreaSeries::setLowerSeries(QLineSeries *series)
412 {
414 {
413 Q_D(QAreaSeries);
415 Q_D(QAreaSeries);
416 series->d_ptr->setBlockOpenGL(true);
414 d->m_lowerSeries = series;
417 d->m_lowerSeries = series;
415 }
418 }
416
419
417 QLineSeries *QAreaSeries::lowerSeries() const
420 QLineSeries *QAreaSeries::lowerSeries() const
418 {
421 {
419 Q_D(const QAreaSeries);
422 Q_D(const QAreaSeries);
420 return d->m_lowerSeries;
423 return d->m_lowerSeries;
421 }
424 }
422
425
423 /*!
426 /*!
424 Sets \a pen used for drawing area outline.
427 Sets \a pen used for drawing area outline.
425 */
428 */
426 void QAreaSeries::setPen(const QPen &pen)
429 void QAreaSeries::setPen(const QPen &pen)
427 {
430 {
428 Q_D(QAreaSeries);
431 Q_D(QAreaSeries);
429 if (d->m_pen != pen) {
432 if (d->m_pen != pen) {
430 d->m_pen = pen;
433 d->m_pen = pen;
431 emit d->updated();
434 emit d->updated();
432 }
435 }
433 }
436 }
434
437
435 QPen QAreaSeries::pen() const
438 QPen QAreaSeries::pen() const
436 {
439 {
437 Q_D(const QAreaSeries);
440 Q_D(const QAreaSeries);
438 if (d->m_pen == QChartPrivate::defaultPen())
441 if (d->m_pen == QChartPrivate::defaultPen())
439 return QPen();
442 return QPen();
440 else
443 else
441 return d->m_pen;
444 return d->m_pen;
442 }
445 }
443
446
444 /*!
447 /*!
445 Sets \a brush used for filling the area.
448 Sets \a brush used for filling the area.
446 */
449 */
447 void QAreaSeries::setBrush(const QBrush &brush)
450 void QAreaSeries::setBrush(const QBrush &brush)
448 {
451 {
449 Q_D(QAreaSeries);
452 Q_D(QAreaSeries);
450 if (d->m_brush != brush) {
453 if (d->m_brush != brush) {
451 bool emitColorChanged = brush.color() != d->m_brush.color();
454 bool emitColorChanged = brush.color() != d->m_brush.color();
452 d->m_brush = brush;
455 d->m_brush = brush;
453 emit d->updated();
456 emit d->updated();
454 if (emitColorChanged)
457 if (emitColorChanged)
455 emit colorChanged(brush.color());
458 emit colorChanged(brush.color());
456 }
459 }
457 }
460 }
458
461
459 QBrush QAreaSeries::brush() const
462 QBrush QAreaSeries::brush() const
460 {
463 {
461 Q_D(const QAreaSeries);
464 Q_D(const QAreaSeries);
462 if (d->m_brush == QChartPrivate::defaultBrush())
465 if (d->m_brush == QChartPrivate::defaultBrush())
463 return QBrush();
466 return QBrush();
464 else
467 else
465 return d->m_brush;
468 return d->m_brush;
466 }
469 }
467
470
468 void QAreaSeries::setColor(const QColor &color)
471 void QAreaSeries::setColor(const QColor &color)
469 {
472 {
470 QBrush b = brush();
473 QBrush b = brush();
471 if (b == QBrush())
474 if (b == QBrush())
472 b.setStyle(Qt::SolidPattern);
475 b.setStyle(Qt::SolidPattern);
473 b.setColor(color);
476 b.setColor(color);
474 setBrush(b);
477 setBrush(b);
475 }
478 }
476
479
477 QColor QAreaSeries::color() const
480 QColor QAreaSeries::color() const
478 {
481 {
479 return brush().color();
482 return brush().color();
480 }
483 }
481
484
482 void QAreaSeries::setBorderColor(const QColor &color)
485 void QAreaSeries::setBorderColor(const QColor &color)
483 {
486 {
484 QPen p = pen();
487 QPen p = pen();
485 if (p.color() != color) {
488 if (p.color() != color) {
486 p.setColor(color);
489 p.setColor(color);
487 setPen(p);
490 setPen(p);
488 emit borderColorChanged(color);
491 emit borderColorChanged(color);
489 }
492 }
490 }
493 }
491
494
492 QColor QAreaSeries::borderColor() const
495 QColor QAreaSeries::borderColor() const
493 {
496 {
494 return pen().color();
497 return pen().color();
495 }
498 }
496
499
497 /*!
500 /*!
498 Sets if data points are \a visible and should be drawn on line.
501 Sets if data points are \a visible and should be drawn on line.
499 */
502 */
500 void QAreaSeries::setPointsVisible(bool visible)
503 void QAreaSeries::setPointsVisible(bool visible)
501 {
504 {
502 Q_D(QAreaSeries);
505 Q_D(QAreaSeries);
503 if (d->m_pointsVisible != visible) {
506 if (d->m_pointsVisible != visible) {
504 d->m_pointsVisible = visible;
507 d->m_pointsVisible = visible;
505 emit d->updated();
508 emit d->updated();
506 }
509 }
507 }
510 }
508
511
509 /*!
512 /*!
510 Returns if the points are drawn for this series.
513 Returns if the points are drawn for this series.
511 \sa setPointsVisible()
514 \sa setPointsVisible()
512 */
515 */
513 bool QAreaSeries::pointsVisible() const
516 bool QAreaSeries::pointsVisible() const
514 {
517 {
515 Q_D(const QAreaSeries);
518 Q_D(const QAreaSeries);
516 return d->m_pointsVisible;
519 return d->m_pointsVisible;
517 }
520 }
518
521
519 void QAreaSeries::setPointLabelsFormat(const QString &format)
522 void QAreaSeries::setPointLabelsFormat(const QString &format)
520 {
523 {
521 Q_D(QAreaSeries);
524 Q_D(QAreaSeries);
522 if (d->m_pointLabelsFormat != format) {
525 if (d->m_pointLabelsFormat != format) {
523 d->m_pointLabelsFormat = format;
526 d->m_pointLabelsFormat = format;
524 emit pointLabelsFormatChanged(format);
527 emit pointLabelsFormatChanged(format);
525 }
528 }
526 }
529 }
527
530
528 QString QAreaSeries::pointLabelsFormat() const
531 QString QAreaSeries::pointLabelsFormat() const
529 {
532 {
530 Q_D(const QAreaSeries);
533 Q_D(const QAreaSeries);
531 return d->m_pointLabelsFormat;
534 return d->m_pointLabelsFormat;
532 }
535 }
533
536
534 void QAreaSeries::setPointLabelsVisible(bool visible)
537 void QAreaSeries::setPointLabelsVisible(bool visible)
535 {
538 {
536 Q_D(QAreaSeries);
539 Q_D(QAreaSeries);
537 if (d->m_pointLabelsVisible != visible) {
540 if (d->m_pointLabelsVisible != visible) {
538 d->m_pointLabelsVisible = visible;
541 d->m_pointLabelsVisible = visible;
539 emit pointLabelsVisibilityChanged(visible);
542 emit pointLabelsVisibilityChanged(visible);
540 }
543 }
541 }
544 }
542
545
543 bool QAreaSeries::pointLabelsVisible() const
546 bool QAreaSeries::pointLabelsVisible() const
544 {
547 {
545 Q_D(const QAreaSeries);
548 Q_D(const QAreaSeries);
546 return d->m_pointLabelsVisible;
549 return d->m_pointLabelsVisible;
547 }
550 }
548
551
549 void QAreaSeries::setPointLabelsFont(const QFont &font)
552 void QAreaSeries::setPointLabelsFont(const QFont &font)
550 {
553 {
551 Q_D(QAreaSeries);
554 Q_D(QAreaSeries);
552 if (d->m_pointLabelsFont != font) {
555 if (d->m_pointLabelsFont != font) {
553 d->m_pointLabelsFont = font;
556 d->m_pointLabelsFont = font;
554 emit pointLabelsFontChanged(font);
557 emit pointLabelsFontChanged(font);
555 }
558 }
556 }
559 }
557
560
558 QFont QAreaSeries::pointLabelsFont() const
561 QFont QAreaSeries::pointLabelsFont() const
559 {
562 {
560 Q_D(const QAreaSeries);
563 Q_D(const QAreaSeries);
561 return d->m_pointLabelsFont;
564 return d->m_pointLabelsFont;
562 }
565 }
563
566
564 void QAreaSeries::setPointLabelsColor(const QColor &color)
567 void QAreaSeries::setPointLabelsColor(const QColor &color)
565 {
568 {
566 Q_D(QAreaSeries);
569 Q_D(QAreaSeries);
567 if (d->m_pointLabelsColor != color) {
570 if (d->m_pointLabelsColor != color) {
568 d->m_pointLabelsColor = color;
571 d->m_pointLabelsColor = color;
569 emit pointLabelsColorChanged(color);
572 emit pointLabelsColorChanged(color);
570 }
573 }
571 }
574 }
572
575
573 QColor QAreaSeries::pointLabelsColor() const
576 QColor QAreaSeries::pointLabelsColor() const
574 {
577 {
575 Q_D(const QAreaSeries);
578 Q_D(const QAreaSeries);
576 if (d->m_pointLabelsColor == QChartPrivate::defaultPen().color())
579 if (d->m_pointLabelsColor == QChartPrivate::defaultPen().color())
577 return QPen().color();
580 return QPen().color();
578 else
581 else
579 return d->m_pointLabelsColor;
582 return d->m_pointLabelsColor;
580 }
583 }
581
584
582 void QAreaSeries::setPointLabelsClipping(bool enabled)
585 void QAreaSeries::setPointLabelsClipping(bool enabled)
583 {
586 {
584 Q_D(QAreaSeries);
587 Q_D(QAreaSeries);
585 if (d->m_pointLabelsClipping != enabled) {
588 if (d->m_pointLabelsClipping != enabled) {
586 d->m_pointLabelsClipping = enabled;
589 d->m_pointLabelsClipping = enabled;
587 emit pointLabelsClippingChanged(enabled);
590 emit pointLabelsClippingChanged(enabled);
588 }
591 }
589 }
592 }
590
593
591 bool QAreaSeries::pointLabelsClipping() const
594 bool QAreaSeries::pointLabelsClipping() const
592 {
595 {
593 Q_D(const QAreaSeries);
596 Q_D(const QAreaSeries);
594 return d->m_pointLabelsClipping;
597 return d->m_pointLabelsClipping;
595 }
598 }
596
599
597 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
600 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
598
601
599 QAreaSeriesPrivate::QAreaSeriesPrivate(QLineSeries *upperSeries, QLineSeries *lowerSeries, QAreaSeries *q)
602 QAreaSeriesPrivate::QAreaSeriesPrivate(QLineSeries *upperSeries, QLineSeries *lowerSeries, QAreaSeries *q)
600 : QAbstractSeriesPrivate(q),
603 : QAbstractSeriesPrivate(q),
601 m_brush(QChartPrivate::defaultBrush()),
604 m_brush(QChartPrivate::defaultBrush()),
602 m_pen(QChartPrivate::defaultPen()),
605 m_pen(QChartPrivate::defaultPen()),
603 m_upperSeries(upperSeries),
606 m_upperSeries(upperSeries),
604 m_lowerSeries(lowerSeries),
607 m_lowerSeries(lowerSeries),
605 m_pointsVisible(false),
608 m_pointsVisible(false),
606 m_pointLabelsFormat(QLatin1String("@xPoint, @yPoint")),
609 m_pointLabelsFormat(QLatin1String("@xPoint, @yPoint")),
607 m_pointLabelsVisible(false),
610 m_pointLabelsVisible(false),
608 m_pointLabelsFont(QChartPrivate::defaultFont()),
611 m_pointLabelsFont(QChartPrivate::defaultFont()),
609 m_pointLabelsColor(QChartPrivate::defaultPen().color()),
612 m_pointLabelsColor(QChartPrivate::defaultPen().color()),
610 m_pointLabelsClipping(true)
613 m_pointLabelsClipping(true)
611 {
614 {
612 }
615 }
613
616
614 void QAreaSeriesPrivate::initializeDomain()
617 void QAreaSeriesPrivate::initializeDomain()
615 {
618 {
616 Q_Q(QAreaSeries);
619 Q_Q(QAreaSeries);
617
620
618 qreal minX(domain()->minX());
621 qreal minX(domain()->minX());
619 qreal minY(domain()->minY());
622 qreal minY(domain()->minY());
620 qreal maxX(domain()->maxX());
623 qreal maxX(domain()->maxX());
621 qreal maxY(domain()->maxY());
624 qreal maxY(domain()->maxY());
622
625
623 QLineSeries *upperSeries = q->upperSeries();
626 QLineSeries *upperSeries = q->upperSeries();
624 QLineSeries *lowerSeries = q->lowerSeries();
627 QLineSeries *lowerSeries = q->lowerSeries();
625
628
626 if (upperSeries) {
629 if (upperSeries) {
627 const QList<QPointF>& points = upperSeries->points();
630 const QVector<QPointF> &points = upperSeries->pointsVector();
628
631
629 for (int i = 0; i < points.count(); i++) {
632 for (int i = 0; i < points.count(); i++) {
630 qreal x = points[i].x();
633 qreal x = points[i].x();
631 qreal y = points[i].y();
634 qreal y = points[i].y();
632 minX = qMin(minX, x);
635 minX = qMin(minX, x);
633 minY = qMin(minY, y);
636 minY = qMin(minY, y);
634 maxX = qMax(maxX, x);
637 maxX = qMax(maxX, x);
635 maxY = qMax(maxY, y);
638 maxY = qMax(maxY, y);
636 }
639 }
637 }
640 }
638 if (lowerSeries) {
641 if (lowerSeries) {
639
642 const QVector<QPointF> &points = lowerSeries->pointsVector();
640 const QList<QPointF>& points = lowerSeries->points();
641
643
642 for (int i = 0; i < points.count(); i++) {
644 for (int i = 0; i < points.count(); i++) {
643 qreal x = points[i].x();
645 qreal x = points[i].x();
644 qreal y = points[i].y();
646 qreal y = points[i].y();
645 minX = qMin(minX, x);
647 minX = qMin(minX, x);
646 minY = qMin(minY, y);
648 minY = qMin(minY, y);
647 maxX = qMax(maxX, x);
649 maxX = qMax(maxX, x);
648 maxY = qMax(maxY, y);
650 maxY = qMax(maxY, y);
649 }
651 }
650 }
652 }
651
653
652 domain()->setRange(minX, maxX, minY, maxY);
654 domain()->setRange(minX, maxX, minY, maxY);
653 }
655 }
654
656
655 void QAreaSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
657 void QAreaSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
656 {
658 {
657 Q_Q(QAreaSeries);
659 Q_Q(QAreaSeries);
658 AreaChartItem *area = new AreaChartItem(q,parent);
660 AreaChartItem *area = new AreaChartItem(q,parent);
659 m_item.reset(area);
661 m_item.reset(area);
660 QAbstractSeriesPrivate::initializeGraphics(parent);
662 QAbstractSeriesPrivate::initializeGraphics(parent);
661 }
663 }
662 void QAreaSeriesPrivate::initializeAnimations(QChart::AnimationOptions options, int duration,
664 void QAreaSeriesPrivate::initializeAnimations(QChart::AnimationOptions options, int duration,
663 QEasingCurve &curve)
665 QEasingCurve &curve)
664 {
666 {
665 Q_Q(QAreaSeries);
667 Q_Q(QAreaSeries);
666 AreaChartItem *area = static_cast<AreaChartItem *>(m_item.data());
668 AreaChartItem *area = static_cast<AreaChartItem *>(m_item.data());
667
669
668 if (q->upperSeries() && area->upperLineItem()->animation())
670 if (q->upperSeries() && area->upperLineItem()->animation())
669 area->upperLineItem()->animation()->stopAndDestroyLater();
671 area->upperLineItem()->animation()->stopAndDestroyLater();
670 if (q->lowerSeries() && area->lowerLineItem()->animation())
672 if (q->lowerSeries() && area->lowerLineItem()->animation())
671 area->lowerLineItem()->animation()->stopAndDestroyLater();
673 area->lowerLineItem()->animation()->stopAndDestroyLater();
672
674
673 if (options.testFlag(QChart::SeriesAnimations)) {
675 if (options.testFlag(QChart::SeriesAnimations)) {
674 area->upperLineItem()->setAnimation(new XYAnimation(area->upperLineItem(), duration,
676 area->upperLineItem()->setAnimation(new XYAnimation(area->upperLineItem(), duration,
675 curve));
677 curve));
676 if (q->lowerSeries())
678 if (q->lowerSeries())
677 area->lowerLineItem()->setAnimation(new XYAnimation(area->lowerLineItem(), duration,
679 area->lowerLineItem()->setAnimation(new XYAnimation(area->lowerLineItem(), duration,
678 curve));
680 curve));
679 } else {
681 } else {
680 if (q->upperSeries())
682 if (q->upperSeries())
681 area->upperLineItem()->setAnimation(0);
683 area->upperLineItem()->setAnimation(0);
682 if (q->lowerSeries())
684 if (q->lowerSeries())
683 area->lowerLineItem()->setAnimation(0);
685 area->lowerLineItem()->setAnimation(0);
684 }
686 }
685 QAbstractSeriesPrivate::initializeAnimations(options, duration, curve);
687 QAbstractSeriesPrivate::initializeAnimations(options, duration, curve);
686 }
688 }
687
689
688 QList<QLegendMarker*> QAreaSeriesPrivate::createLegendMarkers(QLegend* legend)
690 QList<QLegendMarker*> QAreaSeriesPrivate::createLegendMarkers(QLegend* legend)
689 {
691 {
690 Q_Q(QAreaSeries);
692 Q_Q(QAreaSeries);
691 QList<QLegendMarker*> list;
693 QList<QLegendMarker*> list;
692 return list << new QAreaLegendMarker(q,legend);
694 return list << new QAreaLegendMarker(q,legend);
693 }
695 }
694
696
695
697
696 void QAreaSeriesPrivate::initializeAxes()
698 void QAreaSeriesPrivate::initializeAxes()
697 {
699 {
698
700
699 }
701 }
700
702
701 QAbstractAxis::AxisType QAreaSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
703 QAbstractAxis::AxisType QAreaSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
702 {
704 {
703 Q_UNUSED(orientation);
705 Q_UNUSED(orientation);
704 return QAbstractAxis::AxisTypeValue;
706 return QAbstractAxis::AxisTypeValue;
705 }
707 }
706
708
707 QAbstractAxis* QAreaSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
709 QAbstractAxis* QAreaSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
708 {
710 {
709 Q_UNUSED(orientation);
711 Q_UNUSED(orientation);
710 return new QValueAxis;
712 return new QValueAxis;
711 }
713 }
712
714
713 void QAreaSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
715 void QAreaSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
714 {
716 {
715 Q_Q(QAreaSeries);
717 Q_Q(QAreaSeries);
716
718
717 const QList<QGradient> gradients = theme->seriesGradients();
719 const QList<QGradient> gradients = theme->seriesGradients();
718 const QList<QColor> colors = theme->seriesColors();
720 const QList<QColor> colors = theme->seriesColors();
719
721
720 if (forced || QChartPrivate::defaultPen() == m_pen) {
722 if (forced || QChartPrivate::defaultPen() == m_pen) {
721 QPen pen;
723 QPen pen;
722 pen.setColor(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0));
724 pen.setColor(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0));
723 pen.setWidthF(2);
725 pen.setWidthF(2);
724 q->setPen(pen);
726 q->setPen(pen);
725 }
727 }
726
728
727 if (forced || QChartPrivate::defaultBrush() == m_brush) {
729 if (forced || QChartPrivate::defaultBrush() == m_brush) {
728 QBrush brush(colors.at(index % colors.size()));
730 QBrush brush(colors.at(index % colors.size()));
729 q->setBrush(brush);
731 q->setBrush(brush);
730 }
732 }
731
733
732 if (forced || QChartPrivate::defaultPen().color() == m_pointLabelsColor) {
734 if (forced || QChartPrivate::defaultPen().color() == m_pointLabelsColor) {
733 QColor color = theme->labelBrush().color();
735 QColor color = theme->labelBrush().color();
734 q->setPointLabelsColor(color);
736 q->setPointLabelsColor(color);
735 }
737 }
736 }
738 }
737
739
738
740
739 #include "moc_qareaseries.cpp"
741 #include "moc_qareaseries.cpp"
740 #include "moc_qareaseries_p.cpp"
742 #include "moc_qareaseries_p.cpp"
741
743
742 QT_CHARTS_END_NAMESPACE
744 QT_CHARTS_END_NAMESPACE
@@ -1,1090 +1,1090
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <QtCharts/QAbstractAxis>
19 #include <QtCharts/QAbstractAxis>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <private/chartdataset_p.h>
21 #include <private/chartdataset_p.h>
22 #include <private/charttheme_p.h>
22 #include <private/charttheme_p.h>
23 #include <private/qchart_p.h>
23 #include <private/qchart_p.h>
24
24
25 QT_CHARTS_BEGIN_NAMESPACE
25 QT_CHARTS_BEGIN_NAMESPACE
26
26
27 /*!
27 /*!
28 \class QAbstractAxis
28 \class QAbstractAxis
29 \inmodule Qt Charts
29 \inmodule Qt Charts
30 \brief The QAbstractAxis class is used for manipulating chart's axis.
30 \brief The QAbstractAxis class is used for manipulating chart's axis.
31
31
32 Each series can be bound to one or more horizontal and vertical axes, but mixing axis types
32 Each series can be bound to one or more horizontal and vertical axes, but mixing axis types
33 that would result in different domains is not supported, such as specifying
33 that would result in different domains is not supported, such as specifying
34 QValueAxis and QLogValueAxis on the same orientation.
34 QValueAxis and QLogValueAxis on the same orientation.
35
35
36 Properties and visibility of various axis elements such as axis line, title, labels, grid lines,
36 Properties and visibility of various axis elements such as axis line, title, labels, grid lines,
37 and shades can be individually controlled.
37 and shades can be individually controlled.
38 */
38 */
39 /*!
39 /*!
40 \qmltype AbstractAxis
40 \qmltype AbstractAxis
41 \instantiates QAbstractAxis
41 \instantiates QAbstractAxis
42 \inqmlmodule QtCharts
42 \inqmlmodule QtCharts
43
43
44 \brief The AbstractAxis is a base element used for specialized axis elements.
44 \brief The AbstractAxis is a base element used for specialized axis elements.
45
45
46 Each series can be bound to only one horizontal and vertical axis.
46 Each series can be bound to only one horizontal and vertical axis.
47
47
48 Properties and visibility of various axis elements such as axis line, title, labels, grid lines,
48 Properties and visibility of various axis elements such as axis line, title, labels, grid lines,
49 and shades can be individually controlled.
49 and shades can be individually controlled.
50 */
50 */
51
51
52 /*!
52 /*!
53 \enum QAbstractAxis::AxisType
53 \enum QAbstractAxis::AxisType
54
54
55 The type of the axis object.
55 The type of the axis object.
56
56
57 \value AxisTypeNoAxis
57 \value AxisTypeNoAxis
58 \value AxisTypeValue
58 \value AxisTypeValue
59 \value AxisTypeBarCategory
59 \value AxisTypeBarCategory
60 \value AxisTypeCategory
60 \value AxisTypeCategory
61 \value AxisTypeDateTime
61 \value AxisTypeDateTime
62 \value AxisTypeLogValue
62 \value AxisTypeLogValue
63 */
63 */
64
64
65 /*!
65 /*!
66 *\fn void QAbstractAxis::type() const
66 *\fn void QAbstractAxis::type() const
67 Returns the type of the axis
67 Returns the type of the axis
68 */
68 */
69
69
70 /*!
70 /*!
71 \property QAbstractAxis::lineVisible
71 \property QAbstractAxis::lineVisible
72 The visibility of the axis line
72 The visibility of the axis line
73 */
73 */
74 /*!
74 /*!
75 \qmlproperty bool AbstractAxis::lineVisible
75 \qmlproperty bool AbstractAxis::lineVisible
76 The visibility of the axis line
76 The visibility of the axis line
77 */
77 */
78
78
79 /*!
79 /*!
80 \property QAbstractAxis::linePen
80 \property QAbstractAxis::linePen
81 The pen of the line.
81 The pen of the line.
82 */
82 */
83
83
84 /*!
84 /*!
85 \property QAbstractAxis::labelsVisible
85 \property QAbstractAxis::labelsVisible
86 Defines if axis labels are visible.
86 Defines if axis labels are visible.
87 */
87 */
88 /*!
88 /*!
89 \qmlproperty bool AbstractAxis::labelsVisible
89 \qmlproperty bool AbstractAxis::labelsVisible
90 Defines if axis labels are visible.
90 Defines if axis labels are visible.
91 */
91 */
92
92
93 /*!
93 /*!
94 \property QAbstractAxis::labelsBrush
94 \property QAbstractAxis::labelsBrush
95 The brush of the labels. Only the color of the brush is relevant.
95 The brush of the labels. Only the color of the brush is relevant.
96 */
96 */
97
97
98 /*!
98 /*!
99 \property QAbstractAxis::visible
99 \property QAbstractAxis::visible
100 The visibility of the axis.
100 The visibility of the axis.
101 */
101 */
102 /*!
102 /*!
103 \qmlproperty bool AbstractAxis::visible
103 \qmlproperty bool AbstractAxis::visible
104 The visibility of the axis.
104 The visibility of the axis.
105 */
105 */
106
106
107 /*!
107 /*!
108 \property QAbstractAxis::gridVisible
108 \property QAbstractAxis::gridVisible
109 The visibility of the grid lines.
109 The visibility of the grid lines.
110 */
110 */
111 /*!
111 /*!
112 \qmlproperty bool AbstractAxis::gridVisible
112 \qmlproperty bool AbstractAxis::gridVisible
113 The visibility of the grid lines.
113 The visibility of the grid lines.
114 */
114 */
115
115
116 /*!
116 /*!
117 \property QAbstractAxis::minorGridVisible
117 \property QAbstractAxis::minorGridVisible
118 The visibility of the minor grid lines. Applies only to QValueAxis.
118 The visibility of the minor grid lines. Applies only to QValueAxis.
119 */
119 */
120 /*!
120 /*!
121 \qmlproperty bool AbstractAxis::minorGridVisible
121 \qmlproperty bool AbstractAxis::minorGridVisible
122 The visibility of the minor grid lines. Applies only to QValueAxis.
122 The visibility of the minor grid lines. Applies only to QValueAxis.
123 */
123 */
124
124
125 /*!
125 /*!
126 \property QAbstractAxis::color
126 \property QAbstractAxis::color
127 The color of the axis and ticks.
127 The color of the axis and ticks.
128 */
128 */
129 /*!
129 /*!
130 \qmlproperty color AbstractAxis::color
130 \qmlproperty color AbstractAxis::color
131 The color of the axis and ticks.
131 The color of the axis and ticks.
132 */
132 */
133
133
134 /*!
134 /*!
135 \property QAbstractAxis::gridLinePen
135 \property QAbstractAxis::gridLinePen
136 The pen of the grid line.
136 The pen of the grid line.
137 */
137 */
138
138
139 /*!
139 /*!
140 \property QAbstractAxis::minorGridLinePen
140 \property QAbstractAxis::minorGridLinePen
141 The pen of the minor grid line. Applies only to QValueAxis.
141 The pen of the minor grid line. Applies only to QValueAxis.
142 */
142 */
143
143
144 /*!
144 /*!
145 \property QAbstractAxis::gridLineColor
145 \property QAbstractAxis::gridLineColor
146 The color of the grid line.
146 The color of the grid line.
147 */
147 */
148
148
149 /*!
149 /*!
150 \property QAbstractAxis::minorGridLineColor
150 \property QAbstractAxis::minorGridLineColor
151 The color of the minor grid line. Applies only to QValueAxis.
151 The color of the minor grid line. Applies only to QValueAxis.
152 */
152 */
153
153
154 /*!
154 /*!
155 \property QAbstractAxis::labelsFont
155 \property QAbstractAxis::labelsFont
156 The font of the axis labels.
156 The font of the axis labels.
157 */
157 */
158
158
159 /*!
159 /*!
160 \qmlproperty Font AbstractAxis::labelsFont
160 \qmlproperty Font AbstractAxis::labelsFont
161 The font of the axis labels.
161 The font of the axis labels.
162
162
163 See the Qt documentation for more details of Font.
163 See the Qt documentation for more details of Font.
164 */
164 */
165
165
166 /*!
166 /*!
167 \property QAbstractAxis::labelsColor
167 \property QAbstractAxis::labelsColor
168 The color of the axis labels.
168 The color of the axis labels.
169 */
169 */
170 /*!
170 /*!
171 \qmlproperty color AbstractAxis::labelsColor
171 \qmlproperty color AbstractAxis::labelsColor
172 The color of the axis labels.
172 The color of the axis labels.
173 */
173 */
174
174
175 /*!
175 /*!
176 \property QAbstractAxis::labelsAngle
176 \property QAbstractAxis::labelsAngle
177 The angle of the axis labels in degrees.
177 The angle of the axis labels in degrees.
178 */
178 */
179 /*!
179 /*!
180 \qmlproperty int AbstractAxis::labelsAngle
180 \qmlproperty int AbstractAxis::labelsAngle
181 The angle of the axis labels in degrees.
181 The angle of the axis labels in degrees.
182 */
182 */
183
183
184 /*!
184 /*!
185 \property QAbstractAxis::shadesVisible
185 \property QAbstractAxis::shadesVisible
186 The visibility of the axis shades.
186 The visibility of the axis shades.
187 */
187 */
188 /*!
188 /*!
189 \qmlproperty bool AbstractAxis::shadesVisible
189 \qmlproperty bool AbstractAxis::shadesVisible
190 The visibility of the axis shades.
190 The visibility of the axis shades.
191 */
191 */
192
192
193 /*!
193 /*!
194 \property QAbstractAxis::shadesColor
194 \property QAbstractAxis::shadesColor
195 The fill (brush) color of the axis shades.
195 The fill (brush) color of the axis shades.
196 */
196 */
197 /*!
197 /*!
198 \qmlproperty color AbstractAxis::shadesColor
198 \qmlproperty color AbstractAxis::shadesColor
199 The fill (brush) color of the axis shades.
199 The fill (brush) color of the axis shades.
200 */
200 */
201
201
202 /*!
202 /*!
203 \property QAbstractAxis::shadesBorderColor
203 \property QAbstractAxis::shadesBorderColor
204 The border (pen) color of the axis shades.
204 The border (pen) color of the axis shades.
205 */
205 */
206 /*!
206 /*!
207 \qmlproperty color AbstractAxis::shadesBorderColor
207 \qmlproperty color AbstractAxis::shadesBorderColor
208 The border (pen) color of the axis shades.
208 The border (pen) color of the axis shades.
209 */
209 */
210
210
211 /*!
211 /*!
212 \property QAbstractAxis::shadesPen
212 \property QAbstractAxis::shadesPen
213 The pen of the axis shades (area between grid lines).
213 The pen of the axis shades (area between grid lines).
214 */
214 */
215
215
216 /*!
216 /*!
217 \property QAbstractAxis::shadesBrush
217 \property QAbstractAxis::shadesBrush
218 The brush of the axis shades (area between grid lines).
218 The brush of the axis shades (area between grid lines).
219 */
219 */
220
220
221 /*!
221 /*!
222 \property QAbstractAxis::titleVisible
222 \property QAbstractAxis::titleVisible
223 The visibility of the axis title. By default the value is true.
223 The visibility of the axis title. By default the value is true.
224 */
224 */
225 /*!
225 /*!
226 \qmlproperty bool AbstractAxis::titleVisible
226 \qmlproperty bool AbstractAxis::titleVisible
227 The visibility of the axis title. By default the value is true.
227 The visibility of the axis title. By default the value is true.
228 */
228 */
229
229
230 /*!
230 /*!
231 \property QAbstractAxis::titleText
231 \property QAbstractAxis::titleText
232 The title of the axis. Empty by default. Axis titles support html formatting.
232 The title of the axis. Empty by default. Axis titles support html formatting.
233 */
233 */
234 /*!
234 /*!
235 \qmlproperty String AbstractAxis::titleText
235 \qmlproperty String AbstractAxis::titleText
236 The title of the axis. Empty by default. Axis titles support html formatting.
236 The title of the axis. Empty by default. Axis titles support html formatting.
237 */
237 */
238
238
239 /*!
239 /*!
240 \property QAbstractAxis::titleBrush
240 \property QAbstractAxis::titleBrush
241 The brush of the title text. Only the color of the brush is relevant.
241 The brush of the title text. Only the color of the brush is relevant.
242 */
242 */
243
243
244 /*!
244 /*!
245 \property QAbstractAxis::titleFont
245 \property QAbstractAxis::titleFont
246 The font of the title of the axis.
246 The font of the title of the axis.
247 */
247 */
248 /*!
248 /*!
249 \qmlproperty Font AbstractAxis::titleFont
249 \qmlproperty Font AbstractAxis::titleFont
250 The font of the title of the axis.
250 The font of the title of the axis.
251 */
251 */
252
252
253 /*!
253 /*!
254 \property QAbstractAxis::orientation
254 \property QAbstractAxis::orientation
255 The orientation of the axis. Fixed to either Qt::Horizontal or Qt::Vertical when you add the axis to a chart.
255 The orientation of the axis. Fixed to either Qt::Horizontal or Qt::Vertical when you add the axis to a chart.
256 */
256 */
257 /*!
257 /*!
258 \qmlproperty Qt.Orientation AbstractAxis::orientation
258 \qmlproperty Qt.Orientation AbstractAxis::orientation
259 The orientation of the axis. Fixed to either Qt.Horizontal or Qt.Vertical when the axis is set to a series.
259 The orientation of the axis. Fixed to either Qt.Horizontal or Qt.Vertical when the axis is set to a series.
260 */
260 */
261
261
262 /*!
262 /*!
263 \property QAbstractAxis::alignment
263 \property QAbstractAxis::alignment
264 The alignment of the axis. Can be Qt::AlignLeft, Qt::AlignRight, Qt::AlignBottom, or Qt::AlignTop.
264 The alignment of the axis. Can be Qt::AlignLeft, Qt::AlignRight, Qt::AlignBottom, or Qt::AlignTop.
265 */
265 */
266 /*!
266 /*!
267 \qmlproperty alignment AbstractAxis::alignment
267 \qmlproperty alignment AbstractAxis::alignment
268 The alignment of the axis. Can be Qt.AlignLeft, Qt.AlignRight, Qt.AlignBottom, or Qt.AlignTop.
268 The alignment of the axis. Can be Qt.AlignLeft, Qt.AlignRight, Qt.AlignBottom, or Qt.AlignTop.
269 */
269 */
270
270
271 /*!
271 /*!
272 \property QAbstractAxis::reverse
272 \property QAbstractAxis::reverse
273 The reverse property defines if reverse axis is used. By default the value is false.
273 The reverse property defines if reverse axis is used. By default the value is false.
274
274
275 Reverse axis is supported with line, spline, scatter and area series with cartesian chart.
275 Reverse axis is supported with line, spline, scatter and area series with cartesian chart.
276 All axes of the same orientation attached to same series must be reversed if one is reversed or
276 All axes of the same orientation attached to same series must be reversed if one is reversed or
277 the behavior is undefined.
277 the behavior is undefined.
278 */
278 */
279 /*!
279 /*!
280 \qmlproperty alignment AbstractAxis::reverse
280 \qmlproperty alignment AbstractAxis::reverse
281 The reverse property defines if reverse axis is used. By default the value is false.
281 The reverse property defines if reverse axis is used. By default the value is false.
282
282
283 Reverse axis is supported with line, spline, scatter and area series with cartesian chart.
283 Reverse axis is supported with line, spline, scatter and area series with cartesian chart.
284 All axes of the same orientation attached to same series must be reversed if one is reversed or
284 All axes of the same orientation attached to same series must be reversed if one is reversed or
285 the behavior is undefined.
285 the behavior is undefined.
286 */
286 */
287
287
288 /*!
288 /*!
289 \fn void QAbstractAxis::visibleChanged(bool visible)
289 \fn void QAbstractAxis::visibleChanged(bool visible)
290 Visibility of the axis has changed to \a visible.
290 Visibility of the axis has changed to \a visible.
291 */
291 */
292 /*!
292 /*!
293 \qmlsignal AbstractAxis::onVisibleChanged(bool visible)
293 \qmlsignal AbstractAxis::onVisibleChanged(bool visible)
294 Visibility of the axis has changed to \a visible.
294 Visibility of the axis has changed to \a visible.
295 */
295 */
296
296
297 /*!
297 /*!
298 \fn void QAbstractAxis::linePenChanged(const QPen& pen)
298 \fn void QAbstractAxis::linePenChanged(const QPen& pen)
299 The pen of the line of the axis has changed to \a pen.
299 The pen of the line of the axis has changed to \a pen.
300 */
300 */
301
301
302 /*!
302 /*!
303 \fn void QAbstractAxis::lineVisibleChanged(bool visible)
303 \fn void QAbstractAxis::lineVisibleChanged(bool visible)
304 Visibility of the axis line has changed to \a visible.
304 Visibility of the axis line has changed to \a visible.
305 */
305 */
306 /*!
306 /*!
307 \qmlsignal AbstractAxis::onLineVisibleChanged(bool visible)
307 \qmlsignal AbstractAxis::onLineVisibleChanged(bool visible)
308 Visibility of the axis line has changed to \a visible.
308 Visibility of the axis line has changed to \a visible.
309 */
309 */
310
310
311 /*!
311 /*!
312 \fn void QAbstractAxis::labelsVisibleChanged(bool visible)
312 \fn void QAbstractAxis::labelsVisibleChanged(bool visible)
313 Visibility of the labels of the axis has changed to \a visible.
313 Visibility of the labels of the axis has changed to \a visible.
314 */
314 */
315 /*!
315 /*!
316 \qmlsignal AbstractAxis::onLabelsVisibleChanged(bool visible)
316 \qmlsignal AbstractAxis::onLabelsVisibleChanged(bool visible)
317 Visibility of the labels of the axis has changed to \a visible.
317 Visibility of the labels of the axis has changed to \a visible.
318 */
318 */
319
319
320 /*!
320 /*!
321 \fn void QAbstractAxis::labelsFontChanged(const QFont& font)
321 \fn void QAbstractAxis::labelsFontChanged(const QFont& font)
322 The font of the axis labels has changed to \a font.
322 The font of the axis labels has changed to \a font.
323 */
323 */
324 /*!
324 /*!
325 \qmlsignal AbstractAxis::onLabelsFontChanged(Font font)
325 \qmlsignal AbstractAxis::onLabelsFontChanged(Font font)
326 The font of the axis labels has changed to \a font.
326 The font of the axis labels has changed to \a font.
327 */
327 */
328
328
329 /*!
329 /*!
330 \fn void QAbstractAxis::labelsBrushChanged(const QBrush& brush)
330 \fn void QAbstractAxis::labelsBrushChanged(const QBrush& brush)
331 The brush of the axis labels has changed to \a brush.
331 The brush of the axis labels has changed to \a brush.
332 */
332 */
333
333
334 /*!
334 /*!
335 \fn void QAbstractAxis::labelsAngleChanged(int angle)
335 \fn void QAbstractAxis::labelsAngleChanged(int angle)
336 The angle of the axis labels has changed to \a angle.
336 The angle of the axis labels has changed to \a angle.
337 */
337 */
338 /*!
338 /*!
339 \qmlsignal AbstractAxis::onLabelsAngleChanged(int angle)
339 \qmlsignal AbstractAxis::onLabelsAngleChanged(int angle)
340 The angle of the axis labels has changed to \a angle.
340 The angle of the axis labels has changed to \a angle.
341 */
341 */
342
342
343 /*!
343 /*!
344 \fn void QAbstractAxis::gridVisibleChanged(bool visible)
344 \fn void QAbstractAxis::gridVisibleChanged(bool visible)
345 Visibility of the grid lines of the axis has changed to \a visible.
345 Visibility of the grid lines of the axis has changed to \a visible.
346 */
346 */
347 /*!
347 /*!
348 \qmlsignal AbstractAxis::onGridVisibleChanged(bool visible)
348 \qmlsignal AbstractAxis::onGridVisibleChanged(bool visible)
349 Visibility of the grid lines of the axis has changed to \a visible.
349 Visibility of the grid lines of the axis has changed to \a visible.
350 */
350 */
351
351
352 /*!
352 /*!
353 \fn void QAbstractAxis::minorGridVisibleChanged(bool visible)
353 \fn void QAbstractAxis::minorGridVisibleChanged(bool visible)
354 Visibility of the minor grid lines of the axis has changed to \a visible.
354 Visibility of the minor grid lines of the axis has changed to \a visible.
355 */
355 */
356 /*!
356 /*!
357 \qmlsignal AbstractAxis::onMinorGridVisibleChanged(bool visible)
357 \qmlsignal AbstractAxis::onMinorGridVisibleChanged(bool visible)
358 Visibility of the minor grid lines of the axis has changed to \a visible.
358 Visibility of the minor grid lines of the axis has changed to \a visible.
359 */
359 */
360
360
361 /*!
361 /*!
362 \fn void QAbstractAxis::gridLinePenChanged(const QPen& pen)
362 \fn void QAbstractAxis::gridLinePenChanged(const QPen& pen)
363 The pen of the grid line has changed to \a pen.
363 The pen of the grid line has changed to \a pen.
364 */
364 */
365
365
366 /*!
366 /*!
367 \fn void QAbstractAxis::minorGridLinePenChanged(const QPen& pen)
367 \fn void QAbstractAxis::minorGridLinePenChanged(const QPen& pen)
368 The pen of the minor grid line has changed to \a pen.
368 The pen of the minor grid line has changed to \a pen.
369 */
369 */
370
370
371 /*!
371 /*!
372 \fn void QAbstractAxis::gridLineColorChanged(const QColor &color)
372 \fn void QAbstractAxis::gridLineColorChanged(const QColor &color)
373 The color of the pen of the grid line has changed to \a color.
373 The color of the pen of the grid line has changed to \a color.
374 */
374 */
375
375
376 /*!
376 /*!
377 \fn void QAbstractAxis::minorGridLineColorChanged(const QColor &color)
377 \fn void QAbstractAxis::minorGridLineColorChanged(const QColor &color)
378 The color of the pen of the minor grid line has changed to \a color.
378 The color of the pen of the minor grid line has changed to \a color.
379 */
379 */
380
380
381 /*!
381 /*!
382 \fn void QAbstractAxis::colorChanged(QColor color)
382 \fn void QAbstractAxis::colorChanged(QColor color)
383 Emitted if the \a color of the axis is changed.
383 Emitted if the \a color of the axis is changed.
384 */
384 */
385 /*!
385 /*!
386 \qmlsignal AbstractAxis::onColorChanged(QColor color)
386 \qmlsignal AbstractAxis::onColorChanged(QColor color)
387 Emitted if the \a color of the axis is changed.
387 Emitted if the \a color of the axis is changed.
388 */
388 */
389
389
390 /*!
390 /*!
391 \fn void QAbstractAxis::labelsColorChanged(QColor color)
391 \fn void QAbstractAxis::labelsColorChanged(QColor color)
392 Emitted if the \a color of the axis labels is changed.
392 Emitted if the \a color of the axis labels is changed.
393 */
393 */
394 /*!
394 /*!
395 \qmlsignal AbstractAxis::onLabelsColorChanged(QColor color)
395 \qmlsignal AbstractAxis::onLabelsColorChanged(QColor color)
396 Emitted if the \a color of the axis labels is changed.
396 Emitted if the \a color of the axis labels is changed.
397 */
397 */
398
398
399 /*!
399 /*!
400 \fn void QAbstractAxis::titleVisibleChanged(bool visible)
400 \fn void QAbstractAxis::titleVisibleChanged(bool visible)
401 Visibility of the title text of the axis has changed to \a visible.
401 Visibility of the title text of the axis has changed to \a visible.
402 */
402 */
403 /*!
403 /*!
404 \qmlsignal AbstractAxis::onTitleVisibleChanged(bool visible)
404 \qmlsignal AbstractAxis::onTitleVisibleChanged(bool visible)
405 Visibility of the title text of the axis has changed to \a visible.
405 Visibility of the title text of the axis has changed to \a visible.
406 */
406 */
407
407
408 /*!
408 /*!
409 \fn void QAbstractAxis::titleTextChanged(const QString& text)
409 \fn void QAbstractAxis::titleTextChanged(const QString& text)
410 The text of the axis title has changed to \a text.
410 The text of the axis title has changed to \a text.
411 */
411 */
412 /*!
412 /*!
413 \qmlsignal AbstractAxis::onTitleTextChanged(String text)
413 \qmlsignal AbstractAxis::onTitleTextChanged(String text)
414 The text of the axis title has changed to \a text.
414 The text of the axis title has changed to \a text.
415 */
415 */
416
416
417 /*!
417 /*!
418 \fn void QAbstractAxis::titleBrushChanged(const QBrush& brush)
418 \fn void QAbstractAxis::titleBrushChanged(const QBrush& brush)
419 The brush of the axis title has changed to \a brush.
419 The brush of the axis title has changed to \a brush.
420 */
420 */
421
421
422 /*!
422 /*!
423 \fn void QAbstractAxis::titleFontChanged(const QFont& font)
423 \fn void QAbstractAxis::titleFontChanged(const QFont& font)
424 The font of the axis title has changed to \a font.
424 The font of the axis title has changed to \a font.
425 */
425 */
426 /*!
426 /*!
427 \qmlsignal AbstractAxis::onTitleFontChanged(Font font)
427 \qmlsignal AbstractAxis::onTitleFontChanged(Font font)
428 The font of the axis title has changed to \a font.
428 The font of the axis title has changed to \a font.
429 */
429 */
430
430
431 /*!
431 /*!
432 \fn void QAbstractAxis::shadesVisibleChanged(bool)
432 \fn void QAbstractAxis::shadesVisibleChanged(bool)
433 Emitted if the visibility of the axis shades is changed to \a visible.
433 Emitted if the visibility of the axis shades is changed to \a visible.
434 */
434 */
435 /*!
435 /*!
436 \qmlsignal AbstractAxis::onShadesVisibleChanged(bool visible)
436 \qmlsignal AbstractAxis::onShadesVisibleChanged(bool visible)
437 Emitted if the visibility of the axis shades is changed to \a visible.
437 Emitted if the visibility of the axis shades is changed to \a visible.
438 */
438 */
439
439
440 /*!
440 /*!
441 \fn void QAbstractAxis::shadesColorChanged(QColor color)
441 \fn void QAbstractAxis::shadesColorChanged(QColor color)
442 Emitted if the \a color of the axis shades is changed.
442 Emitted if the \a color of the axis shades is changed.
443 */
443 */
444 /*!
444 /*!
445 \qmlsignal AbstractAxis::onShadesColorChanged(QColor color)
445 \qmlsignal AbstractAxis::onShadesColorChanged(QColor color)
446 Emitted if the \a color of the axis shades is changed.
446 Emitted if the \a color of the axis shades is changed.
447 */
447 */
448
448
449 /*!
449 /*!
450 \fn void QAbstractAxis::shadesBorderColorChanged(QColor)
450 \fn void QAbstractAxis::shadesBorderColorChanged(QColor)
451 Emitted if the border \a color of the axis shades is changed.
451 Emitted if the border \a color of the axis shades is changed.
452 */
452 */
453 /*!
453 /*!
454 \qmlsignal AbstractAxis::onBorderColorChanged(QColor color)
454 \qmlsignal AbstractAxis::onBorderColorChanged(QColor color)
455 Emitted if the border \a color of the axis shades is changed.
455 Emitted if the border \a color of the axis shades is changed.
456 */
456 */
457
457
458 /*!
458 /*!
459 \fn void QAbstractAxis::shadesBrushChanged(const QBrush& brush)
459 \fn void QAbstractAxis::shadesBrushChanged(const QBrush& brush)
460 The brush of the axis shades has changed to \a brush.
460 The brush of the axis shades has changed to \a brush.
461 */
461 */
462
462
463 /*!
463 /*!
464 \fn void QAbstractAxis::shadesPenChanged(const QPen& pen)
464 \fn void QAbstractAxis::shadesPenChanged(const QPen& pen)
465 The pen of the axis shades has changed to \a pen.
465 The pen of the axis shades has changed to \a pen.
466 */
466 */
467
467
468 /*!
468 /*!
469 \internal
469 \internal
470 Constructs new axis object which is a child of \a parent. Ownership is taken by
470 Constructs new axis object which is a child of \a parent. Ownership is taken by
471 QChart when axis added.
471 QChart when axis added.
472 */
472 */
473
473
474 QAbstractAxis::QAbstractAxis(QAbstractAxisPrivate &d, QObject *parent)
474 QAbstractAxis::QAbstractAxis(QAbstractAxisPrivate &d, QObject *parent)
475 : QObject(parent),
475 : QObject(parent),
476 d_ptr(&d)
476 d_ptr(&d)
477 {
477 {
478 }
478 }
479
479
480 /*!
480 /*!
481 Destructor of the axis object. When axis is added to chart, chart object takes ownership.
481 Destructor of the axis object. When axis is added to chart, chart object takes ownership.
482 */
482 */
483
483
484 QAbstractAxis::~QAbstractAxis()
484 QAbstractAxis::~QAbstractAxis()
485 {
485 {
486 if (d_ptr->m_chart)
486 if (d_ptr->m_chart)
487 qFatal("Still binded axis detected !");
487 qFatal("Still binded axis detected !");
488 }
488 }
489
489
490 /*!
490 /*!
491 Sets \a pen used to draw axis line and ticks.
491 Sets \a pen used to draw axis line and ticks.
492 */
492 */
493 void QAbstractAxis::setLinePen(const QPen &pen)
493 void QAbstractAxis::setLinePen(const QPen &pen)
494 {
494 {
495 if (d_ptr->m_axisPen != pen) {
495 if (d_ptr->m_axisPen != pen) {
496 d_ptr->m_axisPen = pen;
496 d_ptr->m_axisPen = pen;
497 emit linePenChanged(pen);
497 emit linePenChanged(pen);
498 }
498 }
499 }
499 }
500
500
501 /*!
501 /*!
502 Returns pen used to draw axis and ticks.
502 Returns pen used to draw axis and ticks.
503 */
503 */
504 QPen QAbstractAxis::linePen() const
504 QPen QAbstractAxis::linePen() const
505 {
505 {
506 if (d_ptr->m_axisPen == QChartPrivate::defaultPen())
506 if (d_ptr->m_axisPen == QChartPrivate::defaultPen())
507 return QPen();
507 return QPen();
508 else
508 else
509 return d_ptr->m_axisPen;
509 return d_ptr->m_axisPen;
510 }
510 }
511
511
512 void QAbstractAxis::setLinePenColor(QColor color)
512 void QAbstractAxis::setLinePenColor(QColor color)
513 {
513 {
514 QPen p = d_ptr->m_axisPen;
514 QPen p = d_ptr->m_axisPen;
515 if (p.color() != color) {
515 if (p.color() != color) {
516 p.setColor(color);
516 p.setColor(color);
517 setLinePen(p);
517 setLinePen(p);
518 emit colorChanged(color);
518 emit colorChanged(color);
519 }
519 }
520 }
520 }
521
521
522 QColor QAbstractAxis::linePenColor() const
522 QColor QAbstractAxis::linePenColor() const
523 {
523 {
524 return linePen().color();
524 return linePen().color();
525 }
525 }
526
526
527 /*!
527 /*!
528 Sets if axis and ticks are \a visible.
528 Sets if axis and ticks are \a visible.
529 */
529 */
530 void QAbstractAxis::setLineVisible(bool visible)
530 void QAbstractAxis::setLineVisible(bool visible)
531 {
531 {
532 if (d_ptr->m_arrowVisible != visible) {
532 if (d_ptr->m_arrowVisible != visible) {
533 d_ptr->m_arrowVisible = visible;
533 d_ptr->m_arrowVisible = visible;
534 emit lineVisibleChanged(visible);
534 emit lineVisibleChanged(visible);
535 }
535 }
536 }
536 }
537
537
538 bool QAbstractAxis::isLineVisible() const
538 bool QAbstractAxis::isLineVisible() const
539 {
539 {
540 return d_ptr->m_arrowVisible;
540 return d_ptr->m_arrowVisible;
541 }
541 }
542
542
543 void QAbstractAxis::setGridLineVisible(bool visible)
543 void QAbstractAxis::setGridLineVisible(bool visible)
544 {
544 {
545 if (d_ptr->m_gridLineVisible != visible) {
545 if (d_ptr->m_gridLineVisible != visible) {
546 d_ptr->m_gridLineVisible = visible;
546 d_ptr->m_gridLineVisible = visible;
547 emit gridVisibleChanged(visible);
547 emit gridVisibleChanged(visible);
548 }
548 }
549 }
549 }
550
550
551 bool QAbstractAxis::isGridLineVisible() const
551 bool QAbstractAxis::isGridLineVisible() const
552 {
552 {
553 return d_ptr->m_gridLineVisible;
553 return d_ptr->m_gridLineVisible;
554 }
554 }
555
555
556 void QAbstractAxis::setMinorGridLineVisible(bool visible)
556 void QAbstractAxis::setMinorGridLineVisible(bool visible)
557 {
557 {
558 if (d_ptr->m_minorGridLineVisible != visible) {
558 if (d_ptr->m_minorGridLineVisible != visible) {
559 d_ptr->m_minorGridLineVisible = visible;
559 d_ptr->m_minorGridLineVisible = visible;
560 emit minorGridVisibleChanged(visible);
560 emit minorGridVisibleChanged(visible);
561 }
561 }
562 }
562 }
563
563
564 bool QAbstractAxis::isMinorGridLineVisible() const
564 bool QAbstractAxis::isMinorGridLineVisible() const
565 {
565 {
566 return d_ptr->m_minorGridLineVisible;
566 return d_ptr->m_minorGridLineVisible;
567 }
567 }
568
568
569 /*!
569 /*!
570 Sets \a pen used to draw grid line.
570 Sets \a pen used to draw grid line.
571 */
571 */
572 void QAbstractAxis::setGridLinePen(const QPen &pen)
572 void QAbstractAxis::setGridLinePen(const QPen &pen)
573 {
573 {
574 if (d_ptr->m_gridLinePen != pen) {
574 if (d_ptr->m_gridLinePen != pen) {
575 d_ptr->m_gridLinePen = pen;
575 d_ptr->m_gridLinePen = pen;
576 emit gridLinePenChanged(pen);
576 emit gridLinePenChanged(pen);
577 }
577 }
578 }
578 }
579
579
580 /*!
580 /*!
581 Returns pen used to draw grid.
581 Returns pen used to draw grid.
582 */
582 */
583 QPen QAbstractAxis::gridLinePen() const
583 QPen QAbstractAxis::gridLinePen() const
584 {
584 {
585 if (d_ptr->m_gridLinePen == QChartPrivate::defaultPen())
585 if (d_ptr->m_gridLinePen == QChartPrivate::defaultPen())
586 return QPen();
586 return QPen();
587 else
587 else
588 return d_ptr->m_gridLinePen;
588 return d_ptr->m_gridLinePen;
589 }
589 }
590
590
591 void QAbstractAxis::setMinorGridLinePen(const QPen &pen)
591 void QAbstractAxis::setMinorGridLinePen(const QPen &pen)
592 {
592 {
593 if (d_ptr->m_minorGridLinePen != pen) {
593 if (d_ptr->m_minorGridLinePen != pen) {
594 d_ptr->m_minorGridLinePen = pen;
594 d_ptr->m_minorGridLinePen = pen;
595 emit minorGridLinePenChanged(pen);
595 emit minorGridLinePenChanged(pen);
596 }
596 }
597 }
597 }
598
598
599 QPen QAbstractAxis::minorGridLinePen() const
599 QPen QAbstractAxis::minorGridLinePen() const
600 {
600 {
601 if (d_ptr->m_minorGridLinePen == QChartPrivate::defaultPen())
601 if (d_ptr->m_minorGridLinePen == QChartPrivate::defaultPen())
602 return QPen();
602 return QPen();
603 else
603 else
604 return d_ptr->m_minorGridLinePen;
604 return d_ptr->m_minorGridLinePen;
605 }
605 }
606
606
607 void QAbstractAxis::setGridLineColor(const QColor &color)
607 void QAbstractAxis::setGridLineColor(const QColor &color)
608 {
608 {
609 QPen pen = d_ptr->m_gridLinePen;
609 QPen pen = d_ptr->m_gridLinePen;
610 if (color != pen.color()) {
610 if (color != pen.color()) {
611 pen.setColor(color);
611 pen.setColor(color);
612 d_ptr->m_gridLinePen = pen;
612 d_ptr->m_gridLinePen = pen;
613 emit gridLineColorChanged(color);
613 emit gridLineColorChanged(color);
614 }
614 }
615 }
615 }
616
616
617 QColor QAbstractAxis::gridLineColor()
617 QColor QAbstractAxis::gridLineColor()
618 {
618 {
619 return d_ptr->m_gridLinePen.color();
619 return d_ptr->m_gridLinePen.color();
620 }
620 }
621
621
622 void QAbstractAxis::setMinorGridLineColor(const QColor &color)
622 void QAbstractAxis::setMinorGridLineColor(const QColor &color)
623 {
623 {
624 QPen pen = d_ptr->m_minorGridLinePen;
624 QPen pen = d_ptr->m_minorGridLinePen;
625 if (color != pen.color()) {
625 if (color != pen.color()) {
626 pen.setColor(color);
626 pen.setColor(color);
627 d_ptr->m_minorGridLinePen = pen;
627 d_ptr->m_minorGridLinePen = pen;
628 emit minorGridLineColorChanged(color);
628 emit minorGridLineColorChanged(color);
629 }
629 }
630 }
630 }
631
631
632 QColor QAbstractAxis::minorGridLineColor()
632 QColor QAbstractAxis::minorGridLineColor()
633 {
633 {
634 return d_ptr->m_minorGridLinePen.color();
634 return d_ptr->m_minorGridLinePen.color();
635 }
635 }
636
636
637 void QAbstractAxis::setLabelsVisible(bool visible)
637 void QAbstractAxis::setLabelsVisible(bool visible)
638 {
638 {
639 if (d_ptr->m_labelsVisible != visible) {
639 if (d_ptr->m_labelsVisible != visible) {
640 d_ptr->m_labelsVisible = visible;
640 d_ptr->m_labelsVisible = visible;
641 emit labelsVisibleChanged(visible);
641 emit labelsVisibleChanged(visible);
642 }
642 }
643 }
643 }
644
644
645 bool QAbstractAxis::labelsVisible() const
645 bool QAbstractAxis::labelsVisible() const
646 {
646 {
647 return d_ptr->m_labelsVisible;
647 return d_ptr->m_labelsVisible;
648 }
648 }
649
649
650 /*!
650 /*!
651 Sets \a brush used to draw labels.
651 Sets \a brush used to draw labels.
652 */
652 */
653 void QAbstractAxis::setLabelsBrush(const QBrush &brush)
653 void QAbstractAxis::setLabelsBrush(const QBrush &brush)
654 {
654 {
655 if (d_ptr->m_labelsBrush != brush) {
655 if (d_ptr->m_labelsBrush != brush) {
656 d_ptr->m_labelsBrush = brush;
656 d_ptr->m_labelsBrush = brush;
657 emit labelsBrushChanged(brush);
657 emit labelsBrushChanged(brush);
658 }
658 }
659 }
659 }
660
660
661 /*!
661 /*!
662 Returns brush used to draw labels.
662 Returns brush used to draw labels.
663 */
663 */
664 QBrush QAbstractAxis::labelsBrush() const
664 QBrush QAbstractAxis::labelsBrush() const
665 {
665 {
666 if (d_ptr->m_labelsBrush == QChartPrivate::defaultBrush())
666 if (d_ptr->m_labelsBrush == QChartPrivate::defaultBrush())
667 return QBrush();
667 return QBrush();
668 else
668 else
669 return d_ptr->m_labelsBrush;
669 return d_ptr->m_labelsBrush;
670 }
670 }
671
671
672 /*!
672 /*!
673 Sets \a font used to draw labels.
673 Sets \a font used to draw labels.
674 */
674 */
675 void QAbstractAxis::setLabelsFont(const QFont &font)
675 void QAbstractAxis::setLabelsFont(const QFont &font)
676 {
676 {
677 if (d_ptr->m_labelsFont != font) {
677 if (d_ptr->m_labelsFont != font) {
678 d_ptr->m_labelsFont = font;
678 d_ptr->m_labelsFont = font;
679 emit labelsFontChanged(font);
679 emit labelsFontChanged(font);
680 }
680 }
681 }
681 }
682
682
683 /*!
683 /*!
684 Returns font used to draw labels.
684 Returns font used to draw labels.
685 */
685 */
686 QFont QAbstractAxis::labelsFont() const
686 QFont QAbstractAxis::labelsFont() const
687 {
687 {
688 if (d_ptr->m_labelsFont == QChartPrivate::defaultFont())
688 if (d_ptr->m_labelsFont == QChartPrivate::defaultFont())
689 return QFont();
689 return QFont();
690 else
690 else
691 return d_ptr->m_labelsFont;
691 return d_ptr->m_labelsFont;
692 }
692 }
693
693
694 void QAbstractAxis::setLabelsAngle(int angle)
694 void QAbstractAxis::setLabelsAngle(int angle)
695 {
695 {
696 if (d_ptr->m_labelsAngle != angle) {
696 if (d_ptr->m_labelsAngle != angle) {
697 d_ptr->m_labelsAngle = angle;
697 d_ptr->m_labelsAngle = angle;
698 emit labelsAngleChanged(angle);
698 emit labelsAngleChanged(angle);
699 }
699 }
700 }
700 }
701
701
702 int QAbstractAxis::labelsAngle() const
702 int QAbstractAxis::labelsAngle() const
703 {
703 {
704 return d_ptr->m_labelsAngle;
704 return d_ptr->m_labelsAngle;
705 }
705 }
706 void QAbstractAxis::setLabelsColor(QColor color)
706 void QAbstractAxis::setLabelsColor(QColor color)
707 {
707 {
708 QBrush b = d_ptr->m_labelsBrush;
708 QBrush b = d_ptr->m_labelsBrush;
709 if (b.color() != color) {
709 if (b.color() != color) {
710 b.setColor(color);
710 b.setColor(color);
711 setLabelsBrush(b);
711 setLabelsBrush(b);
712 emit labelsColorChanged(color);
712 emit labelsColorChanged(color);
713 }
713 }
714 }
714 }
715
715
716 QColor QAbstractAxis::labelsColor() const
716 QColor QAbstractAxis::labelsColor() const
717 {
717 {
718 return labelsBrush().color();
718 return labelsBrush().color();
719 }
719 }
720
720
721 void QAbstractAxis::setTitleVisible(bool visible)
721 void QAbstractAxis::setTitleVisible(bool visible)
722 {
722 {
723 if (d_ptr->m_titleVisible != visible) {
723 if (d_ptr->m_titleVisible != visible) {
724 d_ptr->m_titleVisible = visible;
724 d_ptr->m_titleVisible = visible;
725 emit titleVisibleChanged(visible);
725 emit titleVisibleChanged(visible);
726 }
726 }
727 }
727 }
728
728
729 bool QAbstractAxis::isTitleVisible() const
729 bool QAbstractAxis::isTitleVisible() const
730 {
730 {
731 return d_ptr->m_titleVisible;
731 return d_ptr->m_titleVisible;
732 }
732 }
733
733
734 /*!
734 /*!
735 Sets \a brush used to draw title.
735 Sets \a brush used to draw title.
736 */
736 */
737 void QAbstractAxis::setTitleBrush(const QBrush &brush)
737 void QAbstractAxis::setTitleBrush(const QBrush &brush)
738 {
738 {
739 if (d_ptr->m_titleBrush != brush) {
739 if (d_ptr->m_titleBrush != brush) {
740 d_ptr->m_titleBrush = brush;
740 d_ptr->m_titleBrush = brush;
741 emit titleBrushChanged(brush);
741 emit titleBrushChanged(brush);
742 }
742 }
743 }
743 }
744
744
745 /*!
745 /*!
746 Returns brush used to draw title.
746 Returns brush used to draw title.
747 */
747 */
748 QBrush QAbstractAxis::titleBrush() const
748 QBrush QAbstractAxis::titleBrush() const
749 {
749 {
750 if (d_ptr->m_titleBrush == QChartPrivate::defaultBrush())
750 if (d_ptr->m_titleBrush == QChartPrivate::defaultBrush())
751 return QBrush();
751 return QBrush();
752 else
752 else
753 return d_ptr->m_titleBrush;
753 return d_ptr->m_titleBrush;
754 }
754 }
755
755
756 /*!
756 /*!
757 Sets \a font used to draw title.
757 Sets \a font used to draw title.
758 */
758 */
759 void QAbstractAxis::setTitleFont(const QFont &font)
759 void QAbstractAxis::setTitleFont(const QFont &font)
760 {
760 {
761 if (d_ptr->m_titleFont != font) {
761 if (d_ptr->m_titleFont != font) {
762 d_ptr->m_titleFont = font;
762 d_ptr->m_titleFont = font;
763 emit titleFontChanged(font);
763 emit titleFontChanged(font);
764 }
764 }
765 }
765 }
766
766
767 /*!
767 /*!
768 Returns font used to draw title.
768 Returns font used to draw title.
769 */
769 */
770 QFont QAbstractAxis::titleFont() const
770 QFont QAbstractAxis::titleFont() const
771 {
771 {
772 if (d_ptr->m_titleFont == QChartPrivate::defaultFont())
772 if (d_ptr->m_titleFont == QChartPrivate::defaultFont())
773 return QFont();
773 return QFont();
774 else
774 else
775 return d_ptr->m_titleFont;
775 return d_ptr->m_titleFont;
776 }
776 }
777
777
778 void QAbstractAxis::setTitleText(const QString &title)
778 void QAbstractAxis::setTitleText(const QString &title)
779 {
779 {
780 if (d_ptr->m_title != title) {
780 if (d_ptr->m_title != title) {
781 d_ptr->m_title = title;
781 d_ptr->m_title = title;
782 emit titleTextChanged(title);
782 emit titleTextChanged(title);
783 }
783 }
784 }
784 }
785
785
786 QString QAbstractAxis::titleText() const
786 QString QAbstractAxis::titleText() const
787 {
787 {
788 return d_ptr->m_title;
788 return d_ptr->m_title;
789 }
789 }
790
790
791
791
792 void QAbstractAxis::setShadesVisible(bool visible)
792 void QAbstractAxis::setShadesVisible(bool visible)
793 {
793 {
794 if (d_ptr->m_shadesVisible != visible) {
794 if (d_ptr->m_shadesVisible != visible) {
795 d_ptr->m_shadesVisible = visible;
795 d_ptr->m_shadesVisible = visible;
796 emit shadesVisibleChanged(visible);
796 emit shadesVisibleChanged(visible);
797 }
797 }
798 }
798 }
799
799
800 bool QAbstractAxis::shadesVisible() const
800 bool QAbstractAxis::shadesVisible() const
801 {
801 {
802 return d_ptr->m_shadesVisible;
802 return d_ptr->m_shadesVisible;
803 }
803 }
804
804
805 /*!
805 /*!
806 Sets \a pen used to draw shades.
806 Sets \a pen used to draw shades.
807 */
807 */
808 void QAbstractAxis::setShadesPen(const QPen &pen)
808 void QAbstractAxis::setShadesPen(const QPen &pen)
809 {
809 {
810 if (d_ptr->m_shadesPen != pen) {
810 if (d_ptr->m_shadesPen != pen) {
811 d_ptr->m_shadesPen = pen;
811 d_ptr->m_shadesPen = pen;
812 emit shadesPenChanged(pen);
812 emit shadesPenChanged(pen);
813 }
813 }
814 }
814 }
815
815
816 /*!
816 /*!
817 Returns pen used to draw shades.
817 Returns pen used to draw shades.
818 */
818 */
819 QPen QAbstractAxis::shadesPen() const
819 QPen QAbstractAxis::shadesPen() const
820 {
820 {
821 if (d_ptr->m_shadesPen == QChartPrivate::defaultPen())
821 if (d_ptr->m_shadesPen == QChartPrivate::defaultPen())
822 return QPen();
822 return QPen();
823 else
823 else
824 return d_ptr->m_shadesPen;
824 return d_ptr->m_shadesPen;
825 }
825 }
826
826
827 /*!
827 /*!
828 Sets \a brush used to draw shades.
828 Sets \a brush used to draw shades.
829 */
829 */
830 void QAbstractAxis::setShadesBrush(const QBrush &brush)
830 void QAbstractAxis::setShadesBrush(const QBrush &brush)
831 {
831 {
832 if (d_ptr->m_shadesBrush != brush) {
832 if (d_ptr->m_shadesBrush != brush) {
833 d_ptr->m_shadesBrush = brush;
833 d_ptr->m_shadesBrush = brush;
834 emit shadesBrushChanged(brush);
834 emit shadesBrushChanged(brush);
835 }
835 }
836 }
836 }
837
837
838 /*!
838 /*!
839 Returns brush used to draw shades.
839 Returns brush used to draw shades.
840 */
840 */
841 QBrush QAbstractAxis::shadesBrush() const
841 QBrush QAbstractAxis::shadesBrush() const
842 {
842 {
843 if (d_ptr->m_shadesBrush == QChartPrivate::defaultBrush())
843 if (d_ptr->m_shadesBrush == QChartPrivate::defaultBrush())
844 return QBrush(Qt::SolidPattern);
844 return QBrush(Qt::SolidPattern);
845 else
845 else
846 return d_ptr->m_shadesBrush;
846 return d_ptr->m_shadesBrush;
847 }
847 }
848
848
849 void QAbstractAxis::setShadesColor(QColor color)
849 void QAbstractAxis::setShadesColor(QColor color)
850 {
850 {
851 QBrush b = d_ptr->m_shadesBrush;
851 QBrush b = d_ptr->m_shadesBrush;
852 if (b.color() != color) {
852 if (b.color() != color) {
853 b.setColor(color);
853 b.setColor(color);
854 setShadesBrush(b);
854 setShadesBrush(b);
855 emit shadesColorChanged(color);
855 emit shadesColorChanged(color);
856 }
856 }
857 }
857 }
858
858
859 QColor QAbstractAxis::shadesColor() const
859 QColor QAbstractAxis::shadesColor() const
860 {
860 {
861 return shadesBrush().color();
861 return shadesBrush().color();
862 }
862 }
863
863
864 void QAbstractAxis::setShadesBorderColor(QColor color)
864 void QAbstractAxis::setShadesBorderColor(QColor color)
865 {
865 {
866 QPen p = d_ptr->m_shadesPen;
866 QPen p = d_ptr->m_shadesPen;
867 if (p.color() != color) {
867 if (p.color() != color) {
868 p.setColor(color);
868 p.setColor(color);
869 setShadesPen(p);
869 setShadesPen(p);
870 emit shadesColorChanged(color);
870 emit shadesColorChanged(color);
871 }
871 }
872 }
872 }
873
873
874 QColor QAbstractAxis::shadesBorderColor() const
874 QColor QAbstractAxis::shadesBorderColor() const
875 {
875 {
876 return shadesPen().color();
876 return shadesPen().color();
877 }
877 }
878
878
879
879
880 bool QAbstractAxis::isVisible() const
880 bool QAbstractAxis::isVisible() const
881 {
881 {
882 return d_ptr->m_visible;
882 return d_ptr->m_visible;
883 }
883 }
884
884
885 /*!
885 /*!
886 Sets axis, shades, labels and grid lines to be visible.
886 Sets axis, shades, labels and grid lines visibility to \a visible.
887 */
887 */
888 void QAbstractAxis::setVisible(bool visible)
888 void QAbstractAxis::setVisible(bool visible)
889 {
889 {
890 if (d_ptr->m_visible != visible) {
890 if (d_ptr->m_visible != visible) {
891 d_ptr->m_visible = visible;
891 d_ptr->m_visible = visible;
892 emit visibleChanged(visible);
892 emit visibleChanged(visible);
893 }
893 }
894 }
894 }
895
895
896
896
897 /*!
897 /*!
898 Sets axis, shades, labels and grid lines to be visible.
898 Sets axis, shades, labels and grid lines to be visible.
899 */
899 */
900 void QAbstractAxis::show()
900 void QAbstractAxis::show()
901 {
901 {
902 setVisible(true);
902 setVisible(true);
903 }
903 }
904
904
905 /*!
905 /*!
906 Sets axis, shades, labels and grid lines to not be visible.
906 Sets axis, shades, labels and grid lines to not be visible.
907 */
907 */
908 void QAbstractAxis::hide()
908 void QAbstractAxis::hide()
909 {
909 {
910 setVisible(false);
910 setVisible(false);
911 }
911 }
912
912
913 /*!
913 /*!
914 Sets the minimum value shown on the axis.
914 Sets the minimum value shown on the axis.
915 Depending on the actual axis type the \a min parameter is converted to appropriate type.
915 Depending on the actual axis type the \a min parameter is converted to appropriate type.
916 If the conversion is impossible then the function call does nothing
916 If the conversion is impossible then the function call does nothing
917 */
917 */
918 void QAbstractAxis::setMin(const QVariant &min)
918 void QAbstractAxis::setMin(const QVariant &min)
919 {
919 {
920 d_ptr->setMin(min);
920 d_ptr->setMin(min);
921 }
921 }
922
922
923 /*!
923 /*!
924 Sets the maximum value shown on the axis.
924 Sets the maximum value shown on the axis.
925 Depending on the actual axis type the \a max parameter is converted to appropriate type.
925 Depending on the actual axis type the \a max parameter is converted to appropriate type.
926 If the conversion is impossible then the function call does nothing
926 If the conversion is impossible then the function call does nothing
927 */
927 */
928 void QAbstractAxis::setMax(const QVariant &max)
928 void QAbstractAxis::setMax(const QVariant &max)
929 {
929 {
930 d_ptr->setMax(max);
930 d_ptr->setMax(max);
931 }
931 }
932
932
933 /*!
933 /*!
934 Sets the range shown on the axis.
934 Sets the range shown on the axis.
935 Depending on the actual axis type the \a min and \a max parameters are converted to appropriate types.
935 Depending on the actual axis type the \a min and \a max parameters are converted to appropriate types.
936 If the conversion is impossible then the function call does nothing.
936 If the conversion is impossible then the function call does nothing.
937 */
937 */
938 void QAbstractAxis::setRange(const QVariant &min, const QVariant &max)
938 void QAbstractAxis::setRange(const QVariant &min, const QVariant &max)
939 {
939 {
940 d_ptr->setRange(min, max);
940 d_ptr->setRange(min, max);
941 }
941 }
942
942
943
943
944 /*!
944 /*!
945 Returns the orientation in which the axis is being used (Vertical or Horizontal)
945 Returns the orientation in which the axis is being used (Vertical or Horizontal)
946 */
946 */
947 Qt::Orientation QAbstractAxis::orientation() const
947 Qt::Orientation QAbstractAxis::orientation() const
948 {
948 {
949 return d_ptr->orientation();
949 return d_ptr->orientation();
950 }
950 }
951
951
952 Qt::Alignment QAbstractAxis::alignment() const
952 Qt::Alignment QAbstractAxis::alignment() const
953 {
953 {
954 return d_ptr->alignment();
954 return d_ptr->alignment();
955 }
955 }
956
956
957 bool QAbstractAxis::isReverse() const
957 bool QAbstractAxis::isReverse() const
958 {
958 {
959 return d_ptr->m_reverse;
959 return d_ptr->m_reverse;
960 }
960 }
961
961
962 void QAbstractAxis::setReverse(bool reverse)
962 void QAbstractAxis::setReverse(bool reverse)
963 {
963 {
964 if (d_ptr->m_reverse != reverse && type() != QAbstractAxis::AxisTypeBarCategory) {
964 if (d_ptr->m_reverse != reverse && type() != QAbstractAxis::AxisTypeBarCategory) {
965 d_ptr->m_reverse = reverse;
965 d_ptr->m_reverse = reverse;
966 emit reverseChanged(reverse);
966 emit reverseChanged(reverse);
967 }
967 }
968 }
968 }
969
969
970 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
970 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
971
971
972 QAbstractAxisPrivate::QAbstractAxisPrivate(QAbstractAxis *q)
972 QAbstractAxisPrivate::QAbstractAxisPrivate(QAbstractAxis *q)
973 : q_ptr(q),
973 : q_ptr(q),
974 m_chart(0),
974 m_chart(0),
975 m_alignment(0),
975 m_alignment(0),
976 m_orientation(Qt::Orientation(0)),
976 m_orientation(Qt::Orientation(0)),
977 m_visible(true),
977 m_visible(true),
978 m_arrowVisible(true),
978 m_arrowVisible(true),
979 m_axisPen(QChartPrivate::defaultPen()),
979 m_axisPen(QChartPrivate::defaultPen()),
980 m_axisBrush(QChartPrivate::defaultBrush()),
980 m_axisBrush(QChartPrivate::defaultBrush()),
981 m_gridLineVisible(true),
981 m_gridLineVisible(true),
982 m_gridLinePen(QChartPrivate::defaultPen()),
982 m_gridLinePen(QChartPrivate::defaultPen()),
983 m_minorGridLineVisible(true),
983 m_minorGridLineVisible(true),
984 m_minorGridLinePen(QChartPrivate::defaultPen()),
984 m_minorGridLinePen(QChartPrivate::defaultPen()),
985 m_labelsVisible(true),
985 m_labelsVisible(true),
986 m_labelsBrush(QChartPrivate::defaultBrush()),
986 m_labelsBrush(QChartPrivate::defaultBrush()),
987 m_labelsFont(QChartPrivate::defaultFont()),
987 m_labelsFont(QChartPrivate::defaultFont()),
988 m_labelsAngle(0),
988 m_labelsAngle(0),
989 m_titleVisible(true),
989 m_titleVisible(true),
990 m_titleBrush(QChartPrivate::defaultBrush()),
990 m_titleBrush(QChartPrivate::defaultBrush()),
991 m_titleFont(QChartPrivate::defaultFont()),
991 m_titleFont(QChartPrivate::defaultFont()),
992 m_shadesVisible(false),
992 m_shadesVisible(false),
993 m_shadesPen(QChartPrivate::defaultPen()),
993 m_shadesPen(QChartPrivate::defaultPen()),
994 m_shadesBrush(QChartPrivate::defaultBrush()),
994 m_shadesBrush(QChartPrivate::defaultBrush()),
995 m_shadesOpacity(1.0),
995 m_shadesOpacity(1.0),
996 m_dirty(false),
996 m_dirty(false),
997 m_reverse(false)
997 m_reverse(false)
998 {
998 {
999 }
999 }
1000
1000
1001 QAbstractAxisPrivate::~QAbstractAxisPrivate()
1001 QAbstractAxisPrivate::~QAbstractAxisPrivate()
1002 {
1002 {
1003 }
1003 }
1004
1004
1005 void QAbstractAxisPrivate::setAlignment( Qt::Alignment alignment)
1005 void QAbstractAxisPrivate::setAlignment( Qt::Alignment alignment)
1006 {
1006 {
1007 switch(alignment) {
1007 switch(alignment) {
1008 case Qt::AlignTop:
1008 case Qt::AlignTop:
1009 case Qt::AlignBottom:
1009 case Qt::AlignBottom:
1010 m_orientation = Qt::Horizontal;
1010 m_orientation = Qt::Horizontal;
1011 break;
1011 break;
1012 case Qt::AlignLeft:
1012 case Qt::AlignLeft:
1013 case Qt::AlignRight:
1013 case Qt::AlignRight:
1014 m_orientation = Qt::Vertical;
1014 m_orientation = Qt::Vertical;
1015 break;
1015 break;
1016 default:
1016 default:
1017 qWarning()<<"No alignment specified !";
1017 qWarning()<<"No alignment specified !";
1018 break;
1018 break;
1019 };
1019 };
1020 m_alignment=alignment;
1020 m_alignment=alignment;
1021 }
1021 }
1022
1022
1023 void QAbstractAxisPrivate::initializeTheme(ChartTheme* theme, bool forced)
1023 void QAbstractAxisPrivate::initializeTheme(ChartTheme* theme, bool forced)
1024 {
1024 {
1025 if (forced || QChartPrivate::defaultPen() == m_axisPen)
1025 if (forced || QChartPrivate::defaultPen() == m_axisPen)
1026 q_ptr->setLinePen(theme->axisLinePen());
1026 q_ptr->setLinePen(theme->axisLinePen());
1027
1027
1028 if (forced || QChartPrivate::defaultPen() == m_gridLinePen)
1028 if (forced || QChartPrivate::defaultPen() == m_gridLinePen)
1029 q_ptr->setGridLinePen(theme->gridLinePen());
1029 q_ptr->setGridLinePen(theme->gridLinePen());
1030 if (forced || QChartPrivate::defaultPen() == m_minorGridLinePen)
1030 if (forced || QChartPrivate::defaultPen() == m_minorGridLinePen)
1031 q_ptr->setMinorGridLinePen(theme->minorGridLinePen());
1031 q_ptr->setMinorGridLinePen(theme->minorGridLinePen());
1032
1032
1033 if (forced || QChartPrivate::defaultBrush() == m_labelsBrush)
1033 if (forced || QChartPrivate::defaultBrush() == m_labelsBrush)
1034 q_ptr->setLabelsBrush(theme->labelBrush());
1034 q_ptr->setLabelsBrush(theme->labelBrush());
1035 if (forced || QChartPrivate::defaultFont() == m_labelsFont)
1035 if (forced || QChartPrivate::defaultFont() == m_labelsFont)
1036 q_ptr->setLabelsFont(theme->labelFont());
1036 q_ptr->setLabelsFont(theme->labelFont());
1037
1037
1038 if (forced || QChartPrivate::defaultBrush() == m_titleBrush)
1038 if (forced || QChartPrivate::defaultBrush() == m_titleBrush)
1039 q_ptr->setTitleBrush(theme->labelBrush());
1039 q_ptr->setTitleBrush(theme->labelBrush());
1040 if (forced || QChartPrivate::defaultFont() == m_titleFont) {
1040 if (forced || QChartPrivate::defaultFont() == m_titleFont) {
1041 QFont font(m_labelsFont);
1041 QFont font(m_labelsFont);
1042 font.setBold(true);
1042 font.setBold(true);
1043 q_ptr->setTitleFont(font);
1043 q_ptr->setTitleFont(font);
1044 }
1044 }
1045
1045
1046 if (forced || QChartPrivate::defaultBrush() == m_shadesBrush)
1046 if (forced || QChartPrivate::defaultBrush() == m_shadesBrush)
1047 q_ptr->setShadesBrush(theme->backgroundShadesBrush());
1047 q_ptr->setShadesBrush(theme->backgroundShadesBrush());
1048 if (forced || QChartPrivate::defaultPen() == m_shadesPen)
1048 if (forced || QChartPrivate::defaultPen() == m_shadesPen)
1049 q_ptr->setShadesPen(theme->backgroundShadesPen());
1049 q_ptr->setShadesPen(theme->backgroundShadesPen());
1050
1050
1051 bool axisX = m_orientation == Qt::Horizontal;
1051 bool axisX = m_orientation == Qt::Horizontal;
1052 if (forced && (theme->backgroundShades() == ChartTheme::BackgroundShadesBoth
1052 if (forced && (theme->backgroundShades() == ChartTheme::BackgroundShadesBoth
1053 || (theme->backgroundShades() == ChartTheme::BackgroundShadesVertical && axisX)
1053 || (theme->backgroundShades() == ChartTheme::BackgroundShadesVertical && axisX)
1054 || (theme->backgroundShades() == ChartTheme::BackgroundShadesHorizontal && !axisX))) {
1054 || (theme->backgroundShades() == ChartTheme::BackgroundShadesHorizontal && !axisX))) {
1055 q_ptr->setShadesVisible(true);
1055 q_ptr->setShadesVisible(true);
1056 } else if (forced) {
1056 } else if (forced) {
1057 q_ptr->setShadesVisible(false);
1057 q_ptr->setShadesVisible(false);
1058 }
1058 }
1059 }
1059 }
1060
1060
1061 void QAbstractAxisPrivate::handleRangeChanged(qreal min, qreal max)
1061 void QAbstractAxisPrivate::handleRangeChanged(qreal min, qreal max)
1062 {
1062 {
1063 setRange(min,max);
1063 setRange(min,max);
1064 }
1064 }
1065
1065
1066 void QAbstractAxisPrivate::initializeGraphics(QGraphicsItem* parent)
1066 void QAbstractAxisPrivate::initializeGraphics(QGraphicsItem* parent)
1067 {
1067 {
1068 Q_UNUSED(parent);
1068 Q_UNUSED(parent);
1069 }
1069 }
1070
1070
1071 void QAbstractAxisPrivate::initializeAnimations(QChart::AnimationOptions options, int duration,
1071 void QAbstractAxisPrivate::initializeAnimations(QChart::AnimationOptions options, int duration,
1072 QEasingCurve &curve)
1072 QEasingCurve &curve)
1073 {
1073 {
1074 ChartAxisElement *axis = m_item.data();
1074 ChartAxisElement *axis = m_item.data();
1075 Q_ASSERT(axis);
1075 Q_ASSERT(axis);
1076 if (axis->animation())
1076 if (axis->animation())
1077 axis->animation()->stopAndDestroyLater();
1077 axis->animation()->stopAndDestroyLater();
1078
1078
1079 if (options.testFlag(QChart::GridAxisAnimations))
1079 if (options.testFlag(QChart::GridAxisAnimations))
1080 axis->setAnimation(new AxisAnimation(axis, duration, curve));
1080 axis->setAnimation(new AxisAnimation(axis, duration, curve));
1081 else
1081 else
1082 axis->setAnimation(0);
1082 axis->setAnimation(0);
1083 }
1083 }
1084
1084
1085
1085
1086
1086
1087 #include "moc_qabstractaxis.cpp"
1087 #include "moc_qabstractaxis.cpp"
1088 #include "moc_qabstractaxis_p.cpp"
1088 #include "moc_qabstractaxis_p.cpp"
1089
1089
1090 QT_CHARTS_END_NAMESPACE
1090 QT_CHARTS_END_NAMESPACE
@@ -1,688 +1,688
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <QtCharts/QBarSet>
19 #include <QtCharts/QBarSet>
20 #include <private/qbarset_p.h>
20 #include <private/qbarset_p.h>
21 #include <private/charthelpers_p.h>
21 #include <private/charthelpers_p.h>
22 #include <private/qchart_p.h>
22 #include <private/qchart_p.h>
23
23
24 QT_CHARTS_BEGIN_NAMESPACE
24 QT_CHARTS_BEGIN_NAMESPACE
25
25
26 /*!
26 /*!
27 \class QBarSet
27 \class QBarSet
28 \inmodule Qt Charts
28 \inmodule Qt Charts
29 \brief Building block for different bar charts.
29 \brief Building block for different bar charts.
30
30
31 QBarSet represents one set of bars. Set of bars contains one data value for each category.
31 QBarSet represents one set of bars. Set of bars contains one data value for each category.
32 First value of set is assumed to belong to first category, second to second category and so on.
32 First value of set is assumed to belong to first category, second to second category and so on.
33 If set has fewer values than there are categories, then the missing values are assumed to be
33 If set has fewer values than there are categories, then the missing values are assumed to be
34 at the end of set. For missing values in middle of a set, numerical value of zero is used.
34 at the end of set. For missing values in middle of a set, numerical value of zero is used.
35 Labels for zero value sets are not shown.
35 Labels for zero value sets are not shown.
36
36
37 \sa QAbstractBarSeries, QBarSeries, QStackedBarSeries, QPercentBarSeries
37 \sa QAbstractBarSeries, QBarSeries, QStackedBarSeries, QPercentBarSeries
38 */
38 */
39 /*!
39 /*!
40 \qmltype BarSet
40 \qmltype BarSet
41 \instantiates QBarSet
41 \instantiates QBarSet
42 \inqmlmodule QtCharts
42 \inqmlmodule QtCharts
43
43
44 \brief Building block for different bar charts.
44 \brief Building block for different bar charts.
45
45
46 BarSet represents one set of bars. Set of bars contains one data value for each category.
46 BarSet represents one set of bars. Set of bars contains one data value for each category.
47 First value of set is assumed to belong to first category, second to second category and so on.
47 First value of set is assumed to belong to first category, second to second category and so on.
48 If set has fewer values than there are categories, then the missing values are assumed to be
48 If set has fewer values than there are categories, then the missing values are assumed to be
49 at the end of set. For missing values in middle of a set, numerical value of zero is used.
49 at the end of set. For missing values in middle of a set, numerical value of zero is used.
50 Labels for zero value sets are not shown.
50 Labels for zero value sets are not shown.
51 \sa AbstractBarSeries, BarSeries, StackedBarSeries, PercentBarSeries
51 \sa AbstractBarSeries, BarSeries, StackedBarSeries, PercentBarSeries
52 */
52 */
53
53
54 /*!
54 /*!
55 \property QBarSet::label
55 \property QBarSet::label
56 Defines the label of the bar set.
56 Defines the label of the bar set.
57 */
57 */
58 /*!
58 /*!
59 \qmlproperty string BarSet::label
59 \qmlproperty string BarSet::label
60 Defines the label of the bar set.
60 Defines the label of the bar set.
61 */
61 */
62
62
63 /*!
63 /*!
64 \property QBarSet::pen
64 \property QBarSet::pen
65 \brief Defines the pen used by the bar set.
65 \brief Defines the pen used by the bar set.
66 */
66 */
67
67
68 /*!
68 /*!
69 \property QBarSet::brush
69 \property QBarSet::brush
70 \brief Defines the brush used by the bar set.
70 \brief Defines the brush used by the bar set.
71 */
71 */
72
72
73 /*!
73 /*!
74 \qmlproperty QString BarSet::brushFilename
74 \qmlproperty QString BarSet::brushFilename
75 The name of the file used as a brush for the set.
75 The name of the file used as a brush for the set.
76 */
76 */
77
77
78 /*!
78 /*!
79 \property QBarSet::labelBrush
79 \property QBarSet::labelBrush
80 \brief Defines the brush used by the bar set's label.
80 \brief Defines the brush used by the bar set's label.
81 */
81 */
82
82
83 /*!
83 /*!
84 \property QBarSet::labelFont
84 \property QBarSet::labelFont
85 \brief Defines the font used by the bar set's label.
85 \brief Defines the font used by the bar set's label.
86 */
86 */
87
87
88 /*!
88 /*!
89 \qmlproperty Font BarSet::labelFont
89 \qmlproperty Font BarSet::labelFont
90 Defines the font used by the bar set's label.
90 Defines the font used by the bar set's label.
91
91
92 See the Qt documentation for more details of Font.
92 See the Qt documentation for more details of Font.
93 */
93 */
94
94
95 /*!
95 /*!
96 \property QBarSet::color
96 \property QBarSet::color
97 The fill (brush) color of the bar set.
97 The fill (brush) color of the bar set.
98 */
98 */
99 /*!
99 /*!
100 \qmlproperty color BarSet::color
100 \qmlproperty color BarSet::color
101 The fill (brush) color of the bar set.
101 The fill (brush) color of the bar set.
102 */
102 */
103
103
104 /*!
104 /*!
105 \property QBarSet::borderColor
105 \property QBarSet::borderColor
106 The line (pen) color of the bar set.
106 The line (pen) color of the bar set.
107 */
107 */
108 /*!
108 /*!
109 \qmlproperty color BarSet::borderColor
109 \qmlproperty color BarSet::borderColor
110 The line (pen) color of the bar set.
110 The line (pen) color of the bar set.
111 */
111 */
112
112
113 /*!
113 /*!
114 \qmlproperty real BarSet::borderWidth
114 \qmlproperty real BarSet::borderWidth
115 The width of the border line. By default the width is 2.0.
115 The width of the border line. By default the width is 2.0.
116 */
116 */
117
117
118 /*!
118 /*!
119 \property QBarSet::labelColor
119 \property QBarSet::labelColor
120 The text (label) color of the bar set.
120 The text (label) color of the bar set.
121 */
121 */
122 /*!
122 /*!
123 \qmlproperty color BarSet::labelColor
123 \qmlproperty color BarSet::labelColor
124 The text (label) color of the bar set.
124 The text (label) color of the bar set.
125 */
125 */
126
126
127 /*!
127 /*!
128 \fn void QBarSet::clicked(int index)
128 \fn void QBarSet::clicked(int index)
129
129
130 The signal is emitted if the user clicks with a mouse on top of bar set.
130 The signal is emitted if the user clicks with a mouse on top of bar set.
131 Clicked bar inside set is indexed by \a index
131 Clicked bar inside set is indexed by \a index
132 */
132 */
133
133
134 /*!
134 /*!
135 \fn void QBarSet::pressed(int index)
135 \fn void QBarSet::pressed(int index)
136
136
137 The signal is emitted if the user presses with a mouse on top of bar set.
137 The signal is emitted if the user presses with a mouse on top of bar set.
138 Pressed bar inside set is indexed by \a index
138 Pressed bar inside set is indexed by \a index
139 */
139 */
140
140
141 /*!
141 /*!
142 \fn void QBarSet::released(int index)
142 \fn void QBarSet::released(int index)
143
143
144 The signal is emitted if the user releases with a mouse on top of bar set.
144 The signal is emitted if the user releases with a mouse on top of bar set.
145 Released bar inside set is indexed by \a index
145 Released bar inside set is indexed by \a index
146 */
146 */
147
147
148 /*!
148 /*!
149 \fn void QBarSet::doubleClicked(int index)
149 \fn void QBarSet::doubleClicked(int index)
150
150
151 The signal is emitted if the user doubleclicks with a mouse on top of bar set.
151 The signal is emitted if the user doubleclicks with a mouse on top of bar set.
152 Doubleclicked bar inside set is indexed by \a index
152 Doubleclicked bar inside set is indexed by \a index
153 */
153 */
154
154
155 /*!
155 /*!
156 \fn void QBarSet::hovered(bool status, int index)
156 \fn void QBarSet::hovered(bool status, int index)
157
157
158 The signal is emitted if mouse is hovered on top of bar set.
158 The signal is emitted if mouse is hovered on top of bar set.
159 Parameter \a status is true, if mouse entered on top of bar set, false if mouse left from top of bar set.
159 Parameter \a status is true, if mouse entered on top of bar set, false if mouse left from top of bar set.
160 Hovered bar inside the set is indexed by \a index.
160 Hovered bar inside the set is indexed by \a index.
161 */
161 */
162
162
163
163
164 /*!
164 /*!
165 \fn void QBarSet::labelChanged()
165 \fn void QBarSet::labelChanged()
166 This signal is emitted when the label of the bar set has changed.
166 This signal is emitted when the label of the bar set has changed.
167 \sa label
167 \sa label
168 */
168 */
169 /*!
169 /*!
170 \qmlsignal BarSet::onLabelChanged()
170 \qmlsignal BarSet::onLabelChanged()
171 This signal is emitted when the label of the bar set has changed.
171 This signal is emitted when the label of the bar set has changed.
172 */
172 */
173
173
174 /*!
174 /*!
175 \fn void QBarSet::penChanged()
175 \fn void QBarSet::penChanged()
176 This signal is emitted when the pen of the bar set has changed.
176 This signal is emitted when the pen of the bar set has changed.
177 \sa pen
177 \sa pen
178 */
178 */
179
179
180 /*!
180 /*!
181 \fn void QBarSet::brushChanged()
181 \fn void QBarSet::brushChanged()
182 This signal is emitted when the brush of the bar set has changed.
182 This signal is emitted when the brush of the bar set has changed.
183 \sa brush
183 \sa brush
184 */
184 */
185
185
186 /*!
186 /*!
187 \fn void QBarSet::labelBrushChanged()
187 \fn void QBarSet::labelBrushChanged()
188 This signal is emitted when the brush of the bar set's label has changed.
188 This signal is emitted when the brush of the bar set's label has changed.
189 \sa labelBrush
189 \sa labelBrush
190 */
190 */
191
191
192 /*!
192 /*!
193 \fn void QBarSet::labelFontChanged()
193 \fn void QBarSet::labelFontChanged()
194 This signal is emitted when the font of the bar set's label has changed.
194 This signal is emitted when the font of the bar set's label has changed.
195 \sa labelBrush
195 \sa labelBrush
196 */
196 */
197
197
198 /*!
198 /*!
199 \fn void QBarSet::colorChanged(QColor)
199 \fn void QBarSet::colorChanged(QColor)
200 This signal is emitted when the fill (brush) color of the set has changed to \a color.
200 This signal is emitted when the fill (brush) color of the set has changed to \a color.
201 */
201 */
202 /*!
202 /*!
203 \qmlsignal BarSet::onColorChanged(color color)
203 \qmlsignal BarSet::onColorChanged(color color)
204 This signal is emitted when the fill (brush) color of the set has changed to \a color.
204 This signal is emitted when the fill (brush) color of the set has changed to \a color.
205 */
205 */
206
206
207 /*!
207 /*!
208 \fn void QBarSet::borderColorChanged(QColor)
208 \fn void QBarSet::borderColorChanged(QColor)
209 This signal is emitted when the line (pen) color of the set has changed to \a color.
209 This signal is emitted when the line (pen) color of the set has changed to \a color.
210 */
210 */
211 /*!
211 /*!
212 \qmlsignal BarSet::onBorderColorChanged(color color)
212 \qmlsignal BarSet::onBorderColorChanged(color color)
213 This signal is emitted when the line (pen) color of the set has changed to \a color.
213 This signal is emitted when the line (pen) color of the set has changed to \a color.
214 */
214 */
215
215
216 /*!
216 /*!
217 \fn void QBarSet::labelColorChanged(QColor)
217 \fn void QBarSet::labelColorChanged(QColor)
218 This signal is emitted when the text (label) color of the set has changed to \a color.
218 This signal is emitted when the text (label) color of the set has changed to \a color.
219 */
219 */
220 /*!
220 /*!
221 \qmlsignal BarSet::onLabelColorChanged(color color)
221 \qmlsignal BarSet::onLabelColorChanged(color color)
222 This signal is emitted when the text (label) color of the set has changed to \a color.
222 This signal is emitted when the text (label) color of the set has changed to \a color.
223 */
223 */
224
224
225 /*!
225 /*!
226 \fn void QBarSet::valuesAdded(int index, int count)
226 \fn void QBarSet::valuesAdded(int index, int count)
227 This signal is emitted when new values have been added to the set.
227 This signal is emitted when new values have been added to the set.
228 Parameter \a index indicates the position of the first inserted value.
228 Parameter \a index indicates the position of the first inserted value.
229 Parameter \a count is the number of inserted values.
229 Parameter \a count is the number of inserted values.
230 \sa append(), insert()
230 \sa append(), insert()
231 */
231 */
232 /*!
232 /*!
233 \qmlsignal BarSet::onValuesAdded(int index, int count)
233 \qmlsignal BarSet::onValuesAdded(int index, int count)
234 This signal is emitted when new values have been added to the set.
234 This signal is emitted when new values have been added to the set.
235 Parameter \a index indicates the position of the first inserted value.
235 Parameter \a index indicates the position of the first inserted value.
236 Parameter \a count is the number of inserted values.
236 Parameter \a count is the number of inserted values.
237 */
237 */
238
238
239 /*!
239 /*!
240 \fn void QBarSet::valuesRemoved(int index, int count)
240 \fn void QBarSet::valuesRemoved(int index, int count)
241 This signal is emitted values have been removed from the set.
241 This signal is emitted values have been removed from the set.
242 Parameter \a index indicates the position of the first removed value.
242 Parameter \a index indicates the position of the first removed value.
243 Parameter \a count is the number of removed values.
243 Parameter \a count is the number of removed values.
244 \sa remove()
244 \sa remove()
245 */
245 */
246 /*!
246 /*!
247 \qmlsignal BarSet::onValuesRemoved(int index, int count)
247 \qmlsignal BarSet::onValuesRemoved(int index, int count)
248 This signal is emitted values have been removed from the set.
248 This signal is emitted values have been removed from the set.
249 Parameter \a index indicates the position of the first removed value.
249 Parameter \a index indicates the position of the first removed value.
250 Parameter \a count is the number of removed values.
250 Parameter \a count is the number of removed values.
251 */
251 */
252
252
253 /*!
253 /*!
254 \fn void QBarSet::valueChanged(int index)
254 \fn void QBarSet::valueChanged(int index)
255 This signal is emitted values the value in the set has been modified.
255 This signal is emitted values the value in the set has been modified.
256 Parameter \a index indicates the position of the modified value.
256 Parameter \a index indicates the position of the modified value.
257 \sa at()
257 \sa at()
258 */
258 */
259 /*!
259 /*!
260 \qmlsignal BarSet::onValueChanged(int index)
260 \qmlsignal BarSet::onValueChanged(int index)
261 This signal is emitted values the value in the set has been modified.
261 This signal is emitted values the value in the set has been modified.
262 Parameter \a index indicates the position of the modified value.
262 Parameter \a index indicates the position of the modified value.
263 */
263 */
264
264
265 /*!
265 /*!
266 \qmlproperty int BarSet::count
266 \qmlproperty int BarSet::count
267 The count of values on the bar set
267 The count of values on the bar set
268 */
268 */
269
269
270 /*!
270 /*!
271 \qmlproperty QVariantList BarSet::values
271 \qmlproperty QVariantList BarSet::values
272 The values of the bar set. You can set either a list of reals or a list of points as values. If you set a list of
272 The values of the bar set. You can set either a list of reals or a list of points as values. If you set a list of
273 reals as values, the values are automatically completed to points by using the index of a value as it's
273 reals as values, the values are automatically completed to points by using the index of a value as it's
274 x-coordinate. For example the following sets have equal values:
274 x-coordinate. For example the following sets have equal values:
275 \code
275 \code
276 myBarSet1.values = [0, 5, 1, 5];
276 myBarSet1.values = [0, 5, 1, 5];
277 myBarSet2.values = [Qt.point(0, 0), Qt.point(1, 5), Qt.point(2, 1), Qt.point(3, 5)];
277 myBarSet2.values = [Qt.point(0, 0), Qt.point(1, 5), Qt.point(2, 1), Qt.point(3, 5)];
278 \endcode
278 \endcode
279 */
279 */
280
280
281 /*!
281 /*!
282 Constructs QBarSet with a label of \a label and with parent of \a parent.
282 Constructs QBarSet with a label of \a label and with parent of \a parent.
283 */
283 */
284 QBarSet::QBarSet(const QString label, QObject *parent)
284 QBarSet::QBarSet(const QString label, QObject *parent)
285 : QObject(parent),
285 : QObject(parent),
286 d_ptr(new QBarSetPrivate(label, this))
286 d_ptr(new QBarSetPrivate(label, this))
287 {
287 {
288 }
288 }
289
289
290 /*!
290 /*!
291 Destroys the bar set.
291 Destroys the bar set.
292 */
292 */
293 QBarSet::~QBarSet()
293 QBarSet::~QBarSet()
294 {
294 {
295 // NOTE: d_ptr destroyed by QObject
295 // NOTE: d_ptr destroyed by QObject
296 }
296 }
297
297
298 /*!
298 /*!
299 Sets new \a label for set.
299 Sets new \a label for set.
300 */
300 */
301 void QBarSet::setLabel(const QString label)
301 void QBarSet::setLabel(const QString label)
302 {
302 {
303 d_ptr->m_label = label;
303 d_ptr->m_label = label;
304 emit labelChanged();
304 emit labelChanged();
305 }
305 }
306
306
307 /*!
307 /*!
308 Returns label of the set.
308 Returns label of the set.
309 */
309 */
310 QString QBarSet::label() const
310 QString QBarSet::label() const
311 {
311 {
312 return d_ptr->m_label;
312 return d_ptr->m_label;
313 }
313 }
314
314
315 /*!
315 /*!
316 Appends new value \a value to the end of set.
316 Appends new value \a value to the end of set.
317 */
317 */
318 void QBarSet::append(const qreal value)
318 void QBarSet::append(const qreal value)
319 {
319 {
320 // Convert to QPointF
320 // Convert to QPointF
321 int index = d_ptr->m_values.count();
321 int index = d_ptr->m_values.count();
322 d_ptr->append(QPointF(d_ptr->m_values.count(), value));
322 d_ptr->append(QPointF(d_ptr->m_values.count(), value));
323 emit valuesAdded(index, 1);
323 emit valuesAdded(index, 1);
324 }
324 }
325
325
326 /*!
326 /*!
327 Appends a list of reals to set. Works like append with single real value. The \a values in list
327 Appends a list of reals to set. Works like append with single real value. The \a values in list
328 are appended to end of bar set.
328 are appended to end of bar set.
329 \sa append()
329 \sa append()
330 */
330 */
331 void QBarSet::append(const QList<qreal> &values)
331 void QBarSet::append(const QList<qreal> &values)
332 {
332 {
333 int index = d_ptr->m_values.count();
333 int index = d_ptr->m_values.count();
334 d_ptr->append(values);
334 d_ptr->append(values);
335 emit valuesAdded(index, values.count());
335 emit valuesAdded(index, values.count());
336 }
336 }
337
337
338 /*!
338 /*!
339 Convenience operator. Same as append, with real \a value.
339 Convenience operator. Same as append, with real \a value.
340 \sa append()
340 \sa append()
341 */
341 */
342 QBarSet &QBarSet::operator << (const qreal &value)
342 QBarSet &QBarSet::operator << (const qreal &value)
343 {
343 {
344 append(value);
344 append(value);
345 return *this;
345 return *this;
346 }
346 }
347
347
348 /*!
348 /*!
349 Inserts new \a value on the \a index position.
349 Inserts new \a value on the \a index position.
350 The value that is currently at this postion is moved to position index + 1
350 The value that is currently at this postion is moved to position index + 1
351 \sa remove()
351 \sa remove()
352 */
352 */
353 void QBarSet::insert(const int index, const qreal value)
353 void QBarSet::insert(const int index, const qreal value)
354 {
354 {
355 d_ptr->insert(index, value);
355 d_ptr->insert(index, value);
356 emit valuesAdded(index, 1);
356 emit valuesAdded(index, 1);
357 }
357 }
358
358
359 /*!
359 /*!
360 Removes \a count number of values from the set starting at \a index.
360 Removes \a count number of values from the set starting at \a index.
361 \sa insert()
361 \sa insert()
362 */
362 */
363 void QBarSet::remove(const int index, const int count)
363 void QBarSet::remove(const int index, const int count)
364 {
364 {
365 int removedCount = d_ptr->remove(index, count);
365 int removedCount = d_ptr->remove(index, count);
366 if (removedCount > 0)
366 if (removedCount > 0)
367 emit valuesRemoved(index, removedCount);
367 emit valuesRemoved(index, removedCount);
368 return;
368 return;
369 }
369 }
370
370
371 /*!
371 /*!
372 Sets a new value \a value to set, indexed by \a index.
372 Sets a new value \a value to set, indexed by \a index.
373 */
373 */
374 void QBarSet::replace(const int index, const qreal value)
374 void QBarSet::replace(const int index, const qreal value)
375 {
375 {
376 if (index >= 0 && index < d_ptr->m_values.count()) {
376 if (index >= 0 && index < d_ptr->m_values.count()) {
377 d_ptr->replace(index, value);
377 d_ptr->replace(index, value);
378 emit valueChanged(index);
378 emit valueChanged(index);
379 }
379 }
380 }
380 }
381
381
382
382
383 /*!
383 /*!
384 Returns value of set indexed by \a index.
384 Returns value of set indexed by \a index.
385 If the index is out of bounds 0.0 is returned.
385 If the index is out of bounds 0.0 is returned.
386 */
386 */
387 qreal QBarSet::at(const int index) const
387 qreal QBarSet::at(const int index) const
388 {
388 {
389 if (index < 0 || index >= d_ptr->m_values.count())
389 if (index < 0 || index >= d_ptr->m_values.count())
390 return 0;
390 return 0;
391 return d_ptr->m_values.at(index).y();
391 return d_ptr->m_values.at(index).y();
392 }
392 }
393
393
394 /*!
394 /*!
395 Returns value of set indexed by \a index.
395 Returns value of set indexed by \a index.
396 If the index is out of bounds 0.0 is returned.
396 If the index is out of bounds 0.0 is returned.
397 */
397 */
398 qreal QBarSet::operator [](const int index) const
398 qreal QBarSet::operator [](const int index) const
399 {
399 {
400 return at(index);
400 return at(index);
401 }
401 }
402
402
403 /*!
403 /*!
404 Returns count of values in set.
404 Returns count of values in set.
405 */
405 */
406 int QBarSet::count() const
406 int QBarSet::count() const
407 {
407 {
408 return d_ptr->m_values.count();
408 return d_ptr->m_values.count();
409 }
409 }
410
410
411 /*!
411 /*!
412 Returns sum of all values in the bar set.
412 Returns sum of all values in the bar set.
413 */
413 */
414 qreal QBarSet::sum() const
414 qreal QBarSet::sum() const
415 {
415 {
416 qreal total(0);
416 qreal total(0);
417 for (int i = 0; i < d_ptr->m_values.count(); i++)
417 for (int i = 0; i < d_ptr->m_values.count(); i++)
418 total += d_ptr->m_values.at(i).y();
418 total += d_ptr->m_values.at(i).y();
419 return total;
419 return total;
420 }
420 }
421
421
422 /*!
422 /*!
423 Sets pen for set. Bars of this set are drawn using \a pen
423 Sets pen for set. Bars of this set are drawn using \a pen
424 */
424 */
425 void QBarSet::setPen(const QPen &pen)
425 void QBarSet::setPen(const QPen &pen)
426 {
426 {
427 if (d_ptr->m_pen != pen) {
427 if (d_ptr->m_pen != pen) {
428 d_ptr->m_pen = pen;
428 d_ptr->m_pen = pen;
429 emit d_ptr->updatedBars();
429 emit d_ptr->updatedBars();
430 emit penChanged();
430 emit penChanged();
431 }
431 }
432 }
432 }
433
433
434 /*!
434 /*!
435 Returns pen of the set.
435 Returns pen of the set.
436 */
436 */
437 QPen QBarSet::pen() const
437 QPen QBarSet::pen() const
438 {
438 {
439 if (d_ptr->m_pen == QChartPrivate::defaultPen())
439 if (d_ptr->m_pen == QChartPrivate::defaultPen())
440 return QPen();
440 return QPen();
441 else
441 else
442 return d_ptr->m_pen;
442 return d_ptr->m_pen;
443 }
443 }
444
444
445 /*!
445 /*!
446 Sets brush for the set. Bars of this set are drawn using \a brush.
446 Sets brush for the set. Bars of this set are drawn using \a brush.
447 */
447 */
448 void QBarSet::setBrush(const QBrush &brush)
448 void QBarSet::setBrush(const QBrush &brush)
449 {
449 {
450 if (d_ptr->m_brush != brush) {
450 if (d_ptr->m_brush != brush) {
451 d_ptr->m_brush = brush;
451 d_ptr->m_brush = brush;
452 emit d_ptr->updatedBars();
452 emit d_ptr->updatedBars();
453 emit brushChanged();
453 emit brushChanged();
454 }
454 }
455 }
455 }
456
456
457 /*!
457 /*!
458 Returns brush of the set.
458 Returns brush of the set.
459 */
459 */
460 QBrush QBarSet::brush() const
460 QBrush QBarSet::brush() const
461 {
461 {
462 if (d_ptr->m_brush == QChartPrivate::defaultBrush())
462 if (d_ptr->m_brush == QChartPrivate::defaultBrush())
463 return QBrush();
463 return QBrush();
464 else
464 else
465 return d_ptr->m_brush;
465 return d_ptr->m_brush;
466 }
466 }
467
467
468 /*!
468 /*!
469 Sets \a brush of the values that are drawn on top of this bar set.
469 Sets \a brush of the values that are drawn on top of this bar set.
470 */
470 */
471 void QBarSet::setLabelBrush(const QBrush &brush)
471 void QBarSet::setLabelBrush(const QBrush &brush)
472 {
472 {
473 if (d_ptr->m_labelBrush != brush) {
473 if (d_ptr->m_labelBrush != brush) {
474 d_ptr->m_labelBrush = brush;
474 d_ptr->m_labelBrush = brush;
475 emit d_ptr->updatedBars();
475 emit d_ptr->updatedBars();
476 emit labelBrushChanged();
476 emit labelBrushChanged();
477 }
477 }
478 }
478 }
479
479
480 /*!
480 /*!
481 Returns brush of the values that are drawn on top of this bar set.
481 Returns brush of the values that are drawn on top of this bar set.
482 */
482 */
483 QBrush QBarSet::labelBrush() const
483 QBrush QBarSet::labelBrush() const
484 {
484 {
485 if (d_ptr->m_labelBrush == QChartPrivate::defaultBrush())
485 if (d_ptr->m_labelBrush == QChartPrivate::defaultBrush())
486 return QBrush();
486 return QBrush();
487 else
487 else
488 return d_ptr->m_labelBrush;
488 return d_ptr->m_labelBrush;
489 }
489 }
490
490
491 /*!
491 /*!
492 Sets the \a font for values that are drawn on top of this bar set.
492 Sets the \a font for values that are drawn on top of this bar set.
493 */
493 */
494 void QBarSet::setLabelFont(const QFont &font)
494 void QBarSet::setLabelFont(const QFont &font)
495 {
495 {
496 if (d_ptr->m_labelFont != font) {
496 if (d_ptr->m_labelFont != font) {
497 d_ptr->m_labelFont = font;
497 d_ptr->m_labelFont = font;
498 emit d_ptr->updatedBars();
498 emit d_ptr->updatedBars();
499 emit labelFontChanged();
499 emit labelFontChanged();
500 }
500 }
501
501
502 }
502 }
503
503
504 /*!
504 /*!
505 Returns the pen for values that are drawn on top of this bar set.
505 Returns the pen for values that are drawn on top of this bar set.
506 */
506 */
507 QFont QBarSet::labelFont() const
507 QFont QBarSet::labelFont() const
508 {
508 {
509 return d_ptr->m_labelFont;
509 return d_ptr->m_labelFont;
510 }
510 }
511
511
512 /*!
512 /*!
513 Returns the color of the brush of bar set.
513 Returns the color of the brush of bar set.
514 */
514 */
515 QColor QBarSet::color()
515 QColor QBarSet::color()
516 {
516 {
517 return brush().color();
517 return brush().color();
518 }
518 }
519
519
520 /*!
520 /*!
521 Sets the \a color of brush for this bar set.
521 Sets the \a color of brush for this bar set.
522 */
522 */
523 void QBarSet::setColor(QColor color)
523 void QBarSet::setColor(QColor color)
524 {
524 {
525 QBrush b = brush();
525 QBrush b = brush();
526 if ((b.color() != color) || (b.style() == Qt::NoBrush)) {
526 if ((b.color() != color) || (b.style() == Qt::NoBrush)) {
527 b.setColor(color);
527 b.setColor(color);
528 if (b.style() == Qt::NoBrush) {
528 if (b.style() == Qt::NoBrush) {
529 // Set tyle to Qt::SolidPattern. (Default is Qt::NoBrush)
529 // Set tyle to Qt::SolidPattern. (Default is Qt::NoBrush)
530 // This prevents theme to override color defined in QML side:
530 // This prevents theme to override color defined in QML side:
531 // BarSet { label: "Bob"; color:"red"; values: [1,2,3] }
531 // BarSet { label: "Bob"; color:"red"; values: [1,2,3] }
532 // The color must be obeyed, since user wanted it.
532 // The color must be obeyed, since user wanted it.
533 b.setStyle(Qt::SolidPattern);
533 b.setStyle(Qt::SolidPattern);
534 }
534 }
535 setBrush(b);
535 setBrush(b);
536 emit colorChanged(color);
536 emit colorChanged(color);
537 }
537 }
538 }
538 }
539
539
540 /*!
540 /*!
541 Returns the color of pen of this bar set.
541 Returns the color of pen of this bar set.
542 */
542 */
543 QColor QBarSet::borderColor()
543 QColor QBarSet::borderColor()
544 {
544 {
545 return pen().color();
545 return pen().color();
546 }
546 }
547
547
548 /*!
548 /*!
549 Sets the color of pen for this bar set.
549 Sets the \a color of pen for this bar set.
550 */
550 */
551 void QBarSet::setBorderColor(QColor color)
551 void QBarSet::setBorderColor(QColor color)
552 {
552 {
553 QPen p = pen();
553 QPen p = pen();
554 if (p.color() != color) {
554 if (p.color() != color) {
555 p.setColor(color);
555 p.setColor(color);
556 setPen(p);
556 setPen(p);
557 emit borderColorChanged(color);
557 emit borderColorChanged(color);
558 }
558 }
559 }
559 }
560
560
561 /*!
561 /*!
562 Returns the color of labels of this bar set.
562 Returns the color of labels of this bar set.
563 */
563 */
564 QColor QBarSet::labelColor()
564 QColor QBarSet::labelColor()
565 {
565 {
566 return labelBrush().color();
566 return labelBrush().color();
567 }
567 }
568
568
569 /*!
569 /*!
570 Sets the color of labels for this bar set.
570 Sets the \a color of labels for this bar set.
571 */
571 */
572 void QBarSet::setLabelColor(QColor color)
572 void QBarSet::setLabelColor(QColor color)
573 {
573 {
574 QBrush b = labelBrush();
574 QBrush b = labelBrush();
575 if (b == QBrush())
575 if (b == QBrush())
576 b.setStyle(Qt::SolidPattern);
576 b.setStyle(Qt::SolidPattern);
577
577
578 if (d_ptr->m_labelBrush.color() != color) {
578 if (d_ptr->m_labelBrush.color() != color) {
579 b.setColor(color);
579 b.setColor(color);
580 setLabelBrush(b);
580 setLabelBrush(b);
581 emit labelColorChanged(color);
581 emit labelColorChanged(color);
582 }
582 }
583 }
583 }
584
584
585 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
585 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
586
586
587 QBarSetPrivate::QBarSetPrivate(const QString label, QBarSet *parent) : QObject(parent),
587 QBarSetPrivate::QBarSetPrivate(const QString label, QBarSet *parent) : QObject(parent),
588 q_ptr(parent),
588 q_ptr(parent),
589 m_label(label),
589 m_label(label),
590 m_pen(QChartPrivate::defaultPen()),
590 m_pen(QChartPrivate::defaultPen()),
591 m_brush(QChartPrivate::defaultBrush()),
591 m_brush(QChartPrivate::defaultBrush()),
592 m_labelBrush(QChartPrivate::defaultBrush())
592 m_labelBrush(QChartPrivate::defaultBrush())
593 {
593 {
594 }
594 }
595
595
596 QBarSetPrivate::~QBarSetPrivate()
596 QBarSetPrivate::~QBarSetPrivate()
597 {
597 {
598 }
598 }
599
599
600 void QBarSetPrivate::append(QPointF value)
600 void QBarSetPrivate::append(QPointF value)
601 {
601 {
602 if (isValidValue(value)) {
602 if (isValidValue(value)) {
603 m_values.append(value);
603 m_values.append(value);
604 emit restructuredBars();
604 emit restructuredBars();
605 }
605 }
606 }
606 }
607
607
608 void QBarSetPrivate::append(QList<QPointF> values)
608 void QBarSetPrivate::append(QList<QPointF> values)
609 {
609 {
610 for (int i = 0; i < values.count(); i++) {
610 for (int i = 0; i < values.count(); i++) {
611 if (isValidValue(values.at(i)))
611 if (isValidValue(values.at(i)))
612 m_values.append(values.at(i));
612 m_values.append(values.at(i));
613 }
613 }
614 emit restructuredBars();
614 emit restructuredBars();
615 }
615 }
616
616
617 void QBarSetPrivate::append(QList<qreal> values)
617 void QBarSetPrivate::append(QList<qreal> values)
618 {
618 {
619 int index = m_values.count();
619 int index = m_values.count();
620 for (int i = 0; i < values.count(); i++) {
620 for (int i = 0; i < values.count(); i++) {
621 if (isValidValue(values.at(i))) {
621 if (isValidValue(values.at(i))) {
622 m_values.append(QPointF(index, values.at(i)));
622 m_values.append(QPointF(index, values.at(i)));
623 index++;
623 index++;
624 }
624 }
625 }
625 }
626 emit restructuredBars();
626 emit restructuredBars();
627 }
627 }
628
628
629 void QBarSetPrivate::insert(const int index, const qreal value)
629 void QBarSetPrivate::insert(const int index, const qreal value)
630 {
630 {
631 m_values.insert(index, QPointF(index, value));
631 m_values.insert(index, QPointF(index, value));
632 emit restructuredBars();
632 emit restructuredBars();
633 }
633 }
634
634
635 void QBarSetPrivate::insert(const int index, const QPointF value)
635 void QBarSetPrivate::insert(const int index, const QPointF value)
636 {
636 {
637 m_values.insert(index, value);
637 m_values.insert(index, value);
638 emit restructuredBars();
638 emit restructuredBars();
639 }
639 }
640
640
641 int QBarSetPrivate::remove(const int index, const int count)
641 int QBarSetPrivate::remove(const int index, const int count)
642 {
642 {
643 int removeCount = count;
643 int removeCount = count;
644
644
645 if ((index < 0) || (m_values.count() == 0))
645 if ((index < 0) || (m_values.count() == 0))
646 return 0; // Invalid index or not values in list, remove nothing.
646 return 0; // Invalid index or not values in list, remove nothing.
647 else if ((index + count) > m_values.count())
647 else if ((index + count) > m_values.count())
648 removeCount = m_values.count() - index; // Trying to remove more items than list has. Limit amount to be removed.
648 removeCount = m_values.count() - index; // Trying to remove more items than list has. Limit amount to be removed.
649
649
650 int c = 0;
650 int c = 0;
651 while (c < removeCount) {
651 while (c < removeCount) {
652 m_values.removeAt(index);
652 m_values.removeAt(index);
653 c++;
653 c++;
654 }
654 }
655 emit restructuredBars();
655 emit restructuredBars();
656 return removeCount;
656 return removeCount;
657 }
657 }
658
658
659 void QBarSetPrivate::replace(const int index, const qreal value)
659 void QBarSetPrivate::replace(const int index, const qreal value)
660 {
660 {
661 m_values.replace(index, QPointF(index, value));
661 m_values.replace(index, QPointF(index, value));
662 emit updatedLayout();
662 emit updatedLayout();
663 }
663 }
664
664
665 void QBarSetPrivate::replace(const int index, const QPointF value)
665 void QBarSetPrivate::replace(const int index, const QPointF value)
666 {
666 {
667 m_values.replace(index, value);
667 m_values.replace(index, value);
668 emit updatedLayout();
668 emit updatedLayout();
669 }
669 }
670
670
671 qreal QBarSetPrivate::pos(const int index)
671 qreal QBarSetPrivate::pos(const int index)
672 {
672 {
673 if (index < 0 || index >= m_values.count())
673 if (index < 0 || index >= m_values.count())
674 return 0;
674 return 0;
675 return m_values.at(index).x();
675 return m_values.at(index).x();
676 }
676 }
677
677
678 qreal QBarSetPrivate::value(const int index)
678 qreal QBarSetPrivate::value(const int index)
679 {
679 {
680 if (index < 0 || index >= m_values.count())
680 if (index < 0 || index >= m_values.count())
681 return 0;
681 return 0;
682 return m_values.at(index).y();
682 return m_values.at(index).y();
683 }
683 }
684
684
685 #include "moc_qbarset.cpp"
685 #include "moc_qbarset.cpp"
686 #include "moc_qbarset_p.cpp"
686 #include "moc_qbarset_p.cpp"
687
687
688 QT_CHARTS_END_NAMESPACE
688 QT_CHARTS_END_NAMESPACE
@@ -1,631 +1,639
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/chartdataset_p.h>
19 #include <private/chartdataset_p.h>
20 #include <private/chartpresenter_p.h>
20 #include <private/chartpresenter_p.h>
21 #include <QtCharts/QChart>
21 #include <QtCharts/QChart>
22 #include <private/qchart_p.h>
22 #include <private/qchart_p.h>
23 #include <QtCharts/QValueAxis>
23 #include <QtCharts/QValueAxis>
24 #include <QtCharts/QBarCategoryAxis>
24 #include <QtCharts/QBarCategoryAxis>
25 #include <private/qvalueaxis_p.h>
25 #include <private/qvalueaxis_p.h>
26 #include <QtCharts/QCategoryAxis>
26 #include <QtCharts/QCategoryAxis>
27 #include <private/qabstractseries_p.h>
27 #include <private/qabstractseries_p.h>
28 #include <QtCharts/QAbstractBarSeries>
28 #include <QtCharts/QAbstractBarSeries>
29 #include <QtCharts/QStackedBarSeries>
29 #include <QtCharts/QStackedBarSeries>
30 #include <QtCharts/QPercentBarSeries>
30 #include <QtCharts/QPercentBarSeries>
31 #include <QtCharts/QPieSeries>
31 #include <QtCharts/QPieSeries>
32 #include <private/chartitem_p.h>
32 #include <private/chartitem_p.h>
33 #include <private/xydomain_p.h>
33 #include <private/xydomain_p.h>
34 #include <private/xypolardomain_p.h>
34 #include <private/xypolardomain_p.h>
35 #include <private/xlogydomain_p.h>
35 #include <private/xlogydomain_p.h>
36 #include <private/logxydomain_p.h>
36 #include <private/logxydomain_p.h>
37 #include <private/logxlogydomain_p.h>
37 #include <private/logxlogydomain_p.h>
38 #include <private/xlogypolardomain_p.h>
38 #include <private/xlogypolardomain_p.h>
39 #include <private/logxypolardomain_p.h>
39 #include <private/logxypolardomain_p.h>
40 #include <private/logxlogypolardomain_p.h>
40 #include <private/logxlogypolardomain_p.h>
41 #include <private/glxyseriesdata_p.h>
41
42
42 #ifndef QT_ON_ARM
43 #ifndef QT_ON_ARM
43 #include <QtCharts/QDateTimeAxis>
44 #include <QtCharts/QDateTimeAxis>
44 #endif
45 #endif
45
46
46 QT_CHARTS_BEGIN_NAMESPACE
47 QT_CHARTS_BEGIN_NAMESPACE
47
48
48 ChartDataSet::ChartDataSet(QChart *chart)
49 ChartDataSet::ChartDataSet(QChart *chart)
49 : QObject(chart),
50 : QObject(chart),
50 m_chart(chart)
51 m_chart(chart),
52 m_glXYSeriesDataManager(new GLXYSeriesDataManager(this))
51 {
53 {
52
54
53 }
55 }
54
56
55 ChartDataSet::~ChartDataSet()
57 ChartDataSet::~ChartDataSet()
56 {
58 {
57 deleteAllSeries();
59 deleteAllSeries();
58 deleteAllAxes();
60 deleteAllAxes();
59 }
61 }
60
62
61 /*
63 /*
62 * This method adds series to chartdataset, series ownership is taken from caller.
64 * This method adds series to chartdataset, series ownership is taken from caller.
63 */
65 */
64 void ChartDataSet::addSeries(QAbstractSeries *series)
66 void ChartDataSet::addSeries(QAbstractSeries *series)
65 {
67 {
66 if (m_seriesList.contains(series)) {
68 if (m_seriesList.contains(series)) {
67 qWarning() << QObject::tr("Can not add series. Series already on the chart.");
69 qWarning() << QObject::tr("Can not add series. Series already on the chart.");
68 return;
70 return;
69 }
71 }
70
72
71 // Ignore unsupported series added to polar chart
73 // Ignore unsupported series added to polar chart
72 if (m_chart && m_chart->chartType() == QChart::ChartTypePolar) {
74 if (m_chart && m_chart->chartType() == QChart::ChartTypePolar) {
73 if (!(series->type() == QAbstractSeries::SeriesTypeArea
75 if (!(series->type() == QAbstractSeries::SeriesTypeArea
74 || series->type() == QAbstractSeries::SeriesTypeLine
76 || series->type() == QAbstractSeries::SeriesTypeLine
75 || series->type() == QAbstractSeries::SeriesTypeScatter
77 || series->type() == QAbstractSeries::SeriesTypeScatter
76 || series->type() == QAbstractSeries::SeriesTypeSpline)) {
78 || series->type() == QAbstractSeries::SeriesTypeSpline)) {
77 qWarning() << QObject::tr("Can not add series. Series type is not supported by a polar chart.");
79 qWarning() << QObject::tr("Can not add series. Series type is not supported by a polar chart.");
78 return;
80 return;
79 }
81 }
82 // Disable OpenGL for series in polar charts
83 series->setUseOpenGL(false);
80 series->d_ptr->setDomain(new XYPolarDomain());
84 series->d_ptr->setDomain(new XYPolarDomain());
81 // Set the correct domain for upper and lower series too
85 // Set the correct domain for upper and lower series too
82 if (series->type() == QAbstractSeries::SeriesTypeArea) {
86 if (series->type() == QAbstractSeries::SeriesTypeArea) {
83 foreach (QObject *child, series->children()) {
87 foreach (QObject *child, series->children()) {
84 if (qobject_cast<QAbstractSeries *>(child)) {
88 if (qobject_cast<QAbstractSeries *>(child)) {
85 QAbstractSeries *childSeries = qobject_cast<QAbstractSeries *>(child);
89 QAbstractSeries *childSeries = qobject_cast<QAbstractSeries *>(child);
86 childSeries->d_ptr->setDomain(new XYPolarDomain());
90 childSeries->d_ptr->setDomain(new XYPolarDomain());
87 }
91 }
88 }
92 }
89 }
93 }
90 } else {
94 } else {
91 series->d_ptr->setDomain(new XYDomain());
95 series->d_ptr->setDomain(new XYDomain());
92 }
96 }
93
97
94 series->d_ptr->initializeDomain();
98 series->d_ptr->initializeDomain();
95 m_seriesList.append(series);
99 m_seriesList.append(series);
96
100
97 series->setParent(this); // take ownership
101 series->setParent(this); // take ownership
98 series->d_ptr->m_chart = m_chart;
102 series->d_ptr->m_chart = m_chart;
99
103
100 emit seriesAdded(series);
104 emit seriesAdded(series);
101 }
105 }
102
106
103 /*
107 /*
104 * This method adds axis to chartdataset, axis ownership is taken from caller.
108 * This method adds axis to chartdataset, axis ownership is taken from caller.
105 */
109 */
106 void ChartDataSet::addAxis(QAbstractAxis *axis, Qt::Alignment aligment)
110 void ChartDataSet::addAxis(QAbstractAxis *axis, Qt::Alignment aligment)
107 {
111 {
108 if (m_axisList.contains(axis)) {
112 if (m_axisList.contains(axis)) {
109 qWarning() << QObject::tr("Can not add axis. Axis already on the chart.");
113 qWarning() << QObject::tr("Can not add axis. Axis already on the chart.");
110 return;
114 return;
111 }
115 }
112
116
113 axis->d_ptr->setAlignment(aligment);
117 axis->d_ptr->setAlignment(aligment);
114
118
115 if (!axis->alignment()) {
119 if (!axis->alignment()) {
116 qWarning() << QObject::tr("No alignment specified !");
120 qWarning() << QObject::tr("No alignment specified !");
117 return;
121 return;
118 };
122 };
119
123
120 AbstractDomain *newDomain;
124 AbstractDomain *newDomain;
121 if (m_chart && m_chart->chartType() == QChart::ChartTypePolar)
125 if (m_chart && m_chart->chartType() == QChart::ChartTypePolar)
122 newDomain = new XYPolarDomain();
126 newDomain = new XYPolarDomain();
123 else
127 else
124 newDomain = new XYDomain();
128 newDomain = new XYDomain();
125
129
126 QSharedPointer<AbstractDomain> domain(newDomain);
130 QSharedPointer<AbstractDomain> domain(newDomain);
127 axis->d_ptr->initializeDomain(domain.data());
131 axis->d_ptr->initializeDomain(domain.data());
128
132
129 axis->setParent(this);
133 axis->setParent(this);
130 axis->d_ptr->m_chart = m_chart;
134 axis->d_ptr->m_chart = m_chart;
131 m_axisList.append(axis);
135 m_axisList.append(axis);
132
136
133 emit axisAdded(axis);
137 emit axisAdded(axis);
134 }
138 }
135
139
136 /*
140 /*
137 * This method removes series form chartdataset, series ownership is passed back to caller.
141 * This method removes series form chartdataset, series ownership is passed back to caller.
138 */
142 */
139 void ChartDataSet::removeSeries(QAbstractSeries *series)
143 void ChartDataSet::removeSeries(QAbstractSeries *series)
140 {
144 {
141
145
142 if (! m_seriesList.contains(series)) {
146 if (! m_seriesList.contains(series)) {
143 qWarning() << QObject::tr("Can not remove series. Series not found on the chart.");
147 qWarning() << QObject::tr("Can not remove series. Series not found on the chart.");
144 return;
148 return;
145 }
149 }
146
150
147 QList<QAbstractAxis*> axes = series->d_ptr->m_axes;
151 QList<QAbstractAxis*> axes = series->d_ptr->m_axes;
148
152
149 foreach(QAbstractAxis* axis, axes) {
153 foreach(QAbstractAxis* axis, axes) {
150 detachAxis(series,axis);
154 detachAxis(series,axis);
151 }
155 }
152
156
153 emit seriesRemoved(series);
157 emit seriesRemoved(series);
154 m_seriesList.removeAll(series);
158 m_seriesList.removeAll(series);
155
159
156 // Reset domain to default
160 // Reset domain to default
157 series->d_ptr->setDomain(new XYDomain());
161 series->d_ptr->setDomain(new XYDomain());
158 series->setParent(0);
162 series->setParent(0);
159 series->d_ptr->m_chart = 0;
163 series->d_ptr->m_chart = 0;
164
165 QXYSeries *xySeries = qobject_cast<QXYSeries *>(series);
166 if (xySeries)
167 m_glXYSeriesDataManager->removeSeries(xySeries);
160 }
168 }
161
169
162 /*
170 /*
163 * This method removes axis form chartdataset, series ownership is passed back to caller.
171 * This method removes axis form chartdataset, series ownership is passed back to caller.
164 */
172 */
165 void ChartDataSet::removeAxis(QAbstractAxis *axis)
173 void ChartDataSet::removeAxis(QAbstractAxis *axis)
166 {
174 {
167 if (! m_axisList.contains(axis)) {
175 if (! m_axisList.contains(axis)) {
168 qWarning() << QObject::tr("Can not remove axis. Axis not found on the chart.");
176 qWarning() << QObject::tr("Can not remove axis. Axis not found on the chart.");
169 return;
177 return;
170 }
178 }
171
179
172 QList<QAbstractSeries*> series = axis->d_ptr->m_series;
180 QList<QAbstractSeries*> series = axis->d_ptr->m_series;
173
181
174 foreach(QAbstractSeries* s, series) {
182 foreach(QAbstractSeries* s, series) {
175 detachAxis(s,axis);
183 detachAxis(s,axis);
176 }
184 }
177
185
178 emit axisRemoved(axis);
186 emit axisRemoved(axis);
179 m_axisList.removeAll(axis);
187 m_axisList.removeAll(axis);
180
188
181 axis->setParent(0);
189 axis->setParent(0);
182 axis->d_ptr->m_chart = 0;
190 axis->d_ptr->m_chart = 0;
183 }
191 }
184
192
185 /*
193 /*
186 * This method attaches axis to series, return true if success.
194 * This method attaches axis to series, return true if success.
187 */
195 */
188 bool ChartDataSet::attachAxis(QAbstractSeries *series,QAbstractAxis *axis)
196 bool ChartDataSet::attachAxis(QAbstractSeries *series,QAbstractAxis *axis)
189 {
197 {
190 Q_ASSERT(axis);
198 Q_ASSERT(axis);
191
199
192 if (!series)
200 if (!series)
193 return false;
201 return false;
194
202
195 QList<QAbstractSeries *> attachedSeriesList = axis->d_ptr->m_series;
203 QList<QAbstractSeries *> attachedSeriesList = axis->d_ptr->m_series;
196 QList<QAbstractAxis *> attachedAxisList = series->d_ptr->m_axes;
204 QList<QAbstractAxis *> attachedAxisList = series->d_ptr->m_axes;
197
205
198 if (!m_seriesList.contains(series)) {
206 if (!m_seriesList.contains(series)) {
199 qWarning() << QObject::tr("Can not find series on the chart.");
207 qWarning() << QObject::tr("Can not find series on the chart.");
200 return false;
208 return false;
201 }
209 }
202
210
203 if (axis && !m_axisList.contains(axis)) {
211 if (axis && !m_axisList.contains(axis)) {
204 qWarning() << QObject::tr("Can not find axis on the chart.");
212 qWarning() << QObject::tr("Can not find axis on the chart.");
205 return false;
213 return false;
206 }
214 }
207
215
208 if (attachedAxisList.contains(axis)) {
216 if (attachedAxisList.contains(axis)) {
209 qWarning() << QObject::tr("Axis already attached to series.");
217 qWarning() << QObject::tr("Axis already attached to series.");
210 return false;
218 return false;
211 }
219 }
212
220
213 if (attachedSeriesList.contains(series)) {
221 if (attachedSeriesList.contains(series)) {
214 qWarning() << QObject::tr("Axis already attached to series.");
222 qWarning() << QObject::tr("Axis already attached to series.");
215 return false;
223 return false;
216 }
224 }
217
225
218 AbstractDomain *domain = series->d_ptr->domain();
226 AbstractDomain *domain = series->d_ptr->domain();
219 AbstractDomain::DomainType type = selectDomain(attachedAxisList<<axis);
227 AbstractDomain::DomainType type = selectDomain(attachedAxisList<<axis);
220
228
221 if (type == AbstractDomain::UndefinedDomain) return false;
229 if (type == AbstractDomain::UndefinedDomain) return false;
222
230
223 if (domain->type() != type) {
231 if (domain->type() != type) {
224 AbstractDomain *old = domain;
232 AbstractDomain *old = domain;
225 domain = createDomain(type);
233 domain = createDomain(type);
226 domain->setRange(old->minX(), old->maxX(), old->minY(), old->maxY());
234 domain->setRange(old->minX(), old->maxX(), old->minY(), old->maxY());
227 // Initialize domain size to old domain size, as it won't get updated
235 // Initialize domain size to old domain size, as it won't get updated
228 // unless geometry changes.
236 // unless geometry changes.
229 domain->setSize(old->size());
237 domain->setSize(old->size());
230 }
238 }
231
239
232 if (!domain)
240 if (!domain)
233 return false;
241 return false;
234
242
235 if (!domain->attachAxis(axis))
243 if (!domain->attachAxis(axis))
236 return false;
244 return false;
237
245
238 QList<AbstractDomain *> blockedDomains;
246 QList<AbstractDomain *> blockedDomains;
239 domain->blockRangeSignals(true);
247 domain->blockRangeSignals(true);
240 blockedDomains << domain;
248 blockedDomains << domain;
241
249
242 if (domain != series->d_ptr->domain()) {
250 if (domain != series->d_ptr->domain()) {
243 foreach (QAbstractAxis *axis, series->d_ptr->m_axes) {
251 foreach (QAbstractAxis *axis, series->d_ptr->m_axes) {
244 series->d_ptr->domain()->detachAxis(axis);
252 series->d_ptr->domain()->detachAxis(axis);
245 domain->attachAxis(axis);
253 domain->attachAxis(axis);
246 foreach (QAbstractSeries *otherSeries, axis->d_ptr->m_series) {
254 foreach (QAbstractSeries *otherSeries, axis->d_ptr->m_series) {
247 if (otherSeries != series && otherSeries->d_ptr->domain()) {
255 if (otherSeries != series && otherSeries->d_ptr->domain()) {
248 if (!otherSeries->d_ptr->domain()->rangeSignalsBlocked()) {
256 if (!otherSeries->d_ptr->domain()->rangeSignalsBlocked()) {
249 otherSeries->d_ptr->domain()->blockRangeSignals(true);
257 otherSeries->d_ptr->domain()->blockRangeSignals(true);
250 blockedDomains << otherSeries->d_ptr->domain();
258 blockedDomains << otherSeries->d_ptr->domain();
251 }
259 }
252 }
260 }
253 }
261 }
254 }
262 }
255 series->d_ptr->setDomain(domain);
263 series->d_ptr->setDomain(domain);
256 series->d_ptr->initializeDomain();
264 series->d_ptr->initializeDomain();
257 }
265 }
258
266
259 series->d_ptr->m_axes<<axis;
267 series->d_ptr->m_axes<<axis;
260 axis->d_ptr->m_series<<series;
268 axis->d_ptr->m_series<<series;
261
269
262 series->d_ptr->initializeAxes();
270 series->d_ptr->initializeAxes();
263 axis->d_ptr->initializeDomain(domain);
271 axis->d_ptr->initializeDomain(domain);
264
272
265 foreach (AbstractDomain *blockedDomain, blockedDomains)
273 foreach (AbstractDomain *blockedDomain, blockedDomains)
266 blockedDomain->blockRangeSignals(false);
274 blockedDomain->blockRangeSignals(false);
267
275
268 return true;
276 return true;
269 }
277 }
270
278
271 /*
279 /*
272 * This method detaches axis to series, return true if success.
280 * This method detaches axis to series, return true if success.
273 */
281 */
274 bool ChartDataSet::detachAxis(QAbstractSeries* series,QAbstractAxis *axis)
282 bool ChartDataSet::detachAxis(QAbstractSeries* series,QAbstractAxis *axis)
275 {
283 {
276 Q_ASSERT(series);
284 Q_ASSERT(series);
277 Q_ASSERT(axis);
285 Q_ASSERT(axis);
278
286
279 QList<QAbstractSeries* > attachedSeriesList = axis->d_ptr->m_series;
287 QList<QAbstractSeries* > attachedSeriesList = axis->d_ptr->m_series;
280 QList<QAbstractAxis* > attachedAxisList = series->d_ptr->m_axes;
288 QList<QAbstractAxis* > attachedAxisList = series->d_ptr->m_axes;
281 AbstractDomain* domain = series->d_ptr->domain();
289 AbstractDomain* domain = series->d_ptr->domain();
282
290
283 if (!m_seriesList.contains(series)) {
291 if (!m_seriesList.contains(series)) {
284 qWarning() << QObject::tr("Can not find series on the chart.");
292 qWarning() << QObject::tr("Can not find series on the chart.");
285 return false;
293 return false;
286 }
294 }
287
295
288 if (axis && !m_axisList.contains(axis)) {
296 if (axis && !m_axisList.contains(axis)) {
289 qWarning() << QObject::tr("Can not find axis on the chart.");
297 qWarning() << QObject::tr("Can not find axis on the chart.");
290 return false;
298 return false;
291 }
299 }
292
300
293 if (!attachedAxisList.contains(axis)) {
301 if (!attachedAxisList.contains(axis)) {
294 qWarning() << QObject::tr("Axis not attached to series.");
302 qWarning() << QObject::tr("Axis not attached to series.");
295 return false;
303 return false;
296 }
304 }
297
305
298 Q_ASSERT(axis->d_ptr->m_series.contains(series));
306 Q_ASSERT(axis->d_ptr->m_series.contains(series));
299
307
300 domain->detachAxis(axis);
308 domain->detachAxis(axis);
301 series->d_ptr->m_axes.removeAll(axis);
309 series->d_ptr->m_axes.removeAll(axis);
302 axis->d_ptr->m_series.removeAll(series);
310 axis->d_ptr->m_series.removeAll(series);
303
311
304 return true;
312 return true;
305 }
313 }
306
314
307 void ChartDataSet::createDefaultAxes()
315 void ChartDataSet::createDefaultAxes()
308 {
316 {
309 if (m_seriesList.isEmpty())
317 if (m_seriesList.isEmpty())
310 return;
318 return;
311
319
312 QAbstractAxis::AxisTypes typeX(0);
320 QAbstractAxis::AxisTypes typeX(0);
313 QAbstractAxis::AxisTypes typeY(0);
321 QAbstractAxis::AxisTypes typeY(0);
314
322
315 // Remove possibly existing axes
323 // Remove possibly existing axes
316 deleteAllAxes();
324 deleteAllAxes();
317
325
318 Q_ASSERT(m_axisList.isEmpty());
326 Q_ASSERT(m_axisList.isEmpty());
319
327
320 // Select the required axis x and axis y types based on the types of the current series
328 // Select the required axis x and axis y types based on the types of the current series
321 foreach(QAbstractSeries* s, m_seriesList) {
329 foreach(QAbstractSeries* s, m_seriesList) {
322 typeX |= s->d_ptr->defaultAxisType(Qt::Horizontal);
330 typeX |= s->d_ptr->defaultAxisType(Qt::Horizontal);
323 typeY |= s->d_ptr->defaultAxisType(Qt::Vertical);
331 typeY |= s->d_ptr->defaultAxisType(Qt::Vertical);
324 }
332 }
325
333
326 createAxes(typeX, Qt::Horizontal);
334 createAxes(typeX, Qt::Horizontal);
327 createAxes(typeY, Qt::Vertical);
335 createAxes(typeY, Qt::Vertical);
328 }
336 }
329
337
330 void ChartDataSet::createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation)
338 void ChartDataSet::createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation)
331 {
339 {
332 QAbstractAxis *axis = 0;
340 QAbstractAxis *axis = 0;
333 //decide what axis should be created
341 //decide what axis should be created
334
342
335 switch (type) {
343 switch (type) {
336 case QAbstractAxis::AxisTypeValue:
344 case QAbstractAxis::AxisTypeValue:
337 axis = new QValueAxis(this);
345 axis = new QValueAxis(this);
338 break;
346 break;
339 case QAbstractAxis::AxisTypeBarCategory:
347 case QAbstractAxis::AxisTypeBarCategory:
340 axis = new QBarCategoryAxis(this);
348 axis = new QBarCategoryAxis(this);
341 break;
349 break;
342 case QAbstractAxis::AxisTypeCategory:
350 case QAbstractAxis::AxisTypeCategory:
343 axis = new QCategoryAxis(this);
351 axis = new QCategoryAxis(this);
344 break;
352 break;
345 #ifndef Q_WS_QWS
353 #ifndef Q_WS_QWS
346 case QAbstractAxis::AxisTypeDateTime:
354 case QAbstractAxis::AxisTypeDateTime:
347 axis = new QDateTimeAxis(this);
355 axis = new QDateTimeAxis(this);
348 break;
356 break;
349 #endif
357 #endif
350 default:
358 default:
351 axis = 0;
359 axis = 0;
352 break;
360 break;
353 }
361 }
354
362
355 if (axis) {
363 if (axis) {
356 //create one axis for all
364 //create one axis for all
357
365
358 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
366 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
359 qreal min = 0;
367 qreal min = 0;
360 qreal max = 0;
368 qreal max = 0;
361 findMinMaxForSeries(m_seriesList,orientation,min,max);
369 findMinMaxForSeries(m_seriesList,orientation,min,max);
362 foreach(QAbstractSeries *s, m_seriesList) {
370 foreach(QAbstractSeries *s, m_seriesList) {
363 attachAxis(s,axis);
371 attachAxis(s,axis);
364 }
372 }
365 axis->setRange(min,max);
373 axis->setRange(min,max);
366 } else {
374 } else {
367 // Create separate axis for each series
375 // Create separate axis for each series
368 foreach(QAbstractSeries *s, m_seriesList) {
376 foreach(QAbstractSeries *s, m_seriesList) {
369 QAbstractAxis *axis = s->d_ptr->createDefaultAxis(orientation);
377 QAbstractAxis *axis = s->d_ptr->createDefaultAxis(orientation);
370 if(axis) {
378 if(axis) {
371 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
379 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
372 attachAxis(s,axis);
380 attachAxis(s,axis);
373 }
381 }
374 }
382 }
375 }
383 }
376 }
384 }
377
385
378 void ChartDataSet::findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orientations orientation, qreal &min, qreal &max)
386 void ChartDataSet::findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orientations orientation, qreal &min, qreal &max)
379 {
387 {
380 Q_ASSERT(!series.isEmpty());
388 Q_ASSERT(!series.isEmpty());
381
389
382 AbstractDomain *domain = series.first()->d_ptr->domain();
390 AbstractDomain *domain = series.first()->d_ptr->domain();
383 min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
391 min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
384 max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
392 max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
385
393
386 for (int i = 1; i< series.size(); i++) {
394 for (int i = 1; i< series.size(); i++) {
387 AbstractDomain *domain = series[i]->d_ptr->domain();
395 AbstractDomain *domain = series[i]->d_ptr->domain();
388 min = qMin((orientation == Qt::Vertical) ? domain->minY() : domain->minX(), min);
396 min = qMin((orientation == Qt::Vertical) ? domain->minY() : domain->minX(), min);
389 max = qMax((orientation == Qt::Vertical) ? domain->maxY() : domain->maxX(), max);
397 max = qMax((orientation == Qt::Vertical) ? domain->maxY() : domain->maxX(), max);
390 }
398 }
391 if (min == max) {
399 if (min == max) {
392 min -= 0.5;
400 min -= 0.5;
393 max += 0.5;
401 max += 0.5;
394 }
402 }
395 }
403 }
396
404
397 void ChartDataSet::deleteAllSeries()
405 void ChartDataSet::deleteAllSeries()
398 {
406 {
399 foreach (QAbstractSeries *s , m_seriesList){
407 foreach (QAbstractSeries *s , m_seriesList){
400 removeSeries(s);
408 removeSeries(s);
401 s->deleteLater();
409 s->deleteLater();
402 }
410 }
403 Q_ASSERT(m_seriesList.count() == 0);
411 Q_ASSERT(m_seriesList.count() == 0);
404 }
412 }
405
413
406 void ChartDataSet::deleteAllAxes()
414 void ChartDataSet::deleteAllAxes()
407 {
415 {
408 foreach (QAbstractAxis *a , m_axisList){
416 foreach (QAbstractAxis *a , m_axisList){
409 removeAxis(a);
417 removeAxis(a);
410 a->deleteLater();
418 a->deleteLater();
411 }
419 }
412 Q_ASSERT(m_axisList.count() == 0);
420 Q_ASSERT(m_axisList.count() == 0);
413 }
421 }
414
422
415 void ChartDataSet::zoomInDomain(const QRectF &rect)
423 void ChartDataSet::zoomInDomain(const QRectF &rect)
416 {
424 {
417 QList<AbstractDomain*> domains;
425 QList<AbstractDomain*> domains;
418 foreach(QAbstractSeries *s, m_seriesList) {
426 foreach(QAbstractSeries *s, m_seriesList) {
419 AbstractDomain* domain = s->d_ptr->domain();
427 AbstractDomain* domain = s->d_ptr->domain();
420 s->d_ptr->m_domain->blockRangeSignals(true);
428 s->d_ptr->m_domain->blockRangeSignals(true);
421 domains<<domain;
429 domains<<domain;
422 }
430 }
423
431
424 foreach(AbstractDomain *domain, domains)
432 foreach(AbstractDomain *domain, domains)
425 domain->zoomIn(rect);
433 domain->zoomIn(rect);
426
434
427 foreach(AbstractDomain *domain, domains)
435 foreach(AbstractDomain *domain, domains)
428 domain->blockRangeSignals(false);
436 domain->blockRangeSignals(false);
429 }
437 }
430
438
431 void ChartDataSet::zoomOutDomain(const QRectF &rect)
439 void ChartDataSet::zoomOutDomain(const QRectF &rect)
432 {
440 {
433 QList<AbstractDomain*> domains;
441 QList<AbstractDomain*> domains;
434 foreach(QAbstractSeries *s, m_seriesList) {
442 foreach(QAbstractSeries *s, m_seriesList) {
435 AbstractDomain* domain = s->d_ptr->domain();
443 AbstractDomain* domain = s->d_ptr->domain();
436 s->d_ptr->m_domain->blockRangeSignals(true);
444 s->d_ptr->m_domain->blockRangeSignals(true);
437 domains<<domain;
445 domains<<domain;
438 }
446 }
439
447
440 foreach(AbstractDomain *domain, domains)
448 foreach(AbstractDomain *domain, domains)
441 domain->zoomOut(rect);
449 domain->zoomOut(rect);
442
450
443 foreach(AbstractDomain *domain, domains)
451 foreach(AbstractDomain *domain, domains)
444 domain->blockRangeSignals(false);
452 domain->blockRangeSignals(false);
445 }
453 }
446
454
447 void ChartDataSet::zoomResetDomain()
455 void ChartDataSet::zoomResetDomain()
448 {
456 {
449 QList<AbstractDomain*> domains;
457 QList<AbstractDomain*> domains;
450 foreach (QAbstractSeries *s, m_seriesList) {
458 foreach (QAbstractSeries *s, m_seriesList) {
451 AbstractDomain *domain = s->d_ptr->domain();
459 AbstractDomain *domain = s->d_ptr->domain();
452 s->d_ptr->m_domain->blockRangeSignals(true);
460 s->d_ptr->m_domain->blockRangeSignals(true);
453 domains << domain;
461 domains << domain;
454 }
462 }
455
463
456 foreach (AbstractDomain *domain, domains)
464 foreach (AbstractDomain *domain, domains)
457 domain->zoomReset();
465 domain->zoomReset();
458
466
459 foreach (AbstractDomain *domain, domains)
467 foreach (AbstractDomain *domain, domains)
460 domain->blockRangeSignals(false);
468 domain->blockRangeSignals(false);
461 }
469 }
462
470
463 bool ChartDataSet::isZoomedDomain()
471 bool ChartDataSet::isZoomedDomain()
464 {
472 {
465 foreach (QAbstractSeries *s, m_seriesList) {
473 foreach (QAbstractSeries *s, m_seriesList) {
466 if (s->d_ptr->domain()->isZoomed())
474 if (s->d_ptr->domain()->isZoomed())
467 return true;
475 return true;
468 }
476 }
469 return false;
477 return false;
470 }
478 }
471
479
472 void ChartDataSet::scrollDomain(qreal dx, qreal dy)
480 void ChartDataSet::scrollDomain(qreal dx, qreal dy)
473 {
481 {
474 QList<AbstractDomain*> domains;
482 QList<AbstractDomain*> domains;
475 foreach(QAbstractSeries *s, m_seriesList) {
483 foreach(QAbstractSeries *s, m_seriesList) {
476 AbstractDomain* domain = s->d_ptr->domain();
484 AbstractDomain* domain = s->d_ptr->domain();
477 s->d_ptr->m_domain->blockRangeSignals(true);
485 s->d_ptr->m_domain->blockRangeSignals(true);
478 domains<<domain;
486 domains<<domain;
479 }
487 }
480
488
481 foreach(AbstractDomain *domain, domains)
489 foreach(AbstractDomain *domain, domains)
482 domain->move(dx, dy);
490 domain->move(dx, dy);
483
491
484 foreach(AbstractDomain *domain, domains)
492 foreach(AbstractDomain *domain, domains)
485 domain->blockRangeSignals(false);
493 domain->blockRangeSignals(false);
486 }
494 }
487
495
488 QPointF ChartDataSet::mapToValue(const QPointF &position, QAbstractSeries *series)
496 QPointF ChartDataSet::mapToValue(const QPointF &position, QAbstractSeries *series)
489 {
497 {
490 QPointF point;
498 QPointF point;
491 if (series == 0 && !m_seriesList.isEmpty())
499 if (series == 0 && !m_seriesList.isEmpty())
492 series = m_seriesList.first();
500 series = m_seriesList.first();
493
501
494 if (series && series->type() == QAbstractSeries::SeriesTypePie)
502 if (series && series->type() == QAbstractSeries::SeriesTypePie)
495 return point;
503 return point;
496
504
497 if (series && m_seriesList.contains(series))
505 if (series && m_seriesList.contains(series))
498 point = series->d_ptr->m_domain->calculateDomainPoint(position - m_chart->plotArea().topLeft());
506 point = series->d_ptr->m_domain->calculateDomainPoint(position - m_chart->plotArea().topLeft());
499 return point;
507 return point;
500 }
508 }
501
509
502 QPointF ChartDataSet::mapToPosition(const QPointF &value, QAbstractSeries *series)
510 QPointF ChartDataSet::mapToPosition(const QPointF &value, QAbstractSeries *series)
503 {
511 {
504 QPointF point = m_chart->plotArea().topLeft();
512 QPointF point = m_chart->plotArea().topLeft();
505 if (series == 0 && !m_seriesList.isEmpty())
513 if (series == 0 && !m_seriesList.isEmpty())
506 series = m_seriesList.first();
514 series = m_seriesList.first();
507
515
508 if (series && series->type() == QAbstractSeries::SeriesTypePie)
516 if (series && series->type() == QAbstractSeries::SeriesTypePie)
509 return QPoint(0, 0);
517 return QPoint(0, 0);
510
518
511 bool ok;
519 bool ok;
512 if (series && m_seriesList.contains(series))
520 if (series && m_seriesList.contains(series))
513 point += series->d_ptr->m_domain->calculateGeometryPoint(value, ok);
521 point += series->d_ptr->m_domain->calculateGeometryPoint(value, ok);
514 return point;
522 return point;
515 }
523 }
516
524
517 QList<QAbstractAxis *> ChartDataSet::axes() const
525 QList<QAbstractAxis *> ChartDataSet::axes() const
518 {
526 {
519 return m_axisList;
527 return m_axisList;
520 }
528 }
521
529
522 QList<QAbstractSeries *> ChartDataSet::series() const
530 QList<QAbstractSeries *> ChartDataSet::series() const
523 {
531 {
524 return m_seriesList;
532 return m_seriesList;
525 }
533 }
526
534
527 AbstractDomain::DomainType ChartDataSet::selectDomain(QList<QAbstractAxis *> axes)
535 AbstractDomain::DomainType ChartDataSet::selectDomain(QList<QAbstractAxis *> axes)
528 {
536 {
529 enum Type {
537 enum Type {
530 Undefined = 0,
538 Undefined = 0,
531 LogType = 0x1,
539 LogType = 0x1,
532 ValueType = 0x2
540 ValueType = 0x2
533 };
541 };
534
542
535 int horizontal(Undefined);
543 int horizontal(Undefined);
536 int vertical(Undefined);
544 int vertical(Undefined);
537
545
538 // Assume cartesian chart type, unless chart is set
546 // Assume cartesian chart type, unless chart is set
539 QChart::ChartType chartType(QChart::ChartTypeCartesian);
547 QChart::ChartType chartType(QChart::ChartTypeCartesian);
540 if (m_chart)
548 if (m_chart)
541 chartType = m_chart->chartType();
549 chartType = m_chart->chartType();
542
550
543 foreach (QAbstractAxis *axis, axes)
551 foreach (QAbstractAxis *axis, axes)
544 {
552 {
545 switch (axis->type()) {
553 switch (axis->type()) {
546 case QAbstractAxis::AxisTypeLogValue:
554 case QAbstractAxis::AxisTypeLogValue:
547 if (axis->orientation() == Qt::Horizontal)
555 if (axis->orientation() == Qt::Horizontal)
548 horizontal |= LogType;
556 horizontal |= LogType;
549 if (axis->orientation() == Qt::Vertical)
557 if (axis->orientation() == Qt::Vertical)
550 vertical |= LogType;
558 vertical |= LogType;
551 break;
559 break;
552 case QAbstractAxis::AxisTypeValue:
560 case QAbstractAxis::AxisTypeValue:
553 case QAbstractAxis::AxisTypeBarCategory:
561 case QAbstractAxis::AxisTypeBarCategory:
554 case QAbstractAxis::AxisTypeCategory:
562 case QAbstractAxis::AxisTypeCategory:
555 case QAbstractAxis::AxisTypeDateTime:
563 case QAbstractAxis::AxisTypeDateTime:
556 if (axis->orientation() == Qt::Horizontal)
564 if (axis->orientation() == Qt::Horizontal)
557 horizontal |= ValueType;
565 horizontal |= ValueType;
558 if (axis->orientation() == Qt::Vertical)
566 if (axis->orientation() == Qt::Vertical)
559 vertical |= ValueType;
567 vertical |= ValueType;
560 break;
568 break;
561 default:
569 default:
562 qWarning() << "Undefined type";
570 qWarning() << "Undefined type";
563 break;
571 break;
564 }
572 }
565 }
573 }
566
574
567 if (vertical == Undefined)
575 if (vertical == Undefined)
568 vertical = ValueType;
576 vertical = ValueType;
569 if (horizontal == Undefined)
577 if (horizontal == Undefined)
570 horizontal = ValueType;
578 horizontal = ValueType;
571
579
572 if (vertical == ValueType && horizontal == ValueType) {
580 if (vertical == ValueType && horizontal == ValueType) {
573 if (chartType == QChart::ChartTypeCartesian)
581 if (chartType == QChart::ChartTypeCartesian)
574 return AbstractDomain::XYDomain;
582 return AbstractDomain::XYDomain;
575 else if (chartType == QChart::ChartTypePolar)
583 else if (chartType == QChart::ChartTypePolar)
576 return AbstractDomain::XYPolarDomain;
584 return AbstractDomain::XYPolarDomain;
577 }
585 }
578
586
579 if (vertical == LogType && horizontal == ValueType) {
587 if (vertical == LogType && horizontal == ValueType) {
580 if (chartType == QChart::ChartTypeCartesian)
588 if (chartType == QChart::ChartTypeCartesian)
581 return AbstractDomain::XLogYDomain;
589 return AbstractDomain::XLogYDomain;
582 if (chartType == QChart::ChartTypePolar)
590 if (chartType == QChart::ChartTypePolar)
583 return AbstractDomain::XLogYPolarDomain;
591 return AbstractDomain::XLogYPolarDomain;
584 }
592 }
585
593
586 if (vertical == ValueType && horizontal == LogType) {
594 if (vertical == ValueType && horizontal == LogType) {
587 if (chartType == QChart::ChartTypeCartesian)
595 if (chartType == QChart::ChartTypeCartesian)
588 return AbstractDomain::LogXYDomain;
596 return AbstractDomain::LogXYDomain;
589 else if (chartType == QChart::ChartTypePolar)
597 else if (chartType == QChart::ChartTypePolar)
590 return AbstractDomain::LogXYPolarDomain;
598 return AbstractDomain::LogXYPolarDomain;
591 }
599 }
592
600
593 if (vertical == LogType && horizontal == LogType) {
601 if (vertical == LogType && horizontal == LogType) {
594 if (chartType == QChart::ChartTypeCartesian)
602 if (chartType == QChart::ChartTypeCartesian)
595 return AbstractDomain::LogXLogYDomain;
603 return AbstractDomain::LogXLogYDomain;
596 else if (chartType == QChart::ChartTypePolar)
604 else if (chartType == QChart::ChartTypePolar)
597 return AbstractDomain::LogXLogYPolarDomain;
605 return AbstractDomain::LogXLogYPolarDomain;
598 }
606 }
599
607
600 return AbstractDomain::UndefinedDomain;
608 return AbstractDomain::UndefinedDomain;
601 }
609 }
602
610
603 //refactor create factory
611 //refactor create factory
604 AbstractDomain* ChartDataSet::createDomain(AbstractDomain::DomainType type)
612 AbstractDomain* ChartDataSet::createDomain(AbstractDomain::DomainType type)
605 {
613 {
606 switch (type)
614 switch (type)
607 {
615 {
608 case AbstractDomain::LogXLogYDomain:
616 case AbstractDomain::LogXLogYDomain:
609 return new LogXLogYDomain();
617 return new LogXLogYDomain();
610 case AbstractDomain::XYDomain:
618 case AbstractDomain::XYDomain:
611 return new XYDomain();
619 return new XYDomain();
612 case AbstractDomain::XLogYDomain:
620 case AbstractDomain::XLogYDomain:
613 return new XLogYDomain();
621 return new XLogYDomain();
614 case AbstractDomain::LogXYDomain:
622 case AbstractDomain::LogXYDomain:
615 return new LogXYDomain();
623 return new LogXYDomain();
616 case AbstractDomain::XYPolarDomain:
624 case AbstractDomain::XYPolarDomain:
617 return new XYPolarDomain();
625 return new XYPolarDomain();
618 case AbstractDomain::XLogYPolarDomain:
626 case AbstractDomain::XLogYPolarDomain:
619 return new XLogYPolarDomain();
627 return new XLogYPolarDomain();
620 case AbstractDomain::LogXYPolarDomain:
628 case AbstractDomain::LogXYPolarDomain:
621 return new LogXYPolarDomain();
629 return new LogXYPolarDomain();
622 case AbstractDomain::LogXLogYPolarDomain:
630 case AbstractDomain::LogXLogYPolarDomain:
623 return new LogXLogYPolarDomain();
631 return new LogXLogYPolarDomain();
624 default:
632 default:
625 return 0;
633 return 0;
626 }
634 }
627 }
635 }
628
636
629 #include "moc_chartdataset_p.cpp"
637 #include "moc_chartdataset_p.cpp"
630
638
631 QT_CHARTS_END_NAMESPACE
639 QT_CHARTS_END_NAMESPACE
@@ -1,92 +1,96
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 // W A R N I N G
19 // W A R N I N G
20 // -------------
20 // -------------
21 //
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
24 // version without notice, or even be removed.
25 //
25 //
26 // We mean it.
26 // We mean it.
27
27
28 #ifndef CHARTDATASET_P_H
28 #ifndef CHARTDATASET_P_H
29 #define CHARTDATASET_P_H
29 #define CHARTDATASET_P_H
30
30
31 #include <QtCharts/QAbstractSeries>
31 #include <QtCharts/QAbstractSeries>
32 #include <private/abstractdomain_p.h>
32 #include <private/abstractdomain_p.h>
33 #include <private/qabstractaxis_p.h>
33 #include <private/qabstractaxis_p.h>
34 #include <QtCore/QVector>
34 #include <QtCore/QVector>
35
35
36 QT_CHARTS_BEGIN_NAMESPACE
36 QT_CHARTS_BEGIN_NAMESPACE
37
37
38 class QAbstractAxis;
38 class QAbstractAxis;
39 class ChartPresenter;
39 class ChartPresenter;
40 class GLXYSeriesDataManager;
40
41
41 class QT_CHARTS_AUTOTEST_EXPORT ChartDataSet : public QObject
42 class QT_CHARTS_AUTOTEST_EXPORT ChartDataSet : public QObject
42 {
43 {
43 Q_OBJECT
44 Q_OBJECT
44 public:
45 public:
45 ChartDataSet(QChart *chart);
46 ChartDataSet(QChart *chart);
46 virtual ~ChartDataSet();
47 virtual ~ChartDataSet();
47
48
48 void addSeries(QAbstractSeries *series);
49 void addSeries(QAbstractSeries *series);
49 void removeSeries(QAbstractSeries *series);
50 void removeSeries(QAbstractSeries *series);
50 QList<QAbstractSeries *> series() const;
51 QList<QAbstractSeries *> series() const;
51
52
52 void addAxis(QAbstractAxis *axis,Qt::Alignment aligment);
53 void addAxis(QAbstractAxis *axis,Qt::Alignment aligment);
53 void removeAxis(QAbstractAxis *axis);
54 void removeAxis(QAbstractAxis *axis);
54 QList<QAbstractAxis*> axes() const;
55 QList<QAbstractAxis*> axes() const;
55
56
56 bool attachAxis(QAbstractSeries* series,QAbstractAxis *axis);
57 bool attachAxis(QAbstractSeries* series,QAbstractAxis *axis);
57 bool detachAxis(QAbstractSeries* series,QAbstractAxis *axis);
58 bool detachAxis(QAbstractSeries* series,QAbstractAxis *axis);
58
59
59 void createDefaultAxes();
60 void createDefaultAxes();
60
61
61 void zoomInDomain(const QRectF &rect);
62 void zoomInDomain(const QRectF &rect);
62 void zoomOutDomain(const QRectF &rect);
63 void zoomOutDomain(const QRectF &rect);
63 void zoomResetDomain();
64 void zoomResetDomain();
64 bool isZoomedDomain();
65 bool isZoomedDomain();
65 void scrollDomain(qreal dx, qreal dy);
66 void scrollDomain(qreal dx, qreal dy);
66
67
67 QPointF mapToValue(const QPointF &position, QAbstractSeries *series = 0);
68 QPointF mapToValue(const QPointF &position, QAbstractSeries *series = 0);
68 QPointF mapToPosition(const QPointF &value, QAbstractSeries *series = 0);
69 QPointF mapToPosition(const QPointF &value, QAbstractSeries *series = 0);
69
70
71 GLXYSeriesDataManager *glXYSeriesDataManager() { return m_glXYSeriesDataManager; }
72
70 Q_SIGNALS:
73 Q_SIGNALS:
71 void axisAdded(QAbstractAxis* axis);
74 void axisAdded(QAbstractAxis* axis);
72 void axisRemoved(QAbstractAxis* axis);
75 void axisRemoved(QAbstractAxis* axis);
73 void seriesAdded(QAbstractSeries* series);
76 void seriesAdded(QAbstractSeries* series);
74 void seriesRemoved(QAbstractSeries* series);
77 void seriesRemoved(QAbstractSeries* series);
75
78
76 private:
79 private:
77 void createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation);
80 void createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation);
78 QAbstractAxis *createAxis(QAbstractAxis::AxisType type, Qt::Orientation orientation);
81 QAbstractAxis *createAxis(QAbstractAxis::AxisType type, Qt::Orientation orientation);
79 AbstractDomain::DomainType selectDomain(QList<QAbstractAxis* > axes);
82 AbstractDomain::DomainType selectDomain(QList<QAbstractAxis* > axes);
80 AbstractDomain* createDomain(AbstractDomain::DomainType type);
83 AbstractDomain* createDomain(AbstractDomain::DomainType type);
81 void deleteAllAxes();
84 void deleteAllAxes();
82 void deleteAllSeries();
85 void deleteAllSeries();
83 void findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orientations orientation, qreal &min, qreal &max);
86 void findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orientations orientation, qreal &min, qreal &max);
84 private:
87 private:
85 QList<QAbstractSeries *> m_seriesList;
88 QList<QAbstractSeries *> m_seriesList;
86 QList<QAbstractAxis *> m_axisList;
89 QList<QAbstractAxis *> m_axisList;
87 QChart* m_chart;
90 QChart* m_chart;
91 GLXYSeriesDataManager *m_glXYSeriesDataManager;
88 };
92 };
89
93
90 QT_CHARTS_END_NAMESPACE
94 QT_CHARTS_END_NAMESPACE
91
95
92 #endif /* CHARTENGINE_P_H */
96 #endif /* CHARTENGINE_P_H */
@@ -1,53 +1,65
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/chartelement_p.h>
19 #include <private/chartelement_p.h>
20 #include <private/chartpresenter_p.h>
20 #include <private/chartpresenter_p.h>
21 #include <private/abstractdomain_p.h>
21 #include <private/abstractdomain_p.h>
22 #include <private/chartdataset_p.h>
22
23
23 QT_CHARTS_BEGIN_NAMESPACE
24 QT_CHARTS_BEGIN_NAMESPACE
24
25
25 ChartElement::ChartElement(QGraphicsItem* item):
26 ChartElement::ChartElement(QGraphicsItem* item):
26 QGraphicsObject(item),
27 QGraphicsObject(item),
27 m_presenter(0),
28 m_presenter(0),
28 m_themeManager(0)
29 m_themeManager(0),
30 m_dataSet(0)
29 {
31 {
30
32
31 }
33 }
32
34
33 void ChartElement::setPresenter(ChartPresenter *presenter)
35 void ChartElement::setPresenter(ChartPresenter *presenter)
34 {
36 {
35 m_presenter = presenter;
37 m_presenter = presenter;
36 }
38 }
37
39
38 ChartPresenter *ChartElement::presenter() const
40 ChartPresenter *ChartElement::presenter() const
39 {
41 {
40 return m_presenter;
42 return m_presenter;
41 }
43 }
42
44
43 void ChartElement::setThemeManager(ChartThemeManager *manager)
45 void ChartElement::setThemeManager(ChartThemeManager *manager)
44 {
46 {
45 m_themeManager = manager;
47 m_themeManager = manager;
46 }
48 }
47
49
48 ChartThemeManager* ChartElement::themeManager() const
50 ChartThemeManager* ChartElement::themeManager() const
49 {
51 {
50 return m_themeManager;
52 return m_themeManager;
51 }
53 }
52
54
55 void ChartElement::setDataSet(ChartDataSet *dataSet)
56 {
57 m_dataSet = dataSet;
58 }
59
60 ChartDataSet *ChartElement::dataSet() const
61 {
62 return m_dataSet;
63 }
64
53 QT_CHARTS_END_NAMESPACE
65 QT_CHARTS_END_NAMESPACE
@@ -1,63 +1,67
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 // W A R N I N G
19 // W A R N I N G
20 // -------------
20 // -------------
21 //
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
24 // version without notice, or even be removed.
25 //
25 //
26 // We mean it.
26 // We mean it.
27
27
28 #ifndef CHARTELEMENT_H
28 #ifndef CHARTELEMENT_H
29 #define CHARTELEMENT_H
29 #define CHARTELEMENT_H
30
30
31 #include <QtCharts/QChartGlobal>
31 #include <QtCharts/QChartGlobal>
32 #include <QtCore/QObject>
32 #include <QtCore/QObject>
33 #include <QtCore/QRect>
33 #include <QtCore/QRect>
34 #include <QGraphicsObject>
34 #include <QGraphicsObject>
35
35
36 QT_CHARTS_BEGIN_NAMESPACE
36 QT_CHARTS_BEGIN_NAMESPACE
37
37
38 class ChartAnimator;
38 class ChartAnimator;
39 class ChartPresenter;
39 class ChartPresenter;
40 class ChartAnimation;
40 class ChartAnimation;
41 class ChartThemeManager;
41 class ChartThemeManager;
42 class AbstractDomain;
42 class AbstractDomain;
43 class ChartDataSet;
43
44
44 class ChartElement: public QGraphicsObject
45 class ChartElement: public QGraphicsObject
45 {
46 {
46
47
47 public:
48 public:
48 explicit ChartElement(QGraphicsItem* item = 0);
49 explicit ChartElement(QGraphicsItem* item = 0);
49
50
50 virtual ChartAnimation *animation() const { return 0; }
51 virtual ChartAnimation *animation() const { return 0; }
51 virtual void setPresenter(ChartPresenter *presenter);
52 virtual void setPresenter(ChartPresenter *presenter);
52 ChartPresenter *presenter() const;
53 ChartPresenter *presenter() const;
53 virtual void setThemeManager(ChartThemeManager *manager);
54 virtual void setThemeManager(ChartThemeManager *manager);
54 ChartThemeManager* themeManager() const;
55 ChartThemeManager* themeManager() const;
56 virtual void setDataSet(ChartDataSet *dataSet);
57 ChartDataSet *dataSet() const;
55
58
56 private:
59 private:
57 ChartPresenter *m_presenter;
60 ChartPresenter *m_presenter;
58 ChartThemeManager *m_themeManager;
61 ChartThemeManager *m_themeManager;
62 ChartDataSet *m_dataSet;
59 };
63 };
60
64
61 QT_CHARTS_END_NAMESPACE
65 QT_CHARTS_END_NAMESPACE
62
66
63 #endif
67 #endif
@@ -1,536 +1,569
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18 #include <private/chartpresenter_p.h>
18 #include <private/chartpresenter_p.h>
19 #include <QtCharts/QChart>
19 #include <QtCharts/QChart>
20 #include <private/chartitem_p.h>
20 #include <private/chartitem_p.h>
21 #include <private/qchart_p.h>
21 #include <private/qchart_p.h>
22 #include <QtCharts/QAbstractAxis>
22 #include <QtCharts/QAbstractAxis>
23 #include <private/qabstractaxis_p.h>
23 #include <private/qabstractaxis_p.h>
24 #include <private/chartdataset_p.h>
24 #include <private/chartdataset_p.h>
25 #include <private/chartanimation_p.h>
25 #include <private/chartanimation_p.h>
26 #include <private/qabstractseries_p.h>
26 #include <private/qabstractseries_p.h>
27 #include <QtCharts/QAreaSeries>
27 #include <QtCharts/QAreaSeries>
28 #include <private/chartaxiselement_p.h>
28 #include <private/chartaxiselement_p.h>
29 #include <private/chartbackground_p.h>
29 #include <private/chartbackground_p.h>
30 #include <private/cartesianchartlayout_p.h>
30 #include <private/cartesianchartlayout_p.h>
31 #include <private/polarchartlayout_p.h>
31 #include <private/polarchartlayout_p.h>
32 #include <private/charttitle_p.h>
32 #include <private/charttitle_p.h>
33 #include <QtCore/QTimer>
33 #include <QtCore/QTimer>
34 #include <QtGui/QTextDocument>
34 #include <QtGui/QTextDocument>
35
35
36 QT_CHARTS_BEGIN_NAMESPACE
36 QT_CHARTS_BEGIN_NAMESPACE
37
37
38 ChartPresenter::ChartPresenter(QChart *chart, QChart::ChartType type)
38 ChartPresenter::ChartPresenter(QChart *chart, QChart::ChartType type)
39 : QObject(chart),
39 : QObject(chart),
40 m_chart(chart),
40 m_chart(chart),
41 m_options(QChart::NoAnimation),
41 m_options(QChart::NoAnimation),
42 m_animationDuration(ChartAnimationDuration),
42 m_animationDuration(ChartAnimationDuration),
43 m_animationCurve(QEasingCurve::OutQuart),
43 m_animationCurve(QEasingCurve::OutQuart),
44 m_state(ShowState),
44 m_state(ShowState),
45 m_background(0),
45 m_background(0),
46 m_plotAreaBackground(0),
46 m_plotAreaBackground(0),
47 m_title(0),
47 m_title(0),
48 m_localizeNumbers(false)
48 m_localizeNumbers(false)
49 #ifndef QT_NO_OPENGL
50 , m_glWidget(0)
51 , m_glUseWidget(true)
52 #endif
49 {
53 {
50 if (type == QChart::ChartTypeCartesian)
54 if (type == QChart::ChartTypeCartesian)
51 m_layout = new CartesianChartLayout(this);
55 m_layout = new CartesianChartLayout(this);
52 else if (type == QChart::ChartTypePolar)
56 else if (type == QChart::ChartTypePolar)
53 m_layout = new PolarChartLayout(this);
57 m_layout = new PolarChartLayout(this);
54 Q_ASSERT(m_layout);
58 Q_ASSERT(m_layout);
55 }
59 }
56
60
57 ChartPresenter::~ChartPresenter()
61 ChartPresenter::~ChartPresenter()
58 {
62 {
59
63 #ifndef QT_NO_OPENGL
64 delete m_glWidget.data();
65 #endif
60 }
66 }
61
67
62 void ChartPresenter::setGeometry(const QRectF rect)
68 void ChartPresenter::setGeometry(const QRectF rect)
63 {
69 {
64 if (m_rect != rect) {
70 if (m_rect != rect) {
65 m_rect = rect;
71 m_rect = rect;
66 foreach (ChartItem *chart, m_chartItems) {
72 foreach (ChartItem *chart, m_chartItems) {
67 chart->domain()->setSize(rect.size());
73 chart->domain()->setSize(rect.size());
68 chart->setPos(rect.topLeft());
74 chart->setPos(rect.topLeft());
69 }
75 }
76 #ifndef QT_NO_OPENGL
77 if (!m_glWidget.isNull())
78 m_glWidget->setGeometry(m_rect.toRect());
79 #endif
70 emit plotAreaChanged(m_rect);
80 emit plotAreaChanged(m_rect);
71 }
81 }
72 }
82 }
73
83
74 QRectF ChartPresenter::geometry() const
84 QRectF ChartPresenter::geometry() const
75 {
85 {
76 return m_rect;
86 return m_rect;
77 }
87 }
78
88
79 void ChartPresenter::handleAxisAdded(QAbstractAxis *axis)
89 void ChartPresenter::handleAxisAdded(QAbstractAxis *axis)
80 {
90 {
81 axis->d_ptr->initializeGraphics(rootItem());
91 axis->d_ptr->initializeGraphics(rootItem());
82 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
92 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
83 ChartAxisElement *item = axis->d_ptr->axisItem();
93 ChartAxisElement *item = axis->d_ptr->axisItem();
84 item->setPresenter(this);
94 item->setPresenter(this);
85 item->setThemeManager(m_chart->d_ptr->m_themeManager);
95 item->setThemeManager(m_chart->d_ptr->m_themeManager);
86 m_axisItems<<item;
96 m_axisItems<<item;
87 m_axes<<axis;
97 m_axes<<axis;
88 m_layout->invalidate();
98 m_layout->invalidate();
89 }
99 }
90
100
91 void ChartPresenter::handleAxisRemoved(QAbstractAxis *axis)
101 void ChartPresenter::handleAxisRemoved(QAbstractAxis *axis)
92 {
102 {
93 ChartAxisElement *item = axis->d_ptr->m_item.take();
103 ChartAxisElement *item = axis->d_ptr->m_item.take();
94 item->hide();
104 item->hide();
95 item->disconnect();
105 item->disconnect();
96 item->deleteLater();
106 item->deleteLater();
97 m_axisItems.removeAll(item);
107 m_axisItems.removeAll(item);
98 m_axes.removeAll(axis);
108 m_axes.removeAll(axis);
99 m_layout->invalidate();
109 m_layout->invalidate();
100 }
110 }
101
111
102
112
103 void ChartPresenter::handleSeriesAdded(QAbstractSeries *series)
113 void ChartPresenter::handleSeriesAdded(QAbstractSeries *series)
104 {
114 {
105 series->d_ptr->initializeGraphics(rootItem());
115 series->d_ptr->initializeGraphics(rootItem());
106 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
116 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
107 series->d_ptr->setPresenter(this);
117 series->d_ptr->setPresenter(this);
108 ChartItem *chart = series->d_ptr->chartItem();
118 ChartItem *chart = series->d_ptr->chartItem();
109 chart->setPresenter(this);
119 chart->setPresenter(this);
110 chart->setThemeManager(m_chart->d_ptr->m_themeManager);
120 chart->setThemeManager(m_chart->d_ptr->m_themeManager);
121 chart->setDataSet(m_chart->d_ptr->m_dataset);
111 chart->domain()->setSize(m_rect.size());
122 chart->domain()->setSize(m_rect.size());
112 chart->setPos(m_rect.topLeft());
123 chart->setPos(m_rect.topLeft());
113 chart->handleDomainUpdated(); //this could be moved to intializeGraphics when animator is refactored
124 chart->handleDomainUpdated(); //this could be moved to intializeGraphics when animator is refactored
114 m_chartItems<<chart;
125 m_chartItems<<chart;
115 m_series<<series;
126 m_series<<series;
116 m_layout->invalidate();
127 m_layout->invalidate();
117 }
128 }
118
129
119 void ChartPresenter::handleSeriesRemoved(QAbstractSeries *series)
130 void ChartPresenter::handleSeriesRemoved(QAbstractSeries *series)
120 {
131 {
121 ChartItem *chart = series->d_ptr->m_item.take();
132 ChartItem *chart = series->d_ptr->m_item.take();
122 chart->hide();
133 chart->hide();
123 chart->disconnect();
134 chart->disconnect();
124 chart->deleteLater();
135 chart->deleteLater();
125 if (chart->animation())
136 if (chart->animation())
126 chart->animation()->stopAndDestroyLater();
137 chart->animation()->stopAndDestroyLater();
127 m_chartItems.removeAll(chart);
138 m_chartItems.removeAll(chart);
128 m_series.removeAll(series);
139 m_series.removeAll(series);
129 m_layout->invalidate();
140 m_layout->invalidate();
130 }
141 }
131
142
132 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
143 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
133 {
144 {
134 if (m_options != options) {
145 if (m_options != options) {
135 QChart::AnimationOptions oldOptions = m_options;
146 QChart::AnimationOptions oldOptions = m_options;
136 m_options = options;
147 m_options = options;
137 if (options.testFlag(QChart::SeriesAnimations) != oldOptions.testFlag(QChart::SeriesAnimations)) {
148 if (options.testFlag(QChart::SeriesAnimations) != oldOptions.testFlag(QChart::SeriesAnimations)) {
138 foreach (QAbstractSeries *series, m_series)
149 foreach (QAbstractSeries *series, m_series)
139 series->d_ptr->initializeAnimations(m_options, m_animationDuration,
150 series->d_ptr->initializeAnimations(m_options, m_animationDuration,
140 m_animationCurve);
151 m_animationCurve);
141 }
152 }
142 if (options.testFlag(QChart::GridAxisAnimations) != oldOptions.testFlag(QChart::GridAxisAnimations)) {
153 if (options.testFlag(QChart::GridAxisAnimations) != oldOptions.testFlag(QChart::GridAxisAnimations)) {
143 foreach (QAbstractAxis *axis, m_axes)
154 foreach (QAbstractAxis *axis, m_axes)
144 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
155 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
145 }
156 }
146 m_layout->invalidate(); // So that existing animations don't just stop halfway
157 m_layout->invalidate(); // So that existing animations don't just stop halfway
147 }
158 }
148 }
159 }
149
160
150 void ChartPresenter::setAnimationDuration(int msecs)
161 void ChartPresenter::setAnimationDuration(int msecs)
151 {
162 {
152 if (m_animationDuration != msecs) {
163 if (m_animationDuration != msecs) {
153 m_animationDuration = msecs;
164 m_animationDuration = msecs;
154 foreach (QAbstractSeries *series, m_series)
165 foreach (QAbstractSeries *series, m_series)
155 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
166 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
156 foreach (QAbstractAxis *axis, m_axes)
167 foreach (QAbstractAxis *axis, m_axes)
157 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
168 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
158 m_layout->invalidate(); // So that existing animations don't just stop halfway
169 m_layout->invalidate(); // So that existing animations don't just stop halfway
159 }
170 }
160 }
171 }
161
172
162 void ChartPresenter::setAnimationEasingCurve(const QEasingCurve &curve)
173 void ChartPresenter::setAnimationEasingCurve(const QEasingCurve &curve)
163 {
174 {
164 if (m_animationCurve != curve) {
175 if (m_animationCurve != curve) {
165 m_animationCurve = curve;
176 m_animationCurve = curve;
166 foreach (QAbstractSeries *series, m_series)
177 foreach (QAbstractSeries *series, m_series)
167 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
178 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
168 foreach (QAbstractAxis *axis, m_axes)
179 foreach (QAbstractAxis *axis, m_axes)
169 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
180 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
170 m_layout->invalidate(); // So that existing animations don't just stop halfway
181 m_layout->invalidate(); // So that existing animations don't just stop halfway
171 }
182 }
172 }
183 }
173
184
174 void ChartPresenter::setState(State state,QPointF point)
185 void ChartPresenter::setState(State state,QPointF point)
175 {
186 {
176 m_state=state;
187 m_state=state;
177 m_statePoint=point;
188 m_statePoint=point;
178 }
189 }
179
190
180 QChart::AnimationOptions ChartPresenter::animationOptions() const
191 QChart::AnimationOptions ChartPresenter::animationOptions() const
181 {
192 {
182 return m_options;
193 return m_options;
183 }
194 }
184
195
185 void ChartPresenter::createBackgroundItem()
196 void ChartPresenter::createBackgroundItem()
186 {
197 {
187 if (!m_background) {
198 if (!m_background) {
188 m_background = new ChartBackground(rootItem());
199 m_background = new ChartBackground(rootItem());
189 m_background->setPen(Qt::NoPen); // Theme doesn't touch pen so don't use default
200 m_background->setPen(Qt::NoPen); // Theme doesn't touch pen so don't use default
190 m_background->setBrush(QChartPrivate::defaultBrush());
201 m_background->setBrush(QChartPrivate::defaultBrush());
191 m_background->setZValue(ChartPresenter::BackgroundZValue);
202 m_background->setZValue(ChartPresenter::BackgroundZValue);
192 }
203 }
193 }
204 }
194
205
195 void ChartPresenter::createPlotAreaBackgroundItem()
206 void ChartPresenter::createPlotAreaBackgroundItem()
196 {
207 {
197 if (!m_plotAreaBackground) {
208 if (!m_plotAreaBackground) {
198 if (m_chart->chartType() == QChart::ChartTypeCartesian)
209 if (m_chart->chartType() == QChart::ChartTypeCartesian)
199 m_plotAreaBackground = new QGraphicsRectItem(rootItem());
210 m_plotAreaBackground = new QGraphicsRectItem(rootItem());
200 else
211 else
201 m_plotAreaBackground = new QGraphicsEllipseItem(rootItem());
212 m_plotAreaBackground = new QGraphicsEllipseItem(rootItem());
202 // Use transparent pen instead of Qt::NoPen, as Qt::NoPen causes
213 // Use transparent pen instead of Qt::NoPen, as Qt::NoPen causes
203 // antialising artifacts with axis lines for some reason.
214 // antialising artifacts with axis lines for some reason.
204 m_plotAreaBackground->setPen(QPen(Qt::transparent));
215 m_plotAreaBackground->setPen(QPen(Qt::transparent));
205 m_plotAreaBackground->setBrush(Qt::NoBrush);
216 m_plotAreaBackground->setBrush(Qt::NoBrush);
206 m_plotAreaBackground->setZValue(ChartPresenter::PlotAreaZValue);
217 m_plotAreaBackground->setZValue(ChartPresenter::PlotAreaZValue);
207 m_plotAreaBackground->setVisible(false);
218 m_plotAreaBackground->setVisible(false);
208 }
219 }
209 }
220 }
210
221
211 void ChartPresenter::createTitleItem()
222 void ChartPresenter::createTitleItem()
212 {
223 {
213 if (!m_title) {
224 if (!m_title) {
214 m_title = new ChartTitle(rootItem());
225 m_title = new ChartTitle(rootItem());
215 m_title->setZValue(ChartPresenter::BackgroundZValue);
226 m_title->setZValue(ChartPresenter::BackgroundZValue);
216 }
227 }
217 }
228 }
218
229
219 void ChartPresenter::startAnimation(ChartAnimation *animation)
230 void ChartPresenter::startAnimation(ChartAnimation *animation)
220 {
231 {
221 animation->stop();
232 animation->stop();
222 QTimer::singleShot(0, animation, SLOT(startChartAnimation()));
233 QTimer::singleShot(0, animation, SLOT(startChartAnimation()));
223 }
234 }
224
235
225 void ChartPresenter::setBackgroundBrush(const QBrush &brush)
236 void ChartPresenter::setBackgroundBrush(const QBrush &brush)
226 {
237 {
227 createBackgroundItem();
238 createBackgroundItem();
228 m_background->setBrush(brush);
239 m_background->setBrush(brush);
229 m_layout->invalidate();
240 m_layout->invalidate();
230 }
241 }
231
242
232 QBrush ChartPresenter::backgroundBrush() const
243 QBrush ChartPresenter::backgroundBrush() const
233 {
244 {
234 if (!m_background)
245 if (!m_background)
235 return QBrush();
246 return QBrush();
236 return m_background->brush();
247 return m_background->brush();
237 }
248 }
238
249
239 void ChartPresenter::setBackgroundPen(const QPen &pen)
250 void ChartPresenter::setBackgroundPen(const QPen &pen)
240 {
251 {
241 createBackgroundItem();
252 createBackgroundItem();
242 m_background->setPen(pen);
253 m_background->setPen(pen);
243 m_layout->invalidate();
254 m_layout->invalidate();
244 }
255 }
245
256
246 QPen ChartPresenter::backgroundPen() const
257 QPen ChartPresenter::backgroundPen() const
247 {
258 {
248 if (!m_background)
259 if (!m_background)
249 return QPen();
260 return QPen();
250 return m_background->pen();
261 return m_background->pen();
251 }
262 }
252
263
253 void ChartPresenter::setBackgroundRoundness(qreal diameter)
264 void ChartPresenter::setBackgroundRoundness(qreal diameter)
254 {
265 {
255 createBackgroundItem();
266 createBackgroundItem();
256 m_background->setDiameter(diameter);
267 m_background->setDiameter(diameter);
257 m_layout->invalidate();
268 m_layout->invalidate();
258 }
269 }
259
270
260 qreal ChartPresenter::backgroundRoundness() const
271 qreal ChartPresenter::backgroundRoundness() const
261 {
272 {
262 if (!m_background)
273 if (!m_background)
263 return 0;
274 return 0;
264 return m_background->diameter();
275 return m_background->diameter();
265 }
276 }
266
277
267 void ChartPresenter::setPlotAreaBackgroundBrush(const QBrush &brush)
278 void ChartPresenter::setPlotAreaBackgroundBrush(const QBrush &brush)
268 {
279 {
269 createPlotAreaBackgroundItem();
280 createPlotAreaBackgroundItem();
270 m_plotAreaBackground->setBrush(brush);
281 m_plotAreaBackground->setBrush(brush);
271 m_layout->invalidate();
282 m_layout->invalidate();
272 }
283 }
273
284
274 QBrush ChartPresenter::plotAreaBackgroundBrush() const
285 QBrush ChartPresenter::plotAreaBackgroundBrush() const
275 {
286 {
276 if (!m_plotAreaBackground)
287 if (!m_plotAreaBackground)
277 return QBrush();
288 return QBrush();
278 return m_plotAreaBackground->brush();
289 return m_plotAreaBackground->brush();
279 }
290 }
280
291
281 void ChartPresenter::setPlotAreaBackgroundPen(const QPen &pen)
292 void ChartPresenter::setPlotAreaBackgroundPen(const QPen &pen)
282 {
293 {
283 createPlotAreaBackgroundItem();
294 createPlotAreaBackgroundItem();
284 m_plotAreaBackground->setPen(pen);
295 m_plotAreaBackground->setPen(pen);
285 m_layout->invalidate();
296 m_layout->invalidate();
286 }
297 }
287
298
288 QPen ChartPresenter::plotAreaBackgroundPen() const
299 QPen ChartPresenter::plotAreaBackgroundPen() const
289 {
300 {
290 if (!m_plotAreaBackground)
301 if (!m_plotAreaBackground)
291 return QPen();
302 return QPen();
292 return m_plotAreaBackground->pen();
303 return m_plotAreaBackground->pen();
293 }
304 }
294
305
295 void ChartPresenter::setTitle(const QString &title)
306 void ChartPresenter::setTitle(const QString &title)
296 {
307 {
297 createTitleItem();
308 createTitleItem();
298 m_title->setText(title);
309 m_title->setText(title);
299 m_layout->invalidate();
310 m_layout->invalidate();
300 }
311 }
301
312
302 QString ChartPresenter::title() const
313 QString ChartPresenter::title() const
303 {
314 {
304 if (!m_title)
315 if (!m_title)
305 return QString();
316 return QString();
306 return m_title->text();
317 return m_title->text();
307 }
318 }
308
319
309 void ChartPresenter::setTitleFont(const QFont &font)
320 void ChartPresenter::setTitleFont(const QFont &font)
310 {
321 {
311 createTitleItem();
322 createTitleItem();
312 m_title->setFont(font);
323 m_title->setFont(font);
313 m_layout->invalidate();
324 m_layout->invalidate();
314 }
325 }
315
326
316 QFont ChartPresenter::titleFont() const
327 QFont ChartPresenter::titleFont() const
317 {
328 {
318 if (!m_title)
329 if (!m_title)
319 return QFont();
330 return QFont();
320 return m_title->font();
331 return m_title->font();
321 }
332 }
322
333
323 void ChartPresenter::setTitleBrush(const QBrush &brush)
334 void ChartPresenter::setTitleBrush(const QBrush &brush)
324 {
335 {
325 createTitleItem();
336 createTitleItem();
326 m_title->setDefaultTextColor(brush.color());
337 m_title->setDefaultTextColor(brush.color());
327 m_layout->invalidate();
338 m_layout->invalidate();
328 }
339 }
329
340
330 QBrush ChartPresenter::titleBrush() const
341 QBrush ChartPresenter::titleBrush() const
331 {
342 {
332 if (!m_title)
343 if (!m_title)
333 return QBrush();
344 return QBrush();
334 return QBrush(m_title->defaultTextColor());
345 return QBrush(m_title->defaultTextColor());
335 }
346 }
336
347
337 void ChartPresenter::setBackgroundVisible(bool visible)
348 void ChartPresenter::setBackgroundVisible(bool visible)
338 {
349 {
339 createBackgroundItem();
350 createBackgroundItem();
340 m_background->setVisible(visible);
351 m_background->setVisible(visible);
341 }
352 }
342
353
343
354
344 bool ChartPresenter::isBackgroundVisible() const
355 bool ChartPresenter::isBackgroundVisible() const
345 {
356 {
346 if (!m_background)
357 if (!m_background)
347 return false;
358 return false;
348 return m_background->isVisible();
359 return m_background->isVisible();
349 }
360 }
350
361
351 void ChartPresenter::setPlotAreaBackgroundVisible(bool visible)
362 void ChartPresenter::setPlotAreaBackgroundVisible(bool visible)
352 {
363 {
353 createPlotAreaBackgroundItem();
364 createPlotAreaBackgroundItem();
354 m_plotAreaBackground->setVisible(visible);
365 m_plotAreaBackground->setVisible(visible);
355 }
366 }
356
367
357 bool ChartPresenter::isPlotAreaBackgroundVisible() const
368 bool ChartPresenter::isPlotAreaBackgroundVisible() const
358 {
369 {
359 if (!m_plotAreaBackground)
370 if (!m_plotAreaBackground)
360 return false;
371 return false;
361 return m_plotAreaBackground->isVisible();
372 return m_plotAreaBackground->isVisible();
362 }
373 }
363
374
364 void ChartPresenter::setBackgroundDropShadowEnabled(bool enabled)
375 void ChartPresenter::setBackgroundDropShadowEnabled(bool enabled)
365 {
376 {
366 createBackgroundItem();
377 createBackgroundItem();
367 m_background->setDropShadowEnabled(enabled);
378 m_background->setDropShadowEnabled(enabled);
368 }
379 }
369
380
370 bool ChartPresenter::isBackgroundDropShadowEnabled() const
381 bool ChartPresenter::isBackgroundDropShadowEnabled() const
371 {
382 {
372 if (!m_background)
383 if (!m_background)
373 return false;
384 return false;
374 return m_background->isDropShadowEnabled();
385 return m_background->isDropShadowEnabled();
375 }
386 }
376
387
377 void ChartPresenter::setLocalizeNumbers(bool localize)
388 void ChartPresenter::setLocalizeNumbers(bool localize)
378 {
389 {
379 m_localizeNumbers = localize;
390 m_localizeNumbers = localize;
380 m_layout->invalidate();
391 m_layout->invalidate();
381 }
392 }
382
393
383 void ChartPresenter::setLocale(const QLocale &locale)
394 void ChartPresenter::setLocale(const QLocale &locale)
384 {
395 {
385 m_locale = locale;
396 m_locale = locale;
386 m_layout->invalidate();
397 m_layout->invalidate();
387 }
398 }
388
399
389 AbstractChartLayout *ChartPresenter::layout()
400 AbstractChartLayout *ChartPresenter::layout()
390 {
401 {
391 return m_layout;
402 return m_layout;
392 }
403 }
393
404
394 QLegend *ChartPresenter::legend()
405 QLegend *ChartPresenter::legend()
395 {
406 {
396 return m_chart->legend();
407 return m_chart->legend();
397 }
408 }
398
409
399 void ChartPresenter::setVisible(bool visible)
410 void ChartPresenter::setVisible(bool visible)
400 {
411 {
401 m_chart->setVisible(visible);
412 m_chart->setVisible(visible);
402 }
413 }
403
414
404 ChartBackground *ChartPresenter::backgroundElement()
415 ChartBackground *ChartPresenter::backgroundElement()
405 {
416 {
406 return m_background;
417 return m_background;
407 }
418 }
408
419
409 QAbstractGraphicsShapeItem *ChartPresenter::plotAreaElement()
420 QAbstractGraphicsShapeItem *ChartPresenter::plotAreaElement()
410 {
421 {
411 return m_plotAreaBackground;
422 return m_plotAreaBackground;
412 }
423 }
413
424
414 QList<ChartAxisElement *> ChartPresenter::axisItems() const
425 QList<ChartAxisElement *> ChartPresenter::axisItems() const
415 {
426 {
416 return m_axisItems;
427 return m_axisItems;
417 }
428 }
418
429
419 QList<ChartItem *> ChartPresenter::chartItems() const
430 QList<ChartItem *> ChartPresenter::chartItems() const
420 {
431 {
421 return m_chartItems;
432 return m_chartItems;
422 }
433 }
423
434
424 ChartTitle *ChartPresenter::titleElement()
435 ChartTitle *ChartPresenter::titleElement()
425 {
436 {
426 return m_title;
437 return m_title;
427 }
438 }
428
439
429 QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, qreal angle)
440 QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, qreal angle)
430 {
441 {
431 static QGraphicsTextItem dummyTextItem;
442 static QGraphicsTextItem dummyTextItem;
432 static bool initMargin = true;
443 static bool initMargin = true;
433 if (initMargin) {
444 if (initMargin) {
434 dummyTextItem.document()->setDocumentMargin(textMargin());
445 dummyTextItem.document()->setDocumentMargin(textMargin());
435 initMargin = false;
446 initMargin = false;
436 }
447 }
437
448
438 dummyTextItem.setFont(font);
449 dummyTextItem.setFont(font);
439 dummyTextItem.setHtml(text);
450 dummyTextItem.setHtml(text);
440 QRectF boundingRect = dummyTextItem.boundingRect();
451 QRectF boundingRect = dummyTextItem.boundingRect();
441
452
442 // Take rotation into account
453 // Take rotation into account
443 if (angle) {
454 if (angle) {
444 QTransform transform;
455 QTransform transform;
445 transform.rotate(angle);
456 transform.rotate(angle);
446 boundingRect = transform.mapRect(boundingRect);
457 boundingRect = transform.mapRect(boundingRect);
447 }
458 }
448
459
449 return boundingRect;
460 return boundingRect;
450 }
461 }
451
462
452 // boundingRect parameter returns the rotated bounding rect of the text
463 // boundingRect parameter returns the rotated bounding rect of the text
453 QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle,
464 QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle,
454 qreal maxWidth, qreal maxHeight, QRectF &boundingRect)
465 qreal maxWidth, qreal maxHeight, QRectF &boundingRect)
455 {
466 {
456 QString truncatedString(text);
467 QString truncatedString(text);
457 boundingRect = textBoundingRect(font, truncatedString, angle);
468 boundingRect = textBoundingRect(font, truncatedString, angle);
458 if (boundingRect.width() > maxWidth || boundingRect.height() > maxHeight) {
469 if (boundingRect.width() > maxWidth || boundingRect.height() > maxHeight) {
459 // It can be assumed that almost any amount of string manipulation is faster
470 // It can be assumed that almost any amount of string manipulation is faster
460 // than calculating one bounding rectangle, so first prepare a list of truncated strings
471 // than calculating one bounding rectangle, so first prepare a list of truncated strings
461 // to try.
472 // to try.
462 static QRegExp truncateMatcher(QStringLiteral("&#?[0-9a-zA-Z]*;$"));
473 static QRegExp truncateMatcher(QStringLiteral("&#?[0-9a-zA-Z]*;$"));
463
474
464 QVector<QString> testStrings(text.length());
475 QVector<QString> testStrings(text.length());
465 int count(0);
476 int count(0);
466 static QLatin1Char closeTag('>');
477 static QLatin1Char closeTag('>');
467 static QLatin1Char openTag('<');
478 static QLatin1Char openTag('<');
468 static QLatin1Char semiColon(';');
479 static QLatin1Char semiColon(';');
469 static QLatin1String ellipsis("...");
480 static QLatin1String ellipsis("...");
470 while (truncatedString.length() > 1) {
481 while (truncatedString.length() > 1) {
471 int chopIndex(-1);
482 int chopIndex(-1);
472 int chopCount(1);
483 int chopCount(1);
473 QChar lastChar(truncatedString.at(truncatedString.length() - 1));
484 QChar lastChar(truncatedString.at(truncatedString.length() - 1));
474
485
475 if (lastChar == closeTag)
486 if (lastChar == closeTag)
476 chopIndex = truncatedString.lastIndexOf(openTag);
487 chopIndex = truncatedString.lastIndexOf(openTag);
477 else if (lastChar == semiColon)
488 else if (lastChar == semiColon)
478 chopIndex = truncateMatcher.indexIn(truncatedString, 0);
489 chopIndex = truncateMatcher.indexIn(truncatedString, 0);
479
490
480 if (chopIndex != -1)
491 if (chopIndex != -1)
481 chopCount = truncatedString.length() - chopIndex;
492 chopCount = truncatedString.length() - chopIndex;
482 truncatedString.chop(chopCount);
493 truncatedString.chop(chopCount);
483 testStrings[count] = truncatedString + ellipsis;
494 testStrings[count] = truncatedString + ellipsis;
484 count++;
495 count++;
485 }
496 }
486
497
487 // Binary search for best fit
498 // Binary search for best fit
488 int minIndex(0);
499 int minIndex(0);
489 int maxIndex(count - 1);
500 int maxIndex(count - 1);
490 int bestIndex(count);
501 int bestIndex(count);
491 QRectF checkRect;
502 QRectF checkRect;
492
503
493 while (maxIndex >= minIndex) {
504 while (maxIndex >= minIndex) {
494 int mid = (maxIndex + minIndex) / 2;
505 int mid = (maxIndex + minIndex) / 2;
495 checkRect = textBoundingRect(font, testStrings.at(mid), angle);
506 checkRect = textBoundingRect(font, testStrings.at(mid), angle);
496 if (checkRect.width() > maxWidth || checkRect.height() > maxHeight) {
507 if (checkRect.width() > maxWidth || checkRect.height() > maxHeight) {
497 // Checked index too large, all under this are also too large
508 // Checked index too large, all under this are also too large
498 minIndex = mid + 1;
509 minIndex = mid + 1;
499 } else {
510 } else {
500 // Checked index fits, all over this also fit
511 // Checked index fits, all over this also fit
501 maxIndex = mid - 1;
512 maxIndex = mid - 1;
502 bestIndex = mid;
513 bestIndex = mid;
503 boundingRect = checkRect;
514 boundingRect = checkRect;
504 }
515 }
505 }
516 }
506 // Default to "..." if nothing fits
517 // Default to "..." if nothing fits
507 if (bestIndex == count) {
518 if (bestIndex == count) {
508 boundingRect = textBoundingRect(font, ellipsis, angle);
519 boundingRect = textBoundingRect(font, ellipsis, angle);
509 truncatedString = ellipsis;
520 truncatedString = ellipsis;
510 } else {
521 } else {
511 truncatedString = testStrings.at(bestIndex);
522 truncatedString = testStrings.at(bestIndex);
512 }
523 }
513 }
524 }
514
525
515 return truncatedString;
526 return truncatedString;
516 }
527 }
517
528
518 QString ChartPresenter::numberToString(double value, char f, int prec)
529 QString ChartPresenter::numberToString(double value, char f, int prec)
519 {
530 {
520 if (m_localizeNumbers)
531 if (m_localizeNumbers)
521 return m_locale.toString(value, f, prec);
532 return m_locale.toString(value, f, prec);
522 else
533 else
523 return QString::number(value, f, prec);
534 return QString::number(value, f, prec);
524 }
535 }
525
536
526 QString ChartPresenter::numberToString(int value)
537 QString ChartPresenter::numberToString(int value)
527 {
538 {
528 if (m_localizeNumbers)
539 if (m_localizeNumbers)
529 return m_locale.toString(value);
540 return m_locale.toString(value);
530 else
541 else
531 return QString::number(value);
542 return QString::number(value);
532 }
543 }
533
544
545 void ChartPresenter::ensureGLWidget()
546 {
547 #ifndef QT_NO_OPENGL
548 // GLWidget pointer is wrapped in QPointer as its parent is not in our control, and therefore
549 // can potentially get deleted unexpectedly.
550 if (m_glWidget.isNull() && m_glUseWidget && m_chart->scene()) {
551 QObject *parent = m_chart->scene()->parent();
552 while (parent) {
553 QWidget *parentWidget = qobject_cast<QWidget *>(parent);
554 if (parentWidget) {
555 m_glWidget = new GLWidget(m_chart->d_ptr->m_dataset->glXYSeriesDataManager(),
556 parentWidget);
557 m_glWidget->setGeometry(m_rect.toRect());
558 m_glWidget->show();
559 break;
560 }
561 parent = parent->parent();
562 }
563 }
564 #endif
565 }
566
534 #include "moc_chartpresenter_p.cpp"
567 #include "moc_chartpresenter_p.cpp"
535
568
536 QT_CHARTS_END_NAMESPACE
569 QT_CHARTS_END_NAMESPACE
@@ -1,199 +1,208
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 // W A R N I N G
19 // W A R N I N G
20 // -------------
20 // -------------
21 //
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
24 // version without notice, or even be removed.
25 //
25 //
26 // We mean it.
26 // We mean it.
27
27
28 #ifndef CHARTPRESENTER_H
28 #ifndef CHARTPRESENTER_H
29 #define CHARTPRESENTER_H
29 #define CHARTPRESENTER_H
30
30
31 #include <QtCharts/QChartGlobal>
31 #include <QtCharts/QChartGlobal>
32 #include <QtCharts/QChart> //because of QChart::ChartThemeId
32 #include <QtCharts/QChart> //because of QChart::ChartThemeId
33 #include <private/glwidget_p.h>
33 #include <QtCore/QRectF>
34 #include <QtCore/QRectF>
34 #include <QtCore/QMargins>
35 #include <QtCore/QMargins>
35 #include <QtCore/QLocale>
36 #include <QtCore/QLocale>
37 #include <QtCore/QPointer>
36
38
37 QT_CHARTS_BEGIN_NAMESPACE
39 QT_CHARTS_BEGIN_NAMESPACE
38
40
39 class ChartItem;
41 class ChartItem;
40 class AxisItem;
42 class AxisItem;
41 class QAbstractSeries;
43 class QAbstractSeries;
42 class ChartDataSet;
44 class ChartDataSet;
43 class AbstractDomain;
45 class AbstractDomain;
44 class ChartAxisElement;
46 class ChartAxisElement;
45 class ChartAnimator;
47 class ChartAnimator;
46 class ChartBackground;
48 class ChartBackground;
47 class ChartTitle;
49 class ChartTitle;
48 class ChartAnimation;
50 class ChartAnimation;
49 class AbstractChartLayout;
51 class AbstractChartLayout;
50
52
51 class ChartPresenter: public QObject
53 class ChartPresenter: public QObject
52 {
54 {
53 Q_OBJECT
55 Q_OBJECT
54 public:
56 public:
55 enum ZValues {
57 enum ZValues {
56 BackgroundZValue = -1,
58 BackgroundZValue = -1,
57 PlotAreaZValue,
59 PlotAreaZValue,
58 ShadesZValue,
60 ShadesZValue,
59 GridZValue,
61 GridZValue,
60 AxisZValue,
62 AxisZValue,
61 SeriesZValue,
63 SeriesZValue,
62 LineChartZValue = SeriesZValue,
64 LineChartZValue = SeriesZValue,
63 SplineChartZValue = SeriesZValue,
65 SplineChartZValue = SeriesZValue,
64 BarSeriesZValue = SeriesZValue,
66 BarSeriesZValue = SeriesZValue,
65 ScatterSeriesZValue = SeriesZValue,
67 ScatterSeriesZValue = SeriesZValue,
66 PieSeriesZValue = SeriesZValue,
68 PieSeriesZValue = SeriesZValue,
67 BoxPlotSeriesZValue = SeriesZValue,
69 BoxPlotSeriesZValue = SeriesZValue,
68 LegendZValue,
70 LegendZValue,
69 TopMostZValue
71 TopMostZValue
70 };
72 };
71
73
72 enum State {
74 enum State {
73 ShowState,
75 ShowState,
74 ScrollUpState,
76 ScrollUpState,
75 ScrollDownState,
77 ScrollDownState,
76 ScrollLeftState,
78 ScrollLeftState,
77 ScrollRightState,
79 ScrollRightState,
78 ZoomInState,
80 ZoomInState,
79 ZoomOutState
81 ZoomOutState
80 };
82 };
81
83
82 ChartPresenter(QChart *chart, QChart::ChartType type);
84 ChartPresenter(QChart *chart, QChart::ChartType type);
83 virtual ~ChartPresenter();
85 virtual ~ChartPresenter();
84
86
85
87
86 void setGeometry(QRectF rect);
88 void setGeometry(QRectF rect);
87 QRectF geometry() const;
89 QRectF geometry() const;
88
90
89 QGraphicsItem *rootItem(){ return m_chart; }
91 QGraphicsItem *rootItem(){ return m_chart; }
90 ChartBackground *backgroundElement();
92 ChartBackground *backgroundElement();
91 QAbstractGraphicsShapeItem *plotAreaElement();
93 QAbstractGraphicsShapeItem *plotAreaElement();
92 ChartTitle *titleElement();
94 ChartTitle *titleElement();
93 QList<ChartAxisElement *> axisItems() const;
95 QList<ChartAxisElement *> axisItems() const;
94 QList<ChartItem *> chartItems() const;
96 QList<ChartItem *> chartItems() const;
95
97
96 QLegend *legend();
98 QLegend *legend();
97
99
98 void setBackgroundBrush(const QBrush &brush);
100 void setBackgroundBrush(const QBrush &brush);
99 QBrush backgroundBrush() const;
101 QBrush backgroundBrush() const;
100
102
101 void setBackgroundPen(const QPen &pen);
103 void setBackgroundPen(const QPen &pen);
102 QPen backgroundPen() const;
104 QPen backgroundPen() const;
103
105
104 void setBackgroundRoundness(qreal diameter);
106 void setBackgroundRoundness(qreal diameter);
105 qreal backgroundRoundness() const;
107 qreal backgroundRoundness() const;
106
108
107 void setPlotAreaBackgroundBrush(const QBrush &brush);
109 void setPlotAreaBackgroundBrush(const QBrush &brush);
108 QBrush plotAreaBackgroundBrush() const;
110 QBrush plotAreaBackgroundBrush() const;
109
111
110 void setPlotAreaBackgroundPen(const QPen &pen);
112 void setPlotAreaBackgroundPen(const QPen &pen);
111 QPen plotAreaBackgroundPen() const;
113 QPen plotAreaBackgroundPen() const;
112
114
113 void setTitle(const QString &title);
115 void setTitle(const QString &title);
114 QString title() const;
116 QString title() const;
115
117
116 void setTitleFont(const QFont &font);
118 void setTitleFont(const QFont &font);
117 QFont titleFont() const;
119 QFont titleFont() const;
118
120
119 void setTitleBrush(const QBrush &brush);
121 void setTitleBrush(const QBrush &brush);
120 QBrush titleBrush() const;
122 QBrush titleBrush() const;
121
123
122 void setBackgroundVisible(bool visible);
124 void setBackgroundVisible(bool visible);
123 bool isBackgroundVisible() const;
125 bool isBackgroundVisible() const;
124
126
125 void setPlotAreaBackgroundVisible(bool visible);
127 void setPlotAreaBackgroundVisible(bool visible);
126 bool isPlotAreaBackgroundVisible() const;
128 bool isPlotAreaBackgroundVisible() const;
127
129
128 void setBackgroundDropShadowEnabled(bool enabled);
130 void setBackgroundDropShadowEnabled(bool enabled);
129 bool isBackgroundDropShadowEnabled() const;
131 bool isBackgroundDropShadowEnabled() const;
130
132
131 void setLocalizeNumbers(bool localize);
133 void setLocalizeNumbers(bool localize);
132 inline bool localizeNumbers() const { return m_localizeNumbers; }
134 inline bool localizeNumbers() const { return m_localizeNumbers; }
133 void setLocale(const QLocale &locale);
135 void setLocale(const QLocale &locale);
134 inline const QLocale &locale() const { return m_locale; }
136 inline const QLocale &locale() const { return m_locale; }
135
137
136 void setVisible(bool visible);
138 void setVisible(bool visible);
137
139
138 void setAnimationOptions(QChart::AnimationOptions options);
140 void setAnimationOptions(QChart::AnimationOptions options);
139 QChart::AnimationOptions animationOptions() const;
141 QChart::AnimationOptions animationOptions() const;
140 void setAnimationDuration(int msecs);
142 void setAnimationDuration(int msecs);
141 int animationDuration() const { return m_animationDuration; }
143 int animationDuration() const { return m_animationDuration; }
142 void setAnimationEasingCurve(const QEasingCurve &curve);
144 void setAnimationEasingCurve(const QEasingCurve &curve);
143 QEasingCurve animationEasingCurve() const { return m_animationCurve; }
145 QEasingCurve animationEasingCurve() const { return m_animationCurve; }
144
146
145 void startAnimation(ChartAnimation *animation);
147 void startAnimation(ChartAnimation *animation);
146
148
147 void setState(State state,QPointF point);
149 void setState(State state,QPointF point);
148 State state() const { return m_state; }
150 State state() const { return m_state; }
149 QPointF statePoint() const { return m_statePoint; }
151 QPointF statePoint() const { return m_statePoint; }
150 AbstractChartLayout *layout();
152 AbstractChartLayout *layout();
151
153
152 QChart::ChartType chartType() const { return m_chart->chartType(); }
154 QChart::ChartType chartType() const { return m_chart->chartType(); }
153 QChart *chart() { return m_chart; }
155 QChart *chart() { return m_chart; }
154
156
155 static QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0);
157 static QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0);
156 static QString truncatedText(const QFont &font, const QString &text, qreal angle,
158 static QString truncatedText(const QFont &font, const QString &text, qreal angle,
157 qreal maxWidth, qreal maxHeight, QRectF &boundingRect);
159 qreal maxWidth, qreal maxHeight, QRectF &boundingRect);
158 inline static qreal textMargin() { return qreal(0.5); }
160 inline static qreal textMargin() { return qreal(0.5); }
159
161
160 QString numberToString(double value, char f = 'g', int prec = 6);
162 QString numberToString(double value, char f = 'g', int prec = 6);
161 QString numberToString(int value);
163 QString numberToString(int value);
162
164
165 void ensureGLWidget();
166 void glSetUseWidget(bool enable) { m_glUseWidget = enable; }
167
163 private:
168 private:
164 void createBackgroundItem();
169 void createBackgroundItem();
165 void createPlotAreaBackgroundItem();
170 void createPlotAreaBackgroundItem();
166 void createTitleItem();
171 void createTitleItem();
167
172
168 public Q_SLOTS:
173 public Q_SLOTS:
169 void handleSeriesAdded(QAbstractSeries *series);
174 void handleSeriesAdded(QAbstractSeries *series);
170 void handleSeriesRemoved(QAbstractSeries *series);
175 void handleSeriesRemoved(QAbstractSeries *series);
171 void handleAxisAdded(QAbstractAxis *axis);
176 void handleAxisAdded(QAbstractAxis *axis);
172 void handleAxisRemoved(QAbstractAxis *axis);
177 void handleAxisRemoved(QAbstractAxis *axis);
173
178
174 Q_SIGNALS:
179 Q_SIGNALS:
175 void plotAreaChanged(const QRectF &plotArea);
180 void plotAreaChanged(const QRectF &plotArea);
176
181
177 private:
182 private:
178 QChart *m_chart;
183 QChart *m_chart;
179 QList<ChartItem *> m_chartItems;
184 QList<ChartItem *> m_chartItems;
180 QList<ChartAxisElement *> m_axisItems;
185 QList<ChartAxisElement *> m_axisItems;
181 QList<QAbstractSeries *> m_series;
186 QList<QAbstractSeries *> m_series;
182 QList<QAbstractAxis *> m_axes;
187 QList<QAbstractAxis *> m_axes;
183 QChart::AnimationOptions m_options;
188 QChart::AnimationOptions m_options;
184 int m_animationDuration;
189 int m_animationDuration;
185 QEasingCurve m_animationCurve;
190 QEasingCurve m_animationCurve;
186 State m_state;
191 State m_state;
187 QPointF m_statePoint;
192 QPointF m_statePoint;
188 AbstractChartLayout *m_layout;
193 AbstractChartLayout *m_layout;
189 ChartBackground *m_background;
194 ChartBackground *m_background;
190 QAbstractGraphicsShapeItem *m_plotAreaBackground;
195 QAbstractGraphicsShapeItem *m_plotAreaBackground;
191 ChartTitle *m_title;
196 ChartTitle *m_title;
192 QRectF m_rect;
197 QRectF m_rect;
193 bool m_localizeNumbers;
198 bool m_localizeNumbers;
194 QLocale m_locale;
199 QLocale m_locale;
200 #ifndef QT_NO_OPENGL
201 QPointer<GLWidget> m_glWidget;
202 #endif
203 bool m_glUseWidget;
195 };
204 };
196
205
197 QT_CHARTS_END_NAMESPACE
206 QT_CHARTS_END_NAMESPACE
198
207
199 #endif /* CHARTPRESENTER_H */
208 #endif /* CHARTPRESENTER_H */
@@ -1,95 +1,101
1 ############################# BUILD CONFIG ######################################
1 ############################# BUILD CONFIG ######################################
2
2
3 TARGET = QtCharts
3 TARGET = QtCharts
4
4
5 message($$QT_CONFIG)
5 message($$QT_CONFIG)
6 QT = core gui widgets
6 QT = core gui widgets
7 DEFINES += QT_CHARTS_LIBRARY
7 DEFINES += QT_CHARTS_LIBRARY
8 # Fix exports in static builds for applications linking charts module
8 # Fix exports in static builds for applications linking charts module
9 static: MODULE_DEFINES += QT_CHARTS_STATICLIB
9 static: MODULE_DEFINES += QT_CHARTS_STATICLIB
10
10
11 MODULE_INCNAME = QtCharts
11 MODULE_INCNAME = QtCharts
12
12
13 QMAKE_DOCS = $$PWD/doc/qtcharts.qdocconf
13 QMAKE_DOCS = $$PWD/doc/qtcharts.qdocconf
14
14
15 load(qt_module)
15 load(qt_module)
16
16
17 QMAKE_TARGET_PRODUCT = "Qt Charts (Qt $$QT_VERSION)"
17 QMAKE_TARGET_PRODUCT = "Qt Charts (Qt $$QT_VERSION)"
18 QMAKE_TARGET_DESCRIPTION = "Charts component for Qt."
18 QMAKE_TARGET_DESCRIPTION = "Charts component for Qt."
19
19
20 ############################# SOURCES ##########################################
20 ############################# SOURCES ##########################################
21
21
22 SOURCES += \
22 SOURCES += \
23 $$PWD/chartdataset.cpp \
23 $$PWD/chartdataset.cpp \
24 $$PWD/chartpresenter.cpp \
24 $$PWD/chartpresenter.cpp \
25 $$PWD/chartthememanager.cpp \
25 $$PWD/chartthememanager.cpp \
26 $$PWD/qchart.cpp \
26 $$PWD/qchart.cpp \
27 $$PWD/qchartview.cpp \
27 $$PWD/qchartview.cpp \
28 $$PWD/qabstractseries.cpp \
28 $$PWD/qabstractseries.cpp \
29 $$PWD/chartbackground.cpp \
29 $$PWD/chartbackground.cpp \
30 $$PWD/chartelement.cpp \
30 $$PWD/chartelement.cpp \
31 $$PWD/chartitem.cpp \
31 $$PWD/chartitem.cpp \
32 $$PWD/scroller.cpp \
32 $$PWD/scroller.cpp \
33 $$PWD/charttitle.cpp \
33 $$PWD/charttitle.cpp \
34 $$PWD/qpolarchart.cpp
34 $$PWD/qpolarchart.cpp
35
36 contains(QT_CONFIG, opengl): SOURCES += $$PWD/glwidget.cpp
37
35 PRIVATE_HEADERS += \
38 PRIVATE_HEADERS += \
36 $$PWD/chartdataset_p.h \
39 $$PWD/chartdataset_p.h \
37 $$PWD/chartitem_p.h \
40 $$PWD/chartitem_p.h \
38 $$PWD/chartpresenter_p.h \
41 $$PWD/chartpresenter_p.h \
39 $$PWD/chartthememanager_p.h \
42 $$PWD/chartthememanager_p.h \
40 $$PWD/chartbackground_p.h \
43 $$PWD/chartbackground_p.h \
41 $$PWD/chartelement_p.h \
44 $$PWD/chartelement_p.h \
42 $$PWD/chartconfig_p.h \
45 $$PWD/chartconfig_p.h \
43 $$PWD/qchart_p.h \
46 $$PWD/qchart_p.h \
44 $$PWD/qchartview_p.h \
47 $$PWD/qchartview_p.h \
45 $$PWD/scroller_p.h \
48 $$PWD/scroller_p.h \
46 $$PWD/qabstractseries_p.h \
49 $$PWD/qabstractseries_p.h \
47 $$PWD/charttitle_p.h \
50 $$PWD/charttitle_p.h \
48 $$PWD/charthelpers_p.h
51 $$PWD/charthelpers_p.h
52
53 contains(QT_CONFIG, opengl): PRIVATE_HEADERS += $$PWD/glwidget_p.h
54
49 PUBLIC_HEADERS += \
55 PUBLIC_HEADERS += \
50 $$PWD/qchart.h \
56 $$PWD/qchart.h \
51 $$PWD/qchartglobal.h \
57 $$PWD/qchartglobal.h \
52 $$PWD/qabstractseries.h \
58 $$PWD/qabstractseries.h \
53 $$PWD/qchartview.h \
59 $$PWD/qchartview.h \
54 $$PWD/chartsnamespace.h \
60 $$PWD/chartsnamespace.h \
55 $$PWD/qpolarchart.h
61 $$PWD/qpolarchart.h
56
62
57 include($$PWD/common.pri)
63 include($$PWD/common.pri)
58 include($$PWD/animations/animations.pri)
64 include($$PWD/animations/animations.pri)
59 include($$PWD/areachart/areachart.pri)
65 include($$PWD/areachart/areachart.pri)
60 include($$PWD/axis/axis.pri)
66 include($$PWD/axis/axis.pri)
61 include($$PWD/domain/domain.pri)
67 include($$PWD/domain/domain.pri)
62 include($$PWD/barchart/barchart.pri)
68 include($$PWD/barchart/barchart.pri)
63 include($$PWD/legend/legend.pri)
69 include($$PWD/legend/legend.pri)
64 include($$PWD/linechart/linechart.pri)
70 include($$PWD/linechart/linechart.pri)
65 include($$PWD/piechart/piechart.pri)
71 include($$PWD/piechart/piechart.pri)
66 include($$PWD/scatterchart/scatter.pri)
72 include($$PWD/scatterchart/scatter.pri)
67 include($$PWD/splinechart/splinechart.pri)
73 include($$PWD/splinechart/splinechart.pri)
68 include($$PWD/themes/themes.pri)
74 include($$PWD/themes/themes.pri)
69 include($$PWD/xychart/xychart.pri)
75 include($$PWD/xychart/xychart.pri)
70 include($$PWD/layout/layout.pri)
76 include($$PWD/layout/layout.pri)
71 include($$PWD/boxplotchart/boxplotchart.pri)
77 include($$PWD/boxplotchart/boxplotchart.pri)
72
78
73 HEADERS += $$PUBLIC_HEADERS
79 HEADERS += $$PUBLIC_HEADERS
74 HEADERS += $$PRIVATE_HEADERS
80 HEADERS += $$PRIVATE_HEADERS
75 HEADERS += $$THEMES
81 HEADERS += $$THEMES
76
82
77 OTHER_FILES += doc/qtcharts.qdocconf \
83 OTHER_FILES += doc/qtcharts.qdocconf \
78 doc/src/* \
84 doc/src/* \
79 doc/images/*
85 doc/images/*
80
86
81 #Define for unit tests
87 #Define for unit tests
82 CONFIG(debug, debug|release) {
88 CONFIG(debug, debug|release) {
83 DEFINES += BUILD_PRIVATE_UNIT_TESTS
89 DEFINES += BUILD_PRIVATE_UNIT_TESTS
84 }
90 }
85
91
86 msvc {
92 msvc {
87 # Suppress "conversion from 'size_t' to 'int', possible loss of data" warnings in 64bit
93 # Suppress "conversion from 'size_t' to 'int', possible loss of data" warnings in 64bit
88 # builds resulting from usage of str::sort
94 # builds resulting from usage of str::sort
89 QMAKE_CXXFLAGS_WARN_ON += -wd4267
95 QMAKE_CXXFLAGS_WARN_ON += -wd4267
90 }
96 }
91
97
92 win32:!winrt:!wince {
98 win32:!winrt:!wince {
93 # ChartThemeSystem uses Windows native API
99 # ChartThemeSystem uses Windows native API
94 LIBS += -luser32
100 LIBS += -luser32
95 }
101 }
@@ -1,130 +1,130
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 // W A R N I N G
19 // W A R N I N G
20 // -------------
20 // -------------
21 //
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
24 // version without notice, or even be removed.
25 //
25 //
26 // We mean it.
26 // We mean it.
27
27
28 #ifndef ABSTRACTDOMAIN_H
28 #ifndef ABSTRACTDOMAIN_H
29 #define ABSTRACTDOMAIN_H
29 #define ABSTRACTDOMAIN_H
30 #include <QtCharts/QChartGlobal>
30 #include <QtCharts/QChartGlobal>
31 #include <QtCore/QRectF>
31 #include <QtCore/QRectF>
32 #include <QtCore/QSizeF>
32 #include <QtCore/QSizeF>
33 #include <QtCore/QDebug>
33 #include <QtCore/QDebug>
34
34
35 QT_CHARTS_BEGIN_NAMESPACE
35 QT_CHARTS_BEGIN_NAMESPACE
36
36
37 class QAbstractAxis;
37 class QAbstractAxis;
38
38
39 class QT_CHARTS_AUTOTEST_EXPORT AbstractDomain: public QObject
39 class QT_CHARTS_AUTOTEST_EXPORT AbstractDomain: public QObject
40 {
40 {
41 Q_OBJECT
41 Q_OBJECT
42 public:
42 public:
43 enum DomainType { UndefinedDomain,
43 enum DomainType { UndefinedDomain,
44 XYDomain,
44 XYDomain,
45 XLogYDomain,
45 XLogYDomain,
46 LogXYDomain,
46 LogXYDomain,
47 LogXLogYDomain,
47 LogXLogYDomain,
48 XYPolarDomain,
48 XYPolarDomain,
49 XLogYPolarDomain,
49 XLogYPolarDomain,
50 LogXYPolarDomain,
50 LogXYPolarDomain,
51 LogXLogYPolarDomain };
51 LogXLogYPolarDomain };
52 public:
52 public:
53 explicit AbstractDomain(QObject *object = 0);
53 explicit AbstractDomain(QObject *object = 0);
54 virtual ~AbstractDomain();
54 virtual ~AbstractDomain();
55
55
56 virtual void setSize(const QSizeF &size);
56 virtual void setSize(const QSizeF &size);
57 QSizeF size() const;
57 QSizeF size() const;
58
58
59 virtual DomainType type() = 0;
59 virtual DomainType type() = 0;
60
60
61 virtual void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) = 0;
61 virtual void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) = 0;
62 void setRangeX(qreal min, qreal max);
62 void setRangeX(qreal min, qreal max);
63 void setRangeY(qreal min, qreal max);
63 void setRangeY(qreal min, qreal max);
64 void setMinX(qreal min);
64 void setMinX(qreal min);
65 void setMaxX(qreal max);
65 void setMaxX(qreal max);
66 void setMinY(qreal min);
66 void setMinY(qreal min);
67 void setMaxY(qreal max);
67 void setMaxY(qreal max);
68
68
69 qreal minX() const { return m_minX; }
69 qreal minX() const { return m_minX; }
70 qreal maxX() const { return m_maxX; }
70 qreal maxX() const { return m_maxX; }
71 qreal minY() const { return m_minY; }
71 qreal minY() const { return m_minY; }
72 qreal maxY() const { return m_maxY; }
72 qreal maxY() const { return m_maxY; }
73
73
74 qreal spanX() const;
74 qreal spanX() const;
75 qreal spanY() const;
75 qreal spanY() const;
76 bool isEmpty() const;
76 bool isEmpty() const;
77
77
78 void blockRangeSignals(bool block);
78 void blockRangeSignals(bool block);
79 bool rangeSignalsBlocked() const { return m_signalsBlocked; }
79 bool rangeSignalsBlocked() const { return m_signalsBlocked; }
80
80
81 void zoomReset();
81 void zoomReset();
82 void storeZoomReset();
82 void storeZoomReset();
83 bool isZoomed() { return m_zoomed; }
83 bool isZoomed() { return m_zoomed; }
84
84
85 friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2);
85 friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2);
86 friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2);
86 friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2);
87 friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain);
87 friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain);
88
88
89 virtual void zoomIn(const QRectF &rect) = 0;
89 virtual void zoomIn(const QRectF &rect) = 0;
90 virtual void zoomOut(const QRectF &rect) = 0;
90 virtual void zoomOut(const QRectF &rect) = 0;
91 virtual void move(qreal dx, qreal dy) = 0;
91 virtual void move(qreal dx, qreal dy) = 0;
92
92
93 virtual QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const = 0;
93 virtual QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const = 0;
94 virtual QPointF calculateDomainPoint(const QPointF &point) const = 0;
94 virtual QPointF calculateDomainPoint(const QPointF &point) const = 0;
95 virtual QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const = 0;
95 virtual QVector<QPointF> calculateGeometryPoints(const QVector<QPointF> &vector) const = 0;
96
96
97 virtual bool attachAxis(QAbstractAxis *axis);
97 virtual bool attachAxis(QAbstractAxis *axis);
98 virtual bool detachAxis(QAbstractAxis *axis);
98 virtual bool detachAxis(QAbstractAxis *axis);
99
99
100 static void looseNiceNumbers(qreal &min, qreal &max, int &ticksCount);
100 static void looseNiceNumbers(qreal &min, qreal &max, int &ticksCount);
101 static qreal niceNumber(qreal x, bool ceiling);
101 static qreal niceNumber(qreal x, bool ceiling);
102
102
103 Q_SIGNALS:
103 Q_SIGNALS:
104 void updated();
104 void updated();
105 void rangeHorizontalChanged(qreal min, qreal max);
105 void rangeHorizontalChanged(qreal min, qreal max);
106 void rangeVerticalChanged(qreal min, qreal max);
106 void rangeVerticalChanged(qreal min, qreal max);
107
107
108 public Q_SLOTS:
108 public Q_SLOTS:
109 void handleVerticalAxisRangeChanged(qreal min,qreal max);
109 void handleVerticalAxisRangeChanged(qreal min,qreal max);
110 void handleHorizontalAxisRangeChanged(qreal min,qreal max);
110 void handleHorizontalAxisRangeChanged(qreal min,qreal max);
111
111
112 protected:
112 protected:
113 void adjustLogDomainRanges(qreal &min, qreal &max);
113 void adjustLogDomainRanges(qreal &min, qreal &max);
114
114
115 qreal m_minX;
115 qreal m_minX;
116 qreal m_maxX;
116 qreal m_maxX;
117 qreal m_minY;
117 qreal m_minY;
118 qreal m_maxY;
118 qreal m_maxY;
119 QSizeF m_size;
119 QSizeF m_size;
120 bool m_signalsBlocked;
120 bool m_signalsBlocked;
121 bool m_zoomed;
121 bool m_zoomed;
122 qreal m_zoomResetMinX;
122 qreal m_zoomResetMinX;
123 qreal m_zoomResetMaxX;
123 qreal m_zoomResetMaxX;
124 qreal m_zoomResetMinY;
124 qreal m_zoomResetMinY;
125 qreal m_zoomResetMaxY;
125 qreal m_zoomResetMaxY;
126 };
126 };
127
127
128 QT_CHARTS_END_NAMESPACE
128 QT_CHARTS_END_NAMESPACE
129
129
130 #endif // ABSTRACTDOMAIN_H
130 #endif // ABSTRACTDOMAIN_H
@@ -1,277 +1,277
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/logxlogydomain_p.h>
19 #include <private/logxlogydomain_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <QtCharts/QLogValueAxis>
21 #include <QtCharts/QLogValueAxis>
22 #include <QtCore/QtMath>
22 #include <QtCore/QtMath>
23 #include <cmath>
23 #include <cmath>
24
24
25 QT_CHARTS_BEGIN_NAMESPACE
25 QT_CHARTS_BEGIN_NAMESPACE
26
26
27 LogXLogYDomain::LogXLogYDomain(QObject *parent)
27 LogXLogYDomain::LogXLogYDomain(QObject *parent)
28 : AbstractDomain(parent),
28 : AbstractDomain(parent),
29 m_logLeftX(0),
29 m_logLeftX(0),
30 m_logRightX(1),
30 m_logRightX(1),
31 m_logBaseX(10),
31 m_logBaseX(10),
32 m_logLeftY(0),
32 m_logLeftY(0),
33 m_logRightY(1),
33 m_logRightY(1),
34 m_logBaseY(10)
34 m_logBaseY(10)
35 {
35 {
36 }
36 }
37
37
38 LogXLogYDomain::~LogXLogYDomain()
38 LogXLogYDomain::~LogXLogYDomain()
39 {
39 {
40 }
40 }
41
41
42 void LogXLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
42 void LogXLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
43 {
43 {
44 bool axisXChanged = false;
44 bool axisXChanged = false;
45 bool axisYChanged = false;
45 bool axisYChanged = false;
46
46
47 adjustLogDomainRanges(minX, maxX);
47 adjustLogDomainRanges(minX, maxX);
48 adjustLogDomainRanges(minY, maxY);
48 adjustLogDomainRanges(minY, maxY);
49
49
50 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
50 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
51 m_minX = minX;
51 m_minX = minX;
52 m_maxX = maxX;
52 m_maxX = maxX;
53 axisXChanged = true;
53 axisXChanged = true;
54 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
54 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
55 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
55 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
56 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
56 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
57 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
57 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
58 if(!m_signalsBlocked)
58 if(!m_signalsBlocked)
59 emit rangeHorizontalChanged(m_minX, m_maxX);
59 emit rangeHorizontalChanged(m_minX, m_maxX);
60 }
60 }
61
61
62 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
62 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
63 m_minY = minY;
63 m_minY = minY;
64 m_maxY = maxY;
64 m_maxY = maxY;
65 axisYChanged = true;
65 axisYChanged = true;
66 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
66 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
67 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
67 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
68 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
68 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
69 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
69 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
70 if (!m_signalsBlocked)
70 if (!m_signalsBlocked)
71 emit rangeVerticalChanged(m_minY, m_maxY);
71 emit rangeVerticalChanged(m_minY, m_maxY);
72 }
72 }
73
73
74 if (axisXChanged || axisYChanged)
74 if (axisXChanged || axisYChanged)
75 emit updated();
75 emit updated();
76 }
76 }
77
77
78 void LogXLogYDomain::zoomIn(const QRectF &rect)
78 void LogXLogYDomain::zoomIn(const QRectF &rect)
79 {
79 {
80 storeZoomReset();
80 storeZoomReset();
81 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
81 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
82 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
82 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
83 qreal leftX = qPow(m_logBaseX, logLeftX);
83 qreal leftX = qPow(m_logBaseX, logLeftX);
84 qreal rightX = qPow(m_logBaseX, logRightX);
84 qreal rightX = qPow(m_logBaseX, logRightX);
85 qreal minX = leftX < rightX ? leftX : rightX;
85 qreal minX = leftX < rightX ? leftX : rightX;
86 qreal maxX = leftX > rightX ? leftX : rightX;
86 qreal maxX = leftX > rightX ? leftX : rightX;
87
87
88 qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
88 qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
89 qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
89 qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
90 qreal leftY = qPow(m_logBaseY, logLeftY);
90 qreal leftY = qPow(m_logBaseY, logLeftY);
91 qreal rightY = qPow(m_logBaseY, logRightY);
91 qreal rightY = qPow(m_logBaseY, logRightY);
92 qreal minY = leftY < rightY ? leftY : rightY;
92 qreal minY = leftY < rightY ? leftY : rightY;
93 qreal maxY = leftY > rightY ? leftY : rightY;
93 qreal maxY = leftY > rightY ? leftY : rightY;
94
94
95 setRange(minX, maxX, minY, maxY);
95 setRange(minX, maxX, minY, maxY);
96 }
96 }
97
97
98 void LogXLogYDomain::zoomOut(const QRectF &rect)
98 void LogXLogYDomain::zoomOut(const QRectF &rect)
99 {
99 {
100 storeZoomReset();
100 storeZoomReset();
101 const qreal factorX = m_size.width() / rect.width();
101 const qreal factorX = m_size.width() / rect.width();
102 const qreal factorY = m_size.height() / rect.height();
102 const qreal factorY = m_size.height() / rect.height();
103
103
104 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
104 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
105 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
105 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
106 qreal leftX = qPow(m_logBaseX, logLeftX);
106 qreal leftX = qPow(m_logBaseX, logLeftX);
107 qreal rightX = qPow(m_logBaseX, logRIghtX);
107 qreal rightX = qPow(m_logBaseX, logRIghtX);
108 qreal minX = leftX < rightX ? leftX : rightX;
108 qreal minX = leftX < rightX ? leftX : rightX;
109 qreal maxX = leftX > rightX ? leftX : rightX;
109 qreal maxX = leftX > rightX ? leftX : rightX;
110
110
111 qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
111 qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
112 qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
112 qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
113 qreal leftY = qPow(m_logBaseY, newLogMinY);
113 qreal leftY = qPow(m_logBaseY, newLogMinY);
114 qreal rightY = qPow(m_logBaseY, newLogMaxY);
114 qreal rightY = qPow(m_logBaseY, newLogMaxY);
115 qreal minY = leftY < rightY ? leftY : rightY;
115 qreal minY = leftY < rightY ? leftY : rightY;
116 qreal maxY = leftY > rightY ? leftY : rightY;
116 qreal maxY = leftY > rightY ? leftY : rightY;
117
117
118 setRange(minX, maxX, minY, maxY);
118 setRange(minX, maxX, minY, maxY);
119 }
119 }
120
120
121 void LogXLogYDomain::move(qreal dx, qreal dy)
121 void LogXLogYDomain::move(qreal dx, qreal dy)
122 {
122 {
123 qreal stepX = dx * qAbs(m_logRightX - m_logLeftX) / m_size.width();
123 qreal stepX = dx * qAbs(m_logRightX - m_logLeftX) / m_size.width();
124 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
124 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
125 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
125 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
126 qreal minX = leftX < rightX ? leftX : rightX;
126 qreal minX = leftX < rightX ? leftX : rightX;
127 qreal maxX = leftX > rightX ? leftX : rightX;
127 qreal maxX = leftX > rightX ? leftX : rightX;
128
128
129 qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
129 qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
130 qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
130 qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
131 qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
131 qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
132 qreal minY = leftY < rightY ? leftY : rightY;
132 qreal minY = leftY < rightY ? leftY : rightY;
133 qreal maxY = leftY > rightY ? leftY : rightY;
133 qreal maxY = leftY > rightY ? leftY : rightY;
134
134
135 setRange(minX, maxX, minY, maxY);
135 setRange(minX, maxX, minY, maxY);
136 }
136 }
137
137
138 QPointF LogXLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
138 QPointF LogXLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
139 {
139 {
140 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
140 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
141 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
141 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
142 qreal x(0);
142 qreal x(0);
143 qreal y(0);
143 qreal y(0);
144 if (point.x() > 0 && point.y() > 0) {
144 if (point.x() > 0 && point.y() > 0) {
145 x = (std::log10(point.x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
145 x = (std::log10(point.x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
146 y = (std::log10(point.y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
146 y = (std::log10(point.y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
147 ok = true;
147 ok = true;
148 } else {
148 } else {
149 qWarning() << "Logarithms of zero and negative values are undefined.";
149 qWarning() << "Logarithms of zero and negative values are undefined.";
150 ok = false;
150 ok = false;
151 if (point.x() > 0)
151 if (point.x() > 0)
152 x = (std::log10(point.x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
152 x = (std::log10(point.x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
153 else
153 else
154 x = 0;
154 x = 0;
155 if (point.y() > 0) {
155 if (point.y() > 0) {
156 y = (std::log10(point.y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY
156 y = (std::log10(point.y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY
157 + m_size.height();
157 + m_size.height();
158 } else {
158 } else {
159 y = m_size.height();
159 y = m_size.height();
160 }
160 }
161 }
161 }
162 return QPointF(x, y);
162 return QPointF(x, y);
163 }
163 }
164
164
165 QVector<QPointF> LogXLogYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
165 QVector<QPointF> LogXLogYDomain::calculateGeometryPoints(const QVector<QPointF> &vector) const
166 {
166 {
167 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
167 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
168 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
168 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
169
169
170 QVector<QPointF> result;
170 QVector<QPointF> result;
171 result.resize(vector.count());
171 result.resize(vector.count());
172
172
173 for (int i = 0; i < vector.count(); ++i) {
173 for (int i = 0; i < vector.count(); ++i) {
174 if (vector[i].x() > 0 && vector[i].y() > 0) {
174 if (vector[i].x() > 0 && vector[i].y() > 0) {
175 qreal x = (std::log10(vector[i].x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
175 qreal x = (std::log10(vector[i].x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
176 qreal y = (std::log10(vector[i].y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
176 qreal y = (std::log10(vector[i].y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
177 result[i].setX(x);
177 result[i].setX(x);
178 result[i].setY(y);
178 result[i].setY(y);
179 } else {
179 } else {
180 qWarning() << "Logarithms of zero and negative values are undefined.";
180 qWarning() << "Logarithms of zero and negative values are undefined.";
181 return QVector<QPointF>();
181 return QVector<QPointF>();
182 }
182 }
183 }
183 }
184 return result;
184 return result;
185 }
185 }
186
186
187 QPointF LogXLogYDomain::calculateDomainPoint(const QPointF &point) const
187 QPointF LogXLogYDomain::calculateDomainPoint(const QPointF &point) const
188 {
188 {
189 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
189 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
190 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
190 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
191 qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
191 qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
192 qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
192 qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
193 return QPointF(x, y);
193 return QPointF(x, y);
194 }
194 }
195
195
196 bool LogXLogYDomain::attachAxis(QAbstractAxis *axis)
196 bool LogXLogYDomain::attachAxis(QAbstractAxis *axis)
197 {
197 {
198 AbstractDomain::attachAxis(axis);
198 AbstractDomain::attachAxis(axis);
199 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
199 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
200
200
201 if (logAxis && logAxis->orientation() == Qt::Vertical) {
201 if (logAxis && logAxis->orientation() == Qt::Vertical) {
202 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
202 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
203 handleVerticalAxisBaseChanged(logAxis->base());
203 handleVerticalAxisBaseChanged(logAxis->base());
204 }
204 }
205
205
206 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
206 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
207 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
207 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
208 handleHorizontalAxisBaseChanged(logAxis->base());
208 handleHorizontalAxisBaseChanged(logAxis->base());
209 }
209 }
210
210
211 return true;
211 return true;
212 }
212 }
213
213
214 bool LogXLogYDomain::detachAxis(QAbstractAxis *axis)
214 bool LogXLogYDomain::detachAxis(QAbstractAxis *axis)
215 {
215 {
216 AbstractDomain::detachAxis(axis);
216 AbstractDomain::detachAxis(axis);
217 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
217 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
218
218
219 if (logAxis && logAxis->orientation() == Qt::Vertical)
219 if (logAxis && logAxis->orientation() == Qt::Vertical)
220 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
220 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
221
221
222 if (logAxis && logAxis->orientation() == Qt::Horizontal)
222 if (logAxis && logAxis->orientation() == Qt::Horizontal)
223 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
223 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
224
224
225 return true;
225 return true;
226 }
226 }
227
227
228 void LogXLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
228 void LogXLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
229 {
229 {
230 m_logBaseY = baseY;
230 m_logBaseY = baseY;
231 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
231 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
232 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
232 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
233 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
233 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
234 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
234 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
235 emit updated();
235 emit updated();
236 }
236 }
237
237
238 void LogXLogYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
238 void LogXLogYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
239 {
239 {
240 m_logBaseX = baseX;
240 m_logBaseX = baseX;
241 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
241 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
242 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
242 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
243 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
243 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
244 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
244 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
245 emit updated();
245 emit updated();
246 }
246 }
247
247
248 // operators
248 // operators
249
249
250 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
250 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
251 {
251 {
252 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
252 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
253 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
253 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
254 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
254 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
255 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
255 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
256 }
256 }
257
257
258
258
259 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
259 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
260 {
260 {
261 return !(domain1 == domain2);
261 return !(domain1 == domain2);
262 }
262 }
263
263
264
264
265 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYDomain &domain)
265 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYDomain &domain)
266 {
266 {
267 #ifdef QT_NO_TEXTSTREAM
267 #ifdef QT_NO_TEXTSTREAM
268 Q_UNUSED(domain)
268 Q_UNUSED(domain)
269 #else
269 #else
270 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
270 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
271 #endif
271 #endif
272 return dbg.maybeSpace();
272 return dbg.maybeSpace();
273 }
273 }
274
274
275 #include "moc_logxlogydomain_p.cpp"
275 #include "moc_logxlogydomain_p.cpp"
276
276
277 QT_CHARTS_END_NAMESPACE
277 QT_CHARTS_END_NAMESPACE
@@ -1,77 +1,77
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 // W A R N I N G
19 // W A R N I N G
20 // -------------
20 // -------------
21 //
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
24 // version without notice, or even be removed.
25 //
25 //
26 // We mean it.
26 // We mean it.
27
27
28 #ifndef LOGXLOGYDOMAIN_H
28 #ifndef LOGXLOGYDOMAIN_H
29 #define LOGXLOGYDOMAIN_H
29 #define LOGXLOGYDOMAIN_H
30 #include <private/abstractdomain_p.h>
30 #include <private/abstractdomain_p.h>
31 #include <QtCore/QRectF>
31 #include <QtCore/QRectF>
32 #include <QtCore/QSizeF>
32 #include <QtCore/QSizeF>
33
33
34 QT_CHARTS_BEGIN_NAMESPACE
34 QT_CHARTS_BEGIN_NAMESPACE
35
35
36 class QT_CHARTS_AUTOTEST_EXPORT LogXLogYDomain: public AbstractDomain
36 class QT_CHARTS_AUTOTEST_EXPORT LogXLogYDomain: public AbstractDomain
37 {
37 {
38 Q_OBJECT
38 Q_OBJECT
39 public:
39 public:
40 explicit LogXLogYDomain(QObject *object = 0);
40 explicit LogXLogYDomain(QObject *object = 0);
41 virtual ~LogXLogYDomain();
41 virtual ~LogXLogYDomain();
42
42
43 DomainType type(){ return AbstractDomain::LogXLogYDomain;}
43 DomainType type(){ return AbstractDomain::LogXLogYDomain;}
44
44
45 void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
45 void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
46
46
47 friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2);
47 friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2);
48 friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2);
48 friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2);
49 friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYDomain &domain);
49 friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYDomain &domain);
50
50
51 void zoomIn(const QRectF &rect);
51 void zoomIn(const QRectF &rect);
52 void zoomOut(const QRectF &rect);
52 void zoomOut(const QRectF &rect);
53 void move(qreal dx, qreal dy);
53 void move(qreal dx, qreal dy);
54
54
55 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
55 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
56 QPointF calculateDomainPoint(const QPointF &point) const;
56 QPointF calculateDomainPoint(const QPointF &point) const;
57 QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
57 QVector<QPointF> calculateGeometryPoints(const QVector<QPointF> &vector) const;
58
58
59 bool attachAxis(QAbstractAxis *axis);
59 bool attachAxis(QAbstractAxis *axis);
60 bool detachAxis(QAbstractAxis *axis);
60 bool detachAxis(QAbstractAxis *axis);
61
61
62 public Q_SLOTS:
62 public Q_SLOTS:
63 void handleVerticalAxisBaseChanged(qreal baseY);
63 void handleVerticalAxisBaseChanged(qreal baseY);
64 void handleHorizontalAxisBaseChanged(qreal baseX);
64 void handleHorizontalAxisBaseChanged(qreal baseX);
65
65
66 private:
66 private:
67 qreal m_logLeftX;
67 qreal m_logLeftX;
68 qreal m_logRightX;
68 qreal m_logRightX;
69 qreal m_logBaseX;
69 qreal m_logBaseX;
70 qreal m_logLeftY;
70 qreal m_logLeftY;
71 qreal m_logRightY;
71 qreal m_logRightY;
72 qreal m_logBaseY;
72 qreal m_logBaseY;
73 };
73 };
74
74
75 QT_CHARTS_END_NAMESPACE
75 QT_CHARTS_END_NAMESPACE
76
76
77 #endif // LOGXLOGYDOMAIN_H
77 #endif // LOGXLOGYDOMAIN_H
@@ -1,244 +1,244
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/logxydomain_p.h>
19 #include <private/logxydomain_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <QtCharts/QLogValueAxis>
21 #include <QtCharts/QLogValueAxis>
22 #include <QtCore/QtMath>
22 #include <QtCore/QtMath>
23 #include <cmath>
23 #include <cmath>
24
24
25 QT_CHARTS_BEGIN_NAMESPACE
25 QT_CHARTS_BEGIN_NAMESPACE
26
26
27 LogXYDomain::LogXYDomain(QObject *parent)
27 LogXYDomain::LogXYDomain(QObject *parent)
28 : AbstractDomain(parent),
28 : AbstractDomain(parent),
29 m_logLeftX(0),
29 m_logLeftX(0),
30 m_logRightX(1),
30 m_logRightX(1),
31 m_logBaseX(10)
31 m_logBaseX(10)
32 {
32 {
33 }
33 }
34
34
35 LogXYDomain::~LogXYDomain()
35 LogXYDomain::~LogXYDomain()
36 {
36 {
37 }
37 }
38
38
39 void LogXYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
39 void LogXYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
40 {
40 {
41 bool axisXChanged = false;
41 bool axisXChanged = false;
42 bool axisYChanged = false;
42 bool axisYChanged = false;
43
43
44 adjustLogDomainRanges(minX, maxX);
44 adjustLogDomainRanges(minX, maxX);
45
45
46 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
46 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
47 m_minX = minX;
47 m_minX = minX;
48 m_maxX = maxX;
48 m_maxX = maxX;
49 axisXChanged = true;
49 axisXChanged = true;
50 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
50 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
51 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
51 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
52 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
52 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
53 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
53 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
54 if(!m_signalsBlocked)
54 if(!m_signalsBlocked)
55 emit rangeHorizontalChanged(m_minX, m_maxX);
55 emit rangeHorizontalChanged(m_minX, m_maxX);
56 }
56 }
57
57
58 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
58 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
59 m_minY = minY;
59 m_minY = minY;
60 m_maxY = maxY;
60 m_maxY = maxY;
61 axisYChanged = true;
61 axisYChanged = true;
62 if (!m_signalsBlocked)
62 if (!m_signalsBlocked)
63 emit rangeVerticalChanged(m_minY, m_maxY);
63 emit rangeVerticalChanged(m_minY, m_maxY);
64 }
64 }
65
65
66 if (axisXChanged || axisYChanged)
66 if (axisXChanged || axisYChanged)
67 emit updated();
67 emit updated();
68 }
68 }
69
69
70 void LogXYDomain::zoomIn(const QRectF &rect)
70 void LogXYDomain::zoomIn(const QRectF &rect)
71 {
71 {
72 storeZoomReset();
72 storeZoomReset();
73 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
73 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
74 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
74 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
75 qreal leftX = qPow(m_logBaseX, logLeftX);
75 qreal leftX = qPow(m_logBaseX, logLeftX);
76 qreal rightX = qPow(m_logBaseX, logRightX);
76 qreal rightX = qPow(m_logBaseX, logRightX);
77 qreal minX = leftX < rightX ? leftX : rightX;
77 qreal minX = leftX < rightX ? leftX : rightX;
78 qreal maxX = leftX > rightX ? leftX : rightX;
78 qreal maxX = leftX > rightX ? leftX : rightX;
79
79
80 qreal dy = spanY() / m_size.height();
80 qreal dy = spanY() / m_size.height();
81 qreal minY = m_minY;
81 qreal minY = m_minY;
82 qreal maxY = m_maxY;
82 qreal maxY = m_maxY;
83
83
84 minY = maxY - dy * rect.bottom();
84 minY = maxY - dy * rect.bottom();
85 maxY = maxY - dy * rect.top();
85 maxY = maxY - dy * rect.top();
86
86
87 setRange(minX, maxX, minY, maxY);
87 setRange(minX, maxX, minY, maxY);
88 }
88 }
89
89
90 void LogXYDomain::zoomOut(const QRectF &rect)
90 void LogXYDomain::zoomOut(const QRectF &rect)
91 {
91 {
92 storeZoomReset();
92 storeZoomReset();
93 const qreal factorX = m_size.width() / rect.width();
93 const qreal factorX = m_size.width() / rect.width();
94
94
95 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
95 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
96 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
96 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
97 qreal leftX = qPow(m_logBaseX, logLeftX);
97 qreal leftX = qPow(m_logBaseX, logLeftX);
98 qreal rightX = qPow(m_logBaseX, logRIghtX);
98 qreal rightX = qPow(m_logBaseX, logRIghtX);
99 qreal minX = leftX < rightX ? leftX : rightX;
99 qreal minX = leftX < rightX ? leftX : rightX;
100 qreal maxX = leftX > rightX ? leftX : rightX;
100 qreal maxX = leftX > rightX ? leftX : rightX;
101
101
102 qreal dy = spanY() / rect.height();
102 qreal dy = spanY() / rect.height();
103 qreal minY = m_minY;
103 qreal minY = m_minY;
104 qreal maxY = m_maxY;
104 qreal maxY = m_maxY;
105
105
106 maxY = minY + dy * rect.bottom();
106 maxY = minY + dy * rect.bottom();
107 minY = maxY - dy * m_size.height();
107 minY = maxY - dy * m_size.height();
108
108
109 setRange(minX, maxX, minY, maxY);
109 setRange(minX, maxX, minY, maxY);
110 }
110 }
111
111
112 void LogXYDomain::move(qreal dx, qreal dy)
112 void LogXYDomain::move(qreal dx, qreal dy)
113 {
113 {
114 qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
114 qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
115 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
115 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
116 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
116 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
117 qreal minX = leftX < rightX ? leftX : rightX;
117 qreal minX = leftX < rightX ? leftX : rightX;
118 qreal maxX = leftX > rightX ? leftX : rightX;
118 qreal maxX = leftX > rightX ? leftX : rightX;
119
119
120 qreal y = spanY() / m_size.height();
120 qreal y = spanY() / m_size.height();
121 qreal minY = m_minY;
121 qreal minY = m_minY;
122 qreal maxY = m_maxY;
122 qreal maxY = m_maxY;
123
123
124 if (dy != 0) {
124 if (dy != 0) {
125 minY = minY + y * dy;
125 minY = minY + y * dy;
126 maxY = maxY + y * dy;
126 maxY = maxY + y * dy;
127 }
127 }
128 setRange(minX, maxX, minY, maxY);
128 setRange(minX, maxX, minY, maxY);
129 }
129 }
130
130
131 QPointF LogXYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
131 QPointF LogXYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
132 {
132 {
133 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
133 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
134 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
134 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
135
135
136 qreal x(0);
136 qreal x(0);
137 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
137 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
138 if (point.x() > 0) {
138 if (point.x() > 0) {
139 x = (std::log10(point.x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
139 x = (std::log10(point.x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
140 ok = true;
140 ok = true;
141 } else {
141 } else {
142 x = 0;
142 x = 0;
143 qWarning() << "Logarithms of zero and negative values are undefined.";
143 qWarning() << "Logarithms of zero and negative values are undefined.";
144 ok = false;
144 ok = false;
145 }
145 }
146 return QPointF(x, y);
146 return QPointF(x, y);
147 }
147 }
148
148
149 QVector<QPointF> LogXYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
149 QVector<QPointF> LogXYDomain::calculateGeometryPoints(const QVector<QPointF> &vector) const
150 {
150 {
151 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
151 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
152 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
152 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
153
153
154 QVector<QPointF> result;
154 QVector<QPointF> result;
155 result.resize(vector.count());
155 result.resize(vector.count());
156
156
157 for (int i = 0; i < vector.count(); ++i) {
157 for (int i = 0; i < vector.count(); ++i) {
158 if (vector[i].x() > 0) {
158 if (vector[i].x() > 0) {
159 qreal x = (std::log10(vector[i].x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
159 qreal x = (std::log10(vector[i].x()) / std::log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
160 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
160 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
161 result[i].setX(x);
161 result[i].setX(x);
162 result[i].setY(y);
162 result[i].setY(y);
163 } else {
163 } else {
164 qWarning() << "Logarithms of zero and negative values are undefined.";
164 qWarning() << "Logarithms of zero and negative values are undefined.";
165 return QVector<QPointF>();
165 return QVector<QPointF>();
166 }
166 }
167
167
168 }
168 }
169 return result;
169 return result;
170 }
170 }
171
171
172 QPointF LogXYDomain::calculateDomainPoint(const QPointF &point) const
172 QPointF LogXYDomain::calculateDomainPoint(const QPointF &point) const
173 {
173 {
174 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
174 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
175 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
175 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
176 qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
176 qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
177 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
177 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
178 return QPointF(x, y);
178 return QPointF(x, y);
179 }
179 }
180
180
181 bool LogXYDomain::attachAxis(QAbstractAxis *axis)
181 bool LogXYDomain::attachAxis(QAbstractAxis *axis)
182 {
182 {
183 AbstractDomain::attachAxis(axis);
183 AbstractDomain::attachAxis(axis);
184 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
184 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
185
185
186 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
186 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
187 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
187 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
188 handleHorizontalAxisBaseChanged(logAxis->base());
188 handleHorizontalAxisBaseChanged(logAxis->base());
189 }
189 }
190
190
191 return true;
191 return true;
192 }
192 }
193
193
194 bool LogXYDomain::detachAxis(QAbstractAxis *axis)
194 bool LogXYDomain::detachAxis(QAbstractAxis *axis)
195 {
195 {
196 AbstractDomain::detachAxis(axis);
196 AbstractDomain::detachAxis(axis);
197 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
197 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
198
198
199 if (logAxis && logAxis->orientation() == Qt::Horizontal)
199 if (logAxis && logAxis->orientation() == Qt::Horizontal)
200 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
200 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
201
201
202 return true;
202 return true;
203 }
203 }
204
204
205 void LogXYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
205 void LogXYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
206 {
206 {
207 m_logBaseX = baseX;
207 m_logBaseX = baseX;
208 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
208 qreal logMinX = std::log10(m_minX) / std::log10(m_logBaseX);
209 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
209 qreal logMaxX = std::log10(m_maxX) / std::log10(m_logBaseX);
210 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
210 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
211 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
211 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
212 emit updated();
212 emit updated();
213 }
213 }
214
214
215 // operators
215 // operators
216
216
217 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXYDomain &domain1, const LogXYDomain &domain2)
217 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXYDomain &domain1, const LogXYDomain &domain2)
218 {
218 {
219 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
219 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
220 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
220 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
221 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
221 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
222 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
222 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
223 }
223 }
224
224
225
225
226 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXYDomain &domain1, const LogXYDomain &domain2)
226 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXYDomain &domain1, const LogXYDomain &domain2)
227 {
227 {
228 return !(domain1 == domain2);
228 return !(domain1 == domain2);
229 }
229 }
230
230
231
231
232 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYDomain &domain)
232 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYDomain &domain)
233 {
233 {
234 #ifdef QT_NO_TEXTSTREAM
234 #ifdef QT_NO_TEXTSTREAM
235 Q_UNUSED(domain)
235 Q_UNUSED(domain)
236 #else
236 #else
237 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
237 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
238 #endif
238 #endif
239 return dbg.maybeSpace();
239 return dbg.maybeSpace();
240 }
240 }
241
241
242 #include "moc_logxydomain_p.cpp"
242 #include "moc_logxydomain_p.cpp"
243
243
244 QT_CHARTS_END_NAMESPACE
244 QT_CHARTS_END_NAMESPACE
@@ -1,73 +1,73
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 // W A R N I N G
19 // W A R N I N G
20 // -------------
20 // -------------
21 //
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
24 // version without notice, or even be removed.
25 //
25 //
26 // We mean it.
26 // We mean it.
27
27
28 #ifndef LOGXYDOMAIN_H
28 #ifndef LOGXYDOMAIN_H
29 #define LOGXYDOMAIN_H
29 #define LOGXYDOMAIN_H
30 #include <private/abstractdomain_p.h>
30 #include <private/abstractdomain_p.h>
31 #include <QtCore/QRectF>
31 #include <QtCore/QRectF>
32 #include <QtCore/QSizeF>
32 #include <QtCore/QSizeF>
33
33
34 QT_CHARTS_BEGIN_NAMESPACE
34 QT_CHARTS_BEGIN_NAMESPACE
35
35
36 class QT_CHARTS_AUTOTEST_EXPORT LogXYDomain: public AbstractDomain
36 class QT_CHARTS_AUTOTEST_EXPORT LogXYDomain: public AbstractDomain
37 {
37 {
38 Q_OBJECT
38 Q_OBJECT
39 public:
39 public:
40 explicit LogXYDomain(QObject *object = 0);
40 explicit LogXYDomain(QObject *object = 0);
41 virtual ~LogXYDomain();
41 virtual ~LogXYDomain();
42
42
43 DomainType type(){ return AbstractDomain::LogXYDomain;}
43 DomainType type(){ return AbstractDomain::LogXYDomain;}
44
44
45 void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
45 void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
46
46
47 friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXYDomain &domain1, const LogXYDomain &domain2);
47 friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const LogXYDomain &domain1, const LogXYDomain &domain2);
48 friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXYDomain &domain1, const LogXYDomain &domain2);
48 friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const LogXYDomain &domain1, const LogXYDomain &domain2);
49 friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYDomain &domain);
49 friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYDomain &domain);
50
50
51 void zoomIn(const QRectF &rect);
51 void zoomIn(const QRectF &rect);
52 void zoomOut(const QRectF &rect);
52 void zoomOut(const QRectF &rect);
53 void move(qreal dx, qreal dy);
53 void move(qreal dx, qreal dy);
54
54
55 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
55 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
56 QPointF calculateDomainPoint(const QPointF &point) const;
56 QPointF calculateDomainPoint(const QPointF &point) const;
57 QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
57 QVector<QPointF> calculateGeometryPoints(const QVector<QPointF> &vector) const;
58
58
59 bool attachAxis(QAbstractAxis *axis);
59 bool attachAxis(QAbstractAxis *axis);
60 bool detachAxis(QAbstractAxis *axis);
60 bool detachAxis(QAbstractAxis *axis);
61
61
62 public Q_SLOTS:
62 public Q_SLOTS:
63 void handleHorizontalAxisBaseChanged(qreal baseX);
63 void handleHorizontalAxisBaseChanged(qreal baseX);
64
64
65 private:
65 private:
66 qreal m_logLeftX;
66 qreal m_logLeftX;
67 qreal m_logRightX;
67 qreal m_logRightX;
68 qreal m_logBaseX;
68 qreal m_logBaseX;
69 };
69 };
70
70
71 QT_CHARTS_END_NAMESPACE
71 QT_CHARTS_END_NAMESPACE
72
72
73 #endif // LOGXYDOMAIN_H
73 #endif // LOGXYDOMAIN_H
@@ -1,89 +1,89
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/polardomain_p.h>
19 #include <private/polardomain_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <QtCore/QtMath>
21 #include <QtCore/QtMath>
22
22
23 QT_CHARTS_BEGIN_NAMESPACE
23 QT_CHARTS_BEGIN_NAMESPACE
24
24
25 PolarDomain::PolarDomain(QObject *parent)
25 PolarDomain::PolarDomain(QObject *parent)
26 : AbstractDomain(parent)
26 : AbstractDomain(parent)
27 {
27 {
28 }
28 }
29
29
30 PolarDomain::~PolarDomain()
30 PolarDomain::~PolarDomain()
31 {
31 {
32 }
32 }
33
33
34 void PolarDomain::setSize(const QSizeF &size)
34 void PolarDomain::setSize(const QSizeF &size)
35 {
35 {
36 Q_ASSERT(size.width() == size.height());
36 Q_ASSERT(size.width() == size.height());
37 m_radius = size.height() / 2.0;
37 m_radius = size.height() / 2.0;
38 m_center = QPointF(m_radius, m_radius);
38 m_center = QPointF(m_radius, m_radius);
39 AbstractDomain::setSize(size);
39 AbstractDomain::setSize(size);
40 }
40 }
41
41
42 QPointF PolarDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
42 QPointF PolarDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
43 {
43 {
44 qreal r = 0.0;
44 qreal r = 0.0;
45 qreal a = toAngularCoordinate(point.x(), ok);
45 qreal a = toAngularCoordinate(point.x(), ok);
46 if (ok)
46 if (ok)
47 r = toRadialCoordinate(point.y(), ok);
47 r = toRadialCoordinate(point.y(), ok);
48 if (ok) {
48 if (ok) {
49 return m_center + polarCoordinateToPoint(a, r);
49 return m_center + polarCoordinateToPoint(a, r);
50 } else {
50 } else {
51 qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
51 qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
52 return QPointF();
52 return QPointF();
53 }
53 }
54 }
54 }
55
55
56 QVector<QPointF> PolarDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
56 QVector<QPointF> PolarDomain::calculateGeometryPoints(const QVector<QPointF> &vector) const
57 {
57 {
58 QVector<QPointF> result;
58 QVector<QPointF> result;
59 result.resize(vector.count());
59 result.resize(vector.count());
60 bool ok;
60 bool ok;
61 qreal r = 0.0;
61 qreal r = 0.0;
62 qreal a = 0.0;
62 qreal a = 0.0;
63
63
64 for (int i = 0; i < vector.count(); ++i) {
64 for (int i = 0; i < vector.count(); ++i) {
65 a = toAngularCoordinate(vector[i].x(), ok);
65 a = toAngularCoordinate(vector[i].x(), ok);
66 if (ok)
66 if (ok)
67 r = toRadialCoordinate(vector[i].y(), ok);
67 r = toRadialCoordinate(vector[i].y(), ok);
68 if (ok) {
68 if (ok) {
69 result[i] = m_center + polarCoordinateToPoint(a, r);
69 result[i] = m_center + polarCoordinateToPoint(a, r);
70 } else {
70 } else {
71 qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
71 qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
72 return QVector<QPointF>();
72 return QVector<QPointF>();
73 }
73 }
74 }
74 }
75
75
76 return result;
76 return result;
77 }
77 }
78
78
79 QPointF PolarDomain::polarCoordinateToPoint(qreal angularCoordinate, qreal radialCoordinate) const
79 QPointF PolarDomain::polarCoordinateToPoint(qreal angularCoordinate, qreal radialCoordinate) const
80 {
80 {
81 qreal dx = qSin(angularCoordinate * (M_PI / 180)) * radialCoordinate;
81 qreal dx = qSin(angularCoordinate * (M_PI / 180)) * radialCoordinate;
82 qreal dy = qCos(angularCoordinate * (M_PI / 180)) * radialCoordinate;
82 qreal dy = qCos(angularCoordinate * (M_PI / 180)) * radialCoordinate;
83
83
84 return QPointF(dx, -dy);
84 return QPointF(dx, -dy);
85 }
85 }
86
86
87 #include "moc_polardomain_p.cpp"
87 #include "moc_polardomain_p.cpp"
88
88
89 QT_CHARTS_END_NAMESPACE
89 QT_CHARTS_END_NAMESPACE
@@ -1,60 +1,60
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 // W A R N I N G
19 // W A R N I N G
20 // -------------
20 // -------------
21 //
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
24 // version without notice, or even be removed.
25 //
25 //
26 // We mean it.
26 // We mean it.
27
27
28 #ifndef POLARDOMAIN_H
28 #ifndef POLARDOMAIN_H
29 #define POLARDOMAIN_H
29 #define POLARDOMAIN_H
30 #include <private/abstractdomain_p.h>
30 #include <private/abstractdomain_p.h>
31 #include <QtCore/QRectF>
31 #include <QtCore/QRectF>
32 #include <QtCore/QSizeF>
32 #include <QtCore/QSizeF>
33
33
34 QT_CHARTS_BEGIN_NAMESPACE
34 QT_CHARTS_BEGIN_NAMESPACE
35
35
36 class QT_CHARTS_AUTOTEST_EXPORT PolarDomain: public AbstractDomain
36 class QT_CHARTS_AUTOTEST_EXPORT PolarDomain: public AbstractDomain
37 {
37 {
38 Q_OBJECT
38 Q_OBJECT
39 public:
39 public:
40 explicit PolarDomain(QObject *object = 0);
40 explicit PolarDomain(QObject *object = 0);
41 virtual ~PolarDomain();
41 virtual ~PolarDomain();
42
42
43 void setSize(const QSizeF &size);
43 void setSize(const QSizeF &size);
44
44
45 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
45 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
46 QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
46 QVector<QPointF> calculateGeometryPoints(const QVector<QPointF> &vector) const;
47
47
48 virtual qreal toAngularCoordinate(qreal value, bool &ok) const = 0;
48 virtual qreal toAngularCoordinate(qreal value, bool &ok) const = 0;
49 virtual qreal toRadialCoordinate(qreal value, bool &ok) const = 0;
49 virtual qreal toRadialCoordinate(qreal value, bool &ok) const = 0;
50
50
51 protected:
51 protected:
52 QPointF polarCoordinateToPoint(qreal angularCoordinate, qreal radialCoordinate) const;
52 QPointF polarCoordinateToPoint(qreal angularCoordinate, qreal radialCoordinate) const;
53
53
54 QPointF m_center;
54 QPointF m_center;
55 qreal m_radius;
55 qreal m_radius;
56 };
56 };
57
57
58 QT_CHARTS_END_NAMESPACE
58 QT_CHARTS_END_NAMESPACE
59
59
60 #endif // POLARDOMAIN_H
60 #endif // POLARDOMAIN_H
@@ -1,240 +1,240
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/xlogydomain_p.h>
19 #include <private/xlogydomain_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <QtCharts/QLogValueAxis>
21 #include <QtCharts/QLogValueAxis>
22 #include <QtCore/QtMath>
22 #include <QtCore/QtMath>
23 #include <cmath>
23 #include <cmath>
24
24
25 QT_CHARTS_BEGIN_NAMESPACE
25 QT_CHARTS_BEGIN_NAMESPACE
26
26
27 XLogYDomain::XLogYDomain(QObject *parent)
27 XLogYDomain::XLogYDomain(QObject *parent)
28 : AbstractDomain(parent),
28 : AbstractDomain(parent),
29 m_logLeftY(0),
29 m_logLeftY(0),
30 m_logRightY(1),
30 m_logRightY(1),
31 m_logBaseY(10)
31 m_logBaseY(10)
32 {
32 {
33 }
33 }
34
34
35 XLogYDomain::~XLogYDomain()
35 XLogYDomain::~XLogYDomain()
36 {
36 {
37 }
37 }
38
38
39 void XLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
39 void XLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
40 {
40 {
41 bool axisXChanged = false;
41 bool axisXChanged = false;
42 bool axisYChanged = false;
42 bool axisYChanged = false;
43
43
44 adjustLogDomainRanges(minY, maxY);
44 adjustLogDomainRanges(minY, maxY);
45
45
46 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
46 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
47 m_minX = minX;
47 m_minX = minX;
48 m_maxX = maxX;
48 m_maxX = maxX;
49 axisXChanged = true;
49 axisXChanged = true;
50 if(!m_signalsBlocked)
50 if(!m_signalsBlocked)
51 emit rangeHorizontalChanged(m_minX, m_maxX);
51 emit rangeHorizontalChanged(m_minX, m_maxX);
52 }
52 }
53
53
54 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
54 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
55 m_minY = minY;
55 m_minY = minY;
56 m_maxY = maxY;
56 m_maxY = maxY;
57 axisYChanged = true;
57 axisYChanged = true;
58 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
58 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
59 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
59 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
60 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
60 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
61 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
61 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
62 if (!m_signalsBlocked)
62 if (!m_signalsBlocked)
63 emit rangeVerticalChanged(m_minY, m_maxY);
63 emit rangeVerticalChanged(m_minY, m_maxY);
64 }
64 }
65
65
66 if (axisXChanged || axisYChanged)
66 if (axisXChanged || axisYChanged)
67 emit updated();
67 emit updated();
68 }
68 }
69
69
70 void XLogYDomain::zoomIn(const QRectF &rect)
70 void XLogYDomain::zoomIn(const QRectF &rect)
71 {
71 {
72 storeZoomReset();
72 storeZoomReset();
73 qreal dx = spanX() / m_size.width();
73 qreal dx = spanX() / m_size.width();
74 qreal maxX = m_maxX;
74 qreal maxX = m_maxX;
75 qreal minX = m_minX;
75 qreal minX = m_minX;
76
76
77 maxX = minX + dx * rect.right();
77 maxX = minX + dx * rect.right();
78 minX = minX + dx * rect.left();
78 minX = minX + dx * rect.left();
79
79
80 qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
80 qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
81 qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
81 qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
82 qreal leftY = qPow(m_logBaseY, logLeftY);
82 qreal leftY = qPow(m_logBaseY, logLeftY);
83 qreal rightY = qPow(m_logBaseY, logRightY);
83 qreal rightY = qPow(m_logBaseY, logRightY);
84 qreal minY = leftY < rightY ? leftY : rightY;
84 qreal minY = leftY < rightY ? leftY : rightY;
85 qreal maxY = leftY > rightY ? leftY : rightY;
85 qreal maxY = leftY > rightY ? leftY : rightY;
86
86
87 setRange(minX, maxX, minY, maxY);
87 setRange(minX, maxX, minY, maxY);
88 }
88 }
89
89
90 void XLogYDomain::zoomOut(const QRectF &rect)
90 void XLogYDomain::zoomOut(const QRectF &rect)
91 {
91 {
92 storeZoomReset();
92 storeZoomReset();
93 qreal dx = spanX() / rect.width();
93 qreal dx = spanX() / rect.width();
94 qreal maxX = m_maxX;
94 qreal maxX = m_maxX;
95 qreal minX = m_minX;
95 qreal minX = m_minX;
96
96
97 minX = maxX - dx * rect.right();
97 minX = maxX - dx * rect.right();
98 maxX = minX + dx * m_size.width();
98 maxX = minX + dx * m_size.width();
99
99
100 const qreal factorY = m_size.height() / rect.height();
100 const qreal factorY = m_size.height() / rect.height();
101 qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
101 qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
102 qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
102 qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
103 qreal leftY = qPow(m_logBaseY, newLogMinY);
103 qreal leftY = qPow(m_logBaseY, newLogMinY);
104 qreal rightY = qPow(m_logBaseY, newLogMaxY);
104 qreal rightY = qPow(m_logBaseY, newLogMaxY);
105 qreal minY = leftY < rightY ? leftY : rightY;
105 qreal minY = leftY < rightY ? leftY : rightY;
106 qreal maxY = leftY > rightY ? leftY : rightY;
106 qreal maxY = leftY > rightY ? leftY : rightY;
107
107
108 setRange(minX, maxX, minY, maxY);
108 setRange(minX, maxX, minY, maxY);
109 }
109 }
110
110
111 void XLogYDomain::move(qreal dx, qreal dy)
111 void XLogYDomain::move(qreal dx, qreal dy)
112 {
112 {
113 qreal x = spanX() / m_size.width();
113 qreal x = spanX() / m_size.width();
114 qreal maxX = m_maxX;
114 qreal maxX = m_maxX;
115 qreal minX = m_minX;
115 qreal minX = m_minX;
116
116
117 if (dx != 0) {
117 if (dx != 0) {
118 minX = minX + x * dx;
118 minX = minX + x * dx;
119 maxX = maxX + x * dx;
119 maxX = maxX + x * dx;
120 }
120 }
121
121
122 qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
122 qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
123 qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
123 qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
124 qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
124 qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
125 qreal minY = leftY < rightY ? leftY : rightY;
125 qreal minY = leftY < rightY ? leftY : rightY;
126 qreal maxY = leftY > rightY ? leftY : rightY;
126 qreal maxY = leftY > rightY ? leftY : rightY;
127
127
128 setRange(minX, maxX, minY, maxY);
128 setRange(minX, maxX, minY, maxY);
129 }
129 }
130
130
131 QPointF XLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
131 QPointF XLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
132 {
132 {
133 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
133 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
134 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
134 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
135
135
136 qreal x = (point.x() - m_minX) * deltaX;
136 qreal x = (point.x() - m_minX) * deltaX;
137 qreal y(0);
137 qreal y(0);
138 if (point.y() > 0) {
138 if (point.y() > 0) {
139 y = (std::log10(point.y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
139 y = (std::log10(point.y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
140 ok = true;
140 ok = true;
141 } else {
141 } else {
142 y = m_size.height();
142 y = m_size.height();
143 qWarning() << "Logarithms of zero and negative values are undefined.";
143 qWarning() << "Logarithms of zero and negative values are undefined.";
144 ok = false;
144 ok = false;
145 }
145 }
146 return QPointF(x, y);
146 return QPointF(x, y);
147 }
147 }
148
148
149 QVector<QPointF> XLogYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
149 QVector<QPointF> XLogYDomain::calculateGeometryPoints(const QVector<QPointF> &vector) const
150 {
150 {
151 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
151 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
152 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
152 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
153
153
154 QVector<QPointF> result;
154 QVector<QPointF> result;
155 result.resize(vector.count());
155 result.resize(vector.count());
156
156
157 for (int i = 0; i < vector.count(); ++i) {
157 for (int i = 0; i < vector.count(); ++i) {
158 if (vector[i].y() > 0) {
158 if (vector[i].y() > 0) {
159 qreal x = (vector[i].x() - m_minX) * deltaX;
159 qreal x = (vector[i].x() - m_minX) * deltaX;
160 qreal y = (std::log10(vector[i].y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
160 qreal y = (std::log10(vector[i].y()) / std::log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
161 result[i].setX(x);
161 result[i].setX(x);
162 result[i].setY(y);
162 result[i].setY(y);
163 } else {
163 } else {
164 qWarning() << "Logarithms of zero and negative values are undefined.";
164 qWarning() << "Logarithms of zero and negative values are undefined.";
165 return QVector<QPointF>();
165 return QVector<QPointF>();
166 }
166 }
167 }
167 }
168 return result;
168 return result;
169 }
169 }
170
170
171 QPointF XLogYDomain::calculateDomainPoint(const QPointF &point) const
171 QPointF XLogYDomain::calculateDomainPoint(const QPointF &point) const
172 {
172 {
173 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
173 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
174 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
174 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
175 qreal x = point.x() / deltaX + m_minX;
175 qreal x = point.x() / deltaX + m_minX;
176 qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
176 qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
177 return QPointF(x, y);
177 return QPointF(x, y);
178 }
178 }
179
179
180 bool XLogYDomain::attachAxis(QAbstractAxis *axis)
180 bool XLogYDomain::attachAxis(QAbstractAxis *axis)
181 {
181 {
182 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
182 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
183
183
184 if (logAxis && logAxis->orientation() == Qt::Vertical) {
184 if (logAxis && logAxis->orientation() == Qt::Vertical) {
185 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
185 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
186 handleVerticalAxisBaseChanged(logAxis->base());
186 handleVerticalAxisBaseChanged(logAxis->base());
187 }
187 }
188 return AbstractDomain::attachAxis(axis);
188 return AbstractDomain::attachAxis(axis);
189 }
189 }
190
190
191 bool XLogYDomain::detachAxis(QAbstractAxis *axis)
191 bool XLogYDomain::detachAxis(QAbstractAxis *axis)
192 {
192 {
193 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
193 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
194
194
195 if (logAxis && logAxis->orientation() == Qt::Vertical)
195 if (logAxis && logAxis->orientation() == Qt::Vertical)
196 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
196 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
197
197
198 return AbstractDomain::detachAxis(axis);
198 return AbstractDomain::detachAxis(axis);
199 }
199 }
200
200
201 void XLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
201 void XLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
202 {
202 {
203 m_logBaseY = baseY;
203 m_logBaseY = baseY;
204 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
204 qreal logMinY = std::log10(m_minY) / std::log10(m_logBaseY);
205 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
205 qreal logMaxY = std::log10(m_maxY) / std::log10(m_logBaseY);
206 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
206 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
207 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
207 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
208 emit updated();
208 emit updated();
209 }
209 }
210
210
211 // operators
211 // operators
212
212
213 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XLogYDomain &domain1, const XLogYDomain &domain2)
213 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XLogYDomain &domain1, const XLogYDomain &domain2)
214 {
214 {
215 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
215 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
216 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
216 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
217 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
217 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
218 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
218 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
219 }
219 }
220
220
221
221
222 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XLogYDomain &domain1, const XLogYDomain &domain2)
222 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XLogYDomain &domain1, const XLogYDomain &domain2)
223 {
223 {
224 return !(domain1 == domain2);
224 return !(domain1 == domain2);
225 }
225 }
226
226
227
227
228 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYDomain &domain)
228 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYDomain &domain)
229 {
229 {
230 #ifdef QT_NO_TEXTSTREAM
230 #ifdef QT_NO_TEXTSTREAM
231 Q_UNUSED(domain)
231 Q_UNUSED(domain)
232 #else
232 #else
233 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
233 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
234 #endif
234 #endif
235 return dbg.maybeSpace();
235 return dbg.maybeSpace();
236 }
236 }
237
237
238 #include "moc_xlogydomain_p.cpp"
238 #include "moc_xlogydomain_p.cpp"
239
239
240 QT_CHARTS_END_NAMESPACE
240 QT_CHARTS_END_NAMESPACE
@@ -1,73 +1,73
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 // W A R N I N G
19 // W A R N I N G
20 // -------------
20 // -------------
21 //
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
24 // version without notice, or even be removed.
25 //
25 //
26 // We mean it.
26 // We mean it.
27
27
28 #ifndef XLOGYDOMAIN_H
28 #ifndef XLOGYDOMAIN_H
29 #define XLOGYDOMAIN_H
29 #define XLOGYDOMAIN_H
30 #include <private/abstractdomain_p.h>
30 #include <private/abstractdomain_p.h>
31 #include <QtCore/QRectF>
31 #include <QtCore/QRectF>
32 #include <QtCore/QSizeF>
32 #include <QtCore/QSizeF>
33
33
34 QT_CHARTS_BEGIN_NAMESPACE
34 QT_CHARTS_BEGIN_NAMESPACE
35
35
36 class QT_CHARTS_AUTOTEST_EXPORT XLogYDomain: public AbstractDomain
36 class QT_CHARTS_AUTOTEST_EXPORT XLogYDomain: public AbstractDomain
37 {
37 {
38 Q_OBJECT
38 Q_OBJECT
39 public:
39 public:
40 explicit XLogYDomain(QObject *object = 0);
40 explicit XLogYDomain(QObject *object = 0);
41 virtual ~XLogYDomain();
41 virtual ~XLogYDomain();
42
42
43 DomainType type(){ return AbstractDomain::XLogYDomain;};
43 DomainType type(){ return AbstractDomain::XLogYDomain;};
44
44
45 void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
45 void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
46
46
47 friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XLogYDomain &domain1, const XLogYDomain &domain2);
47 friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XLogYDomain &domain1, const XLogYDomain &domain2);
48 friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XLogYDomain &domain1, const XLogYDomain &domain2);
48 friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XLogYDomain &domain1, const XLogYDomain &domain2);
49 friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYDomain &domain);
49 friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYDomain &domain);
50
50
51 void zoomIn(const QRectF &rect);
51 void zoomIn(const QRectF &rect);
52 void zoomOut(const QRectF &rect);
52 void zoomOut(const QRectF &rect);
53 void move(qreal dx, qreal dy);
53 void move(qreal dx, qreal dy);
54
54
55 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
55 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
56 QPointF calculateDomainPoint(const QPointF &point) const;
56 QPointF calculateDomainPoint(const QPointF &point) const;
57 QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
57 QVector<QPointF> calculateGeometryPoints(const QVector<QPointF> &vector) const;
58
58
59 bool attachAxis(QAbstractAxis *axis);
59 bool attachAxis(QAbstractAxis *axis);
60 bool detachAxis(QAbstractAxis *axis);
60 bool detachAxis(QAbstractAxis *axis);
61
61
62 public Q_SLOTS:
62 public Q_SLOTS:
63 void handleVerticalAxisBaseChanged(qreal baseY);
63 void handleVerticalAxisBaseChanged(qreal baseY);
64
64
65 private:
65 private:
66 qreal m_logLeftY;
66 qreal m_logLeftY;
67 qreal m_logRightY;
67 qreal m_logRightY;
68 qreal m_logBaseY;
68 qreal m_logBaseY;
69 };
69 };
70
70
71 QT_CHARTS_END_NAMESPACE
71 QT_CHARTS_END_NAMESPACE
72
72
73 #endif // XLOGYDOMAIN_H
73 #endif // XLOGYDOMAIN_H
@@ -1,202 +1,202
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/xydomain_p.h>
19 #include <private/xydomain_p.h>
20 #include <private/qabstractaxis_p.h>
20 #include <private/qabstractaxis_p.h>
21 #include <QtCore/QtMath>
21 #include <QtCore/QtMath>
22
22
23 QT_CHARTS_BEGIN_NAMESPACE
23 QT_CHARTS_BEGIN_NAMESPACE
24
24
25 XYDomain::XYDomain(QObject *parent)
25 XYDomain::XYDomain(QObject *parent)
26 : AbstractDomain(parent)
26 : AbstractDomain(parent)
27 {
27 {
28 }
28 }
29
29
30 XYDomain::~XYDomain()
30 XYDomain::~XYDomain()
31 {
31 {
32 }
32 }
33
33
34 void XYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
34 void XYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
35 {
35 {
36 bool axisXChanged = false;
36 bool axisXChanged = false;
37 bool axisYChanged = false;
37 bool axisYChanged = false;
38
38
39 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
39 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
40 m_minX = minX;
40 m_minX = minX;
41 m_maxX = maxX;
41 m_maxX = maxX;
42 axisXChanged = true;
42 axisXChanged = true;
43 if(!m_signalsBlocked)
43 if(!m_signalsBlocked)
44 emit rangeHorizontalChanged(m_minX, m_maxX);
44 emit rangeHorizontalChanged(m_minX, m_maxX);
45 }
45 }
46
46
47 if (!qFuzzyCompare(m_minY, minY) || !qFuzzyCompare(m_maxY, maxY)) {
47 if (!qFuzzyCompare(m_minY, minY) || !qFuzzyCompare(m_maxY, maxY)) {
48 m_minY = minY;
48 m_minY = minY;
49 m_maxY = maxY;
49 m_maxY = maxY;
50 axisYChanged = true;
50 axisYChanged = true;
51 if(!m_signalsBlocked)
51 if(!m_signalsBlocked)
52 emit rangeVerticalChanged(m_minY, m_maxY);
52 emit rangeVerticalChanged(m_minY, m_maxY);
53 }
53 }
54
54
55 if (axisXChanged || axisYChanged)
55 if (axisXChanged || axisYChanged)
56 emit updated();
56 emit updated();
57 }
57 }
58
58
59
59
60 void XYDomain::zoomIn(const QRectF &rect)
60 void XYDomain::zoomIn(const QRectF &rect)
61 {
61 {
62 storeZoomReset();
62 storeZoomReset();
63 qreal dx = spanX() / m_size.width();
63 qreal dx = spanX() / m_size.width();
64 qreal dy = spanY() / m_size.height();
64 qreal dy = spanY() / m_size.height();
65
65
66 qreal maxX = m_maxX;
66 qreal maxX = m_maxX;
67 qreal minX = m_minX;
67 qreal minX = m_minX;
68 qreal minY = m_minY;
68 qreal minY = m_minY;
69 qreal maxY = m_maxY;
69 qreal maxY = m_maxY;
70
70
71 maxX = minX + dx * rect.right();
71 maxX = minX + dx * rect.right();
72 minX = minX + dx * rect.left();
72 minX = minX + dx * rect.left();
73 minY = maxY - dy * rect.bottom();
73 minY = maxY - dy * rect.bottom();
74 maxY = maxY - dy * rect.top();
74 maxY = maxY - dy * rect.top();
75
75
76 if ((maxX - minX) == spanX()) {
76 if ((maxX - minX) == spanX()) {
77 minX = m_minX;
77 minX = m_minX;
78 maxX = m_maxX;
78 maxX = m_maxX;
79 }
79 }
80 if ((maxY - minY) == spanY()) {
80 if ((maxY - minY) == spanY()) {
81 minY = m_minY;
81 minY = m_minY;
82 maxY = m_maxY;
82 maxY = m_maxY;
83 }
83 }
84
84
85 setRange(minX, maxX, minY, maxY);
85 setRange(minX, maxX, minY, maxY);
86 }
86 }
87
87
88 void XYDomain::zoomOut(const QRectF &rect)
88 void XYDomain::zoomOut(const QRectF &rect)
89 {
89 {
90 storeZoomReset();
90 storeZoomReset();
91 qreal dx = spanX() / rect.width();
91 qreal dx = spanX() / rect.width();
92 qreal dy = spanY() / rect.height();
92 qreal dy = spanY() / rect.height();
93
93
94 qreal maxX = m_maxX;
94 qreal maxX = m_maxX;
95 qreal minX = m_minX;
95 qreal minX = m_minX;
96 qreal minY = m_minY;
96 qreal minY = m_minY;
97 qreal maxY = m_maxY;
97 qreal maxY = m_maxY;
98
98
99 minX = maxX - dx * rect.right();
99 minX = maxX - dx * rect.right();
100 maxX = minX + dx * m_size.width();
100 maxX = minX + dx * m_size.width();
101 maxY = minY + dy * rect.bottom();
101 maxY = minY + dy * rect.bottom();
102 minY = maxY - dy * m_size.height();
102 minY = maxY - dy * m_size.height();
103
103
104 if ((maxX - minX) == spanX()) {
104 if ((maxX - minX) == spanX()) {
105 minX = m_minX;
105 minX = m_minX;
106 maxX = m_maxX;
106 maxX = m_maxX;
107 }
107 }
108 if ((maxY - minY) == spanY()) {
108 if ((maxY - minY) == spanY()) {
109 minY = m_minY;
109 minY = m_minY;
110 maxY = m_maxY;
110 maxY = m_maxY;
111 }
111 }
112
112
113 setRange(minX, maxX, minY, maxY);
113 setRange(minX, maxX, minY, maxY);
114 }
114 }
115
115
116 void XYDomain::move(qreal dx, qreal dy)
116 void XYDomain::move(qreal dx, qreal dy)
117 {
117 {
118 qreal x = spanX() / m_size.width();
118 qreal x = spanX() / m_size.width();
119 qreal y = spanY() / m_size.height();
119 qreal y = spanY() / m_size.height();
120
120
121 qreal maxX = m_maxX;
121 qreal maxX = m_maxX;
122 qreal minX = m_minX;
122 qreal minX = m_minX;
123 qreal minY = m_minY;
123 qreal minY = m_minY;
124 qreal maxY = m_maxY;
124 qreal maxY = m_maxY;
125
125
126 if (dx != 0) {
126 if (dx != 0) {
127 minX = minX + x * dx;
127 minX = minX + x * dx;
128 maxX = maxX + x * dx;
128 maxX = maxX + x * dx;
129 }
129 }
130 if (dy != 0) {
130 if (dy != 0) {
131 minY = minY + y * dy;
131 minY = minY + y * dy;
132 maxY = maxY + y * dy;
132 maxY = maxY + y * dy;
133 }
133 }
134 setRange(minX, maxX, minY, maxY);
134 setRange(minX, maxX, minY, maxY);
135 }
135 }
136
136
137 QPointF XYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
137 QPointF XYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
138 {
138 {
139 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
139 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
140 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
140 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
141 qreal x = (point.x() - m_minX) * deltaX;
141 qreal x = (point.x() - m_minX) * deltaX;
142 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
142 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
143 ok = true;
143 ok = true;
144 return QPointF(x, y);
144 return QPointF(x, y);
145 }
145 }
146
146
147 QVector<QPointF> XYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
147 QVector<QPointF> XYDomain::calculateGeometryPoints(const QVector<QPointF> &vector) const
148 {
148 {
149 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
149 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
150 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
150 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
151
151
152 QVector<QPointF> result;
152 QVector<QPointF> result;
153 result.resize(vector.count());
153 result.resize(vector.count());
154
154
155 for (int i = 0; i < vector.count(); ++i) {
155 for (int i = 0; i < vector.count(); ++i) {
156 qreal x = (vector[i].x() - m_minX) * deltaX;
156 qreal x = (vector[i].x() - m_minX) * deltaX;
157 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
157 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
158 result[i].setX(x);
158 result[i].setX(x);
159 result[i].setY(y);
159 result[i].setY(y);
160 }
160 }
161 return result;
161 return result;
162 }
162 }
163
163
164 QPointF XYDomain::calculateDomainPoint(const QPointF &point) const
164 QPointF XYDomain::calculateDomainPoint(const QPointF &point) const
165 {
165 {
166 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
166 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
167 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
167 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
168 qreal x = point.x() / deltaX + m_minX;
168 qreal x = point.x() / deltaX + m_minX;
169 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
169 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
170 return QPointF(x, y);
170 return QPointF(x, y);
171 }
171 }
172
172
173 // operators
173 // operators
174
174
175 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XYDomain &domain1, const XYDomain &domain2)
175 bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XYDomain &domain1, const XYDomain &domain2)
176 {
176 {
177 return (qFuzzyCompare(domain1.m_maxX, domain2.m_maxX)
177 return (qFuzzyCompare(domain1.m_maxX, domain2.m_maxX)
178 && qFuzzyCompare(domain1.m_maxY, domain2.m_maxY)
178 && qFuzzyCompare(domain1.m_maxY, domain2.m_maxY)
179 && qFuzzyCompare(domain1.m_minX, domain2.m_minX)
179 && qFuzzyCompare(domain1.m_minX, domain2.m_minX)
180 && qFuzzyCompare(domain1.m_minY, domain2.m_minY));
180 && qFuzzyCompare(domain1.m_minY, domain2.m_minY));
181 }
181 }
182
182
183
183
184 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XYDomain &domain1, const XYDomain &domain2)
184 bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XYDomain &domain1, const XYDomain &domain2)
185 {
185 {
186 return !(domain1 == domain2);
186 return !(domain1 == domain2);
187 }
187 }
188
188
189
189
190 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYDomain &domain)
190 QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYDomain &domain)
191 {
191 {
192 #ifdef QT_NO_TEXTSTREAM
192 #ifdef QT_NO_TEXTSTREAM
193 Q_UNUSED(domain)
193 Q_UNUSED(domain)
194 #else
194 #else
195 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
195 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
196 #endif
196 #endif
197 return dbg.maybeSpace();
197 return dbg.maybeSpace();
198 }
198 }
199
199
200 #include "moc_xydomain_p.cpp"
200 #include "moc_xydomain_p.cpp"
201
201
202 QT_CHARTS_END_NAMESPACE
202 QT_CHARTS_END_NAMESPACE
@@ -1,62 +1,62
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 // W A R N I N G
19 // W A R N I N G
20 // -------------
20 // -------------
21 //
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
24 // version without notice, or even be removed.
25 //
25 //
26 // We mean it.
26 // We mean it.
27
27
28 #ifndef XYDOMAIN_H
28 #ifndef XYDOMAIN_H
29 #define XYDOMAIN_H
29 #define XYDOMAIN_H
30 #include <private/abstractdomain_p.h>
30 #include <private/abstractdomain_p.h>
31 #include <QtCore/QRectF>
31 #include <QtCore/QRectF>
32 #include <QtCore/QSizeF>
32 #include <QtCore/QSizeF>
33
33
34 QT_CHARTS_BEGIN_NAMESPACE
34 QT_CHARTS_BEGIN_NAMESPACE
35
35
36 class QT_CHARTS_AUTOTEST_EXPORT XYDomain: public AbstractDomain
36 class QT_CHARTS_AUTOTEST_EXPORT XYDomain: public AbstractDomain
37 {
37 {
38 Q_OBJECT
38 Q_OBJECT
39 public:
39 public:
40 explicit XYDomain(QObject *object = 0);
40 explicit XYDomain(QObject *object = 0);
41 virtual ~XYDomain();
41 virtual ~XYDomain();
42
42
43 DomainType type(){ return AbstractDomain::XYDomain;}
43 DomainType type(){ return AbstractDomain::XYDomain;}
44
44
45 void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
45 void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
46
46
47 friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XYDomain &Domain1, const XYDomain &Domain2);
47 friend bool QT_CHARTS_AUTOTEST_EXPORT operator== (const XYDomain &Domain1, const XYDomain &Domain2);
48 friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XYDomain &Domain1, const XYDomain &Domain2);
48 friend bool QT_CHARTS_AUTOTEST_EXPORT operator!= (const XYDomain &Domain1, const XYDomain &Domain2);
49 friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYDomain &AbstractDomain);
49 friend QDebug QT_CHARTS_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYDomain &AbstractDomain);
50
50
51 void zoomIn(const QRectF &rect);
51 void zoomIn(const QRectF &rect);
52 void zoomOut(const QRectF &rect);
52 void zoomOut(const QRectF &rect);
53 void move(qreal dx, qreal dy);
53 void move(qreal dx, qreal dy);
54
54
55 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
55 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
56 QPointF calculateDomainPoint(const QPointF &point) const;
56 QPointF calculateDomainPoint(const QPointF &point) const;
57 QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const;
57 QVector<QPointF> calculateGeometryPoints(const QVector<QPointF> &vector) const;
58 };
58 };
59
59
60 QT_CHARTS_END_NAMESPACE
60 QT_CHARTS_END_NAMESPACE
61
61
62 #endif // XYDOMAIN_H
62 #endif // XYDOMAIN_H
@@ -1,441 +1,455
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/linechartitem_p.h>
19 #include <private/linechartitem_p.h>
20 #include <QtCharts/QLineSeries>
20 #include <QtCharts/QLineSeries>
21 #include <private/qlineseries_p.h>
21 #include <private/qlineseries_p.h>
22 #include <private/chartpresenter_p.h>
22 #include <private/chartpresenter_p.h>
23 #include <private/polardomain_p.h>
23 #include <private/polardomain_p.h>
24 #include <private/chartthememanager_p.h>
24 #include <private/chartthememanager_p.h>
25 #include <private/charttheme_p.h>
25 #include <private/charttheme_p.h>
26 #include <QtGui/QPainter>
26 #include <QtGui/QPainter>
27 #include <QtWidgets/QGraphicsSceneMouseEvent>
27 #include <QtWidgets/QGraphicsSceneMouseEvent>
28
28
29 QT_CHARTS_BEGIN_NAMESPACE
29 QT_CHARTS_BEGIN_NAMESPACE
30
30
31 const qreal mouseEventMinWidth(12);
31 const qreal mouseEventMinWidth(12);
32
32
33 LineChartItem::LineChartItem(QLineSeries *series, QGraphicsItem *item)
33 LineChartItem::LineChartItem(QLineSeries *series, QGraphicsItem *item)
34 : XYChart(series,item),
34 : XYChart(series,item),
35 m_series(series),
35 m_series(series),
36 m_pointsVisible(false),
36 m_pointsVisible(false),
37 m_chartType(QChart::ChartTypeUndefined),
37 m_chartType(QChart::ChartTypeUndefined),
38 m_pointLabelsVisible(false),
38 m_pointLabelsVisible(false),
39 m_pointLabelsFormat(series->pointLabelsFormat()),
39 m_pointLabelsFormat(series->pointLabelsFormat()),
40 m_pointLabelsFont(series->pointLabelsFont()),
40 m_pointLabelsFont(series->pointLabelsFont()),
41 m_pointLabelsColor(series->pointLabelsColor()),
41 m_pointLabelsColor(series->pointLabelsColor()),
42 m_pointLabelsClipping(true),
42 m_pointLabelsClipping(true),
43 m_mousePressed(false)
43 m_mousePressed(false)
44 {
44 {
45 setAcceptHoverEvents(true);
45 setAcceptHoverEvents(true);
46 setFlag(QGraphicsItem::ItemIsSelectable);
46 setFlag(QGraphicsItem::ItemIsSelectable);
47 setZValue(ChartPresenter::LineChartZValue);
47 setZValue(ChartPresenter::LineChartZValue);
48 QObject::connect(series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdated()));
48 QObject::connect(series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdated()));
49 QObject::connect(series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
49 QObject::connect(series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
50 QObject::connect(series, SIGNAL(opacityChanged()), this, SLOT(handleUpdated()));
50 QObject::connect(series, SIGNAL(opacityChanged()), this, SLOT(handleUpdated()));
51 QObject::connect(series, SIGNAL(pointLabelsFormatChanged(QString)),
51 QObject::connect(series, SIGNAL(pointLabelsFormatChanged(QString)),
52 this, SLOT(handleUpdated()));
52 this, SLOT(handleUpdated()));
53 QObject::connect(series, SIGNAL(pointLabelsVisibilityChanged(bool)),
53 QObject::connect(series, SIGNAL(pointLabelsVisibilityChanged(bool)),
54 this, SLOT(handleUpdated()));
54 this, SLOT(handleUpdated()));
55 QObject::connect(series, SIGNAL(pointLabelsFontChanged(QFont)), this, SLOT(handleUpdated()));
55 QObject::connect(series, SIGNAL(pointLabelsFontChanged(QFont)), this, SLOT(handleUpdated()));
56 QObject::connect(series, SIGNAL(pointLabelsColorChanged(QColor)), this, SLOT(handleUpdated()));
56 QObject::connect(series, SIGNAL(pointLabelsColorChanged(QColor)), this, SLOT(handleUpdated()));
57 QObject::connect(series, SIGNAL(pointLabelsClippingChanged(bool)), this, SLOT(handleUpdated()));
57 QObject::connect(series, SIGNAL(pointLabelsClippingChanged(bool)), this, SLOT(handleUpdated()));
58 handleUpdated();
58 handleUpdated();
59 }
59 }
60
60
61 QRectF LineChartItem::boundingRect() const
61 QRectF LineChartItem::boundingRect() const
62 {
62 {
63 return m_rect;
63 return m_rect;
64 }
64 }
65
65
66 QPainterPath LineChartItem::shape() const
66 QPainterPath LineChartItem::shape() const
67 {
67 {
68 return m_shapePath;
68 return m_shapePath;
69 }
69 }
70
70
71 void LineChartItem::updateGeometry()
71 void LineChartItem::updateGeometry()
72 {
72 {
73 static const QRectF dummyRect = QRectF(0.0, 0.0, 0.001, 0.001);
74 if (m_series->useOpenGL()) {
75 // Fake a miniscule region, so we trigger changed signal.
76 if (m_rect.width() != dummyRect.width()) {
77 prepareGeometryChange();
78 m_rect = dummyRect;
79 }
80 update();
81 return;
82 }
83
73 // Store the points to a local variable so that the old line gets properly cleared
84 // Store the points to a local variable so that the old line gets properly cleared
74 // when animation starts.
85 // when animation starts.
75 m_linePoints = geometryPoints();
86 m_linePoints = geometryPoints();
76 const QVector<QPointF> &points = m_linePoints;
87 const QVector<QPointF> &points = m_linePoints;
77
88
78 if (points.size() == 0) {
89 if (points.size() == 0) {
79 prepareGeometryChange();
90 prepareGeometryChange();
80 m_fullPath = QPainterPath();
91 m_fullPath = QPainterPath();
81 m_linePath = QPainterPath();
92 m_linePath = QPainterPath();
82 m_rect = QRect();
93 m_rect = QRect();
83 return;
94 return;
84 }
95 }
85
96
86 QPainterPath linePath;
97 QPainterPath linePath;
87 QPainterPath fullPath;
98 QPainterPath fullPath;
88 // Use worst case scenario to determine required margin.
99 // Use worst case scenario to determine required margin.
89 qreal margin = m_linePen.width() * 1.42;
100 qreal margin = m_linePen.width() * 1.42;
90
101
91 // Area series use component line series that aren't necessarily added to the chart themselves,
102 // Area series use component line series that aren't necessarily added to the chart themselves,
92 // so check if chart type is forced before trying to obtain it from the chart.
103 // so check if chart type is forced before trying to obtain it from the chart.
93 QChart::ChartType chartType = m_chartType;
104 QChart::ChartType chartType = m_chartType;
94 if (chartType == QChart::ChartTypeUndefined)
105 if (chartType == QChart::ChartTypeUndefined)
95 chartType = m_series->chart()->chartType();
106 chartType = m_series->chart()->chartType();
96
107
97 // For polar charts, we need special handling for angular (horizontal)
108 // For polar charts, we need special handling for angular (horizontal)
98 // points that are off-grid.
109 // points that are off-grid.
99 if (chartType == QChart::ChartTypePolar) {
110 if (chartType == QChart::ChartTypePolar) {
100 QPainterPath linePathLeft;
111 QPainterPath linePathLeft;
101 QPainterPath linePathRight;
112 QPainterPath linePathRight;
102 QPainterPath *currentSegmentPath = 0;
113 QPainterPath *currentSegmentPath = 0;
103 QPainterPath *previousSegmentPath = 0;
114 QPainterPath *previousSegmentPath = 0;
104 qreal minX = domain()->minX();
115 qreal minX = domain()->minX();
105 qreal maxX = domain()->maxX();
116 qreal maxX = domain()->maxX();
106 qreal minY = domain()->minY();
117 qreal minY = domain()->minY();
107 QPointF currentSeriesPoint = m_series->at(0);
118 QPointF currentSeriesPoint = m_series->at(0);
108 QPointF currentGeometryPoint = points.at(0);
119 QPointF currentGeometryPoint = points.at(0);
109 QPointF previousGeometryPoint = points.at(0);
120 QPointF previousGeometryPoint = points.at(0);
110 int size = m_linePen.width();
121 int size = m_linePen.width();
111 bool pointOffGrid = false;
122 bool pointOffGrid = false;
112 bool previousPointWasOffGrid = (currentSeriesPoint.x() < minX || currentSeriesPoint.x() > maxX);
123 bool previousPointWasOffGrid = (currentSeriesPoint.x() < minX || currentSeriesPoint.x() > maxX);
113
124
114 qreal domainRadius = domain()->size().height() / 2.0;
125 qreal domainRadius = domain()->size().height() / 2.0;
115 const QPointF centerPoint(domainRadius, domainRadius);
126 const QPointF centerPoint(domainRadius, domainRadius);
116
127
117 if (!previousPointWasOffGrid) {
128 if (!previousPointWasOffGrid) {
118 fullPath.moveTo(points.at(0));
129 fullPath.moveTo(points.at(0));
119 if (m_pointsVisible && currentSeriesPoint.y() >= minY) {
130 if (m_pointsVisible && currentSeriesPoint.y() >= minY) {
120 // Do not draw ellipses for points below minimum Y.
131 // Do not draw ellipses for points below minimum Y.
121 linePath.addEllipse(points.at(0), size, size);
132 linePath.addEllipse(points.at(0), size, size);
122 fullPath.addEllipse(points.at(0), size, size);
133 fullPath.addEllipse(points.at(0), size, size);
123 linePath.moveTo(points.at(0));
134 linePath.moveTo(points.at(0));
124 fullPath.moveTo(points.at(0));
135 fullPath.moveTo(points.at(0));
125 }
136 }
126 }
137 }
127
138
128 qreal leftMarginLine = centerPoint.x() - margin;
139 qreal leftMarginLine = centerPoint.x() - margin;
129 qreal rightMarginLine = centerPoint.x() + margin;
140 qreal rightMarginLine = centerPoint.x() + margin;
130 qreal horizontal = centerPoint.y();
141 qreal horizontal = centerPoint.y();
131
142
132 // See ScatterChartItem::updateGeometry() for explanation why seriesLastIndex is needed
143 // See ScatterChartItem::updateGeometry() for explanation why seriesLastIndex is needed
133 const int seriesLastIndex = m_series->count() - 1;
144 const int seriesLastIndex = m_series->count() - 1;
134
145
135 for (int i = 1; i < points.size(); i++) {
146 for (int i = 1; i < points.size(); i++) {
136 // Interpolating line fragments would be ugly when thick pen is used,
147 // Interpolating line fragments would be ugly when thick pen is used,
137 // so we work around it by utilizing three separate
148 // so we work around it by utilizing three separate
138 // paths for line segments and clip those with custom regions at paint time.
149 // paths for line segments and clip those with custom regions at paint time.
139 // "Right" path contains segments that cross the axis line with visible point on the
150 // "Right" path contains segments that cross the axis line with visible point on the
140 // right side of the axis line, as well as segments that have one point within the margin
151 // right side of the axis line, as well as segments that have one point within the margin
141 // on the right side of the axis line and another point on the right side of the chart.
152 // on the right side of the axis line and another point on the right side of the chart.
142 // "Left" path contains points with similarly on the left side.
153 // "Left" path contains points with similarly on the left side.
143 // "Full" path contains rest of the points.
154 // "Full" path contains rest of the points.
144 // This doesn't yield perfect results always. E.g. when segment covers more than 90
155 // This doesn't yield perfect results always. E.g. when segment covers more than 90
145 // degrees and both of the points are within the margin, one in the top half and one in the
156 // degrees and both of the points are within the margin, one in the top half and one in the
146 // bottom half of the chart, the bottom one gets clipped incorrectly.
157 // bottom half of the chart, the bottom one gets clipped incorrectly.
147 // However, this should be rare occurrence in any sensible chart.
158 // However, this should be rare occurrence in any sensible chart.
148 currentSeriesPoint = m_series->at(qMin(seriesLastIndex, i));
159 currentSeriesPoint = m_series->at(qMin(seriesLastIndex, i));
149 currentGeometryPoint = points.at(i);
160 currentGeometryPoint = points.at(i);
150 pointOffGrid = (currentSeriesPoint.x() < minX || currentSeriesPoint.x() > maxX);
161 pointOffGrid = (currentSeriesPoint.x() < minX || currentSeriesPoint.x() > maxX);
151
162
152 // Draw something unless both off-grid
163 // Draw something unless both off-grid
153 if (!pointOffGrid || !previousPointWasOffGrid) {
164 if (!pointOffGrid || !previousPointWasOffGrid) {
154 QPointF intersectionPoint;
165 QPointF intersectionPoint;
155 qreal y;
166 qreal y;
156 if (pointOffGrid != previousPointWasOffGrid) {
167 if (pointOffGrid != previousPointWasOffGrid) {
157 if (currentGeometryPoint.x() == previousGeometryPoint.x()) {
168 if (currentGeometryPoint.x() == previousGeometryPoint.x()) {
158 y = currentGeometryPoint.y() + (currentGeometryPoint.y() - previousGeometryPoint.y()) / 2.0;
169 y = currentGeometryPoint.y() + (currentGeometryPoint.y() - previousGeometryPoint.y()) / 2.0;
159 } else {
170 } else {
160 qreal ratio = (centerPoint.x() - currentGeometryPoint.x()) / (currentGeometryPoint.x() - previousGeometryPoint.x());
171 qreal ratio = (centerPoint.x() - currentGeometryPoint.x()) / (currentGeometryPoint.x() - previousGeometryPoint.x());
161 y = currentGeometryPoint.y() + (currentGeometryPoint.y() - previousGeometryPoint.y()) * ratio;
172 y = currentGeometryPoint.y() + (currentGeometryPoint.y() - previousGeometryPoint.y()) * ratio;
162 }
173 }
163 intersectionPoint = QPointF(centerPoint.x(), y);
174 intersectionPoint = QPointF(centerPoint.x(), y);
164 }
175 }
165
176
166 bool dummyOk; // We know points are ok, but this is needed
177 bool dummyOk; // We know points are ok, but this is needed
167 qreal currentAngle = 0;
178 qreal currentAngle = 0;
168 qreal previousAngle = 0;
179 qreal previousAngle = 0;
169 if (const PolarDomain *pd = qobject_cast<const PolarDomain *>(domain())) {
180 if (const PolarDomain *pd = qobject_cast<const PolarDomain *>(domain())) {
170 currentAngle = pd->toAngularCoordinate(currentSeriesPoint.x(), dummyOk);
181 currentAngle = pd->toAngularCoordinate(currentSeriesPoint.x(), dummyOk);
171 previousAngle = pd->toAngularCoordinate(m_series->at(i - 1).x(), dummyOk);
182 previousAngle = pd->toAngularCoordinate(m_series->at(i - 1).x(), dummyOk);
172 } else {
183 } else {
173 qWarning() << Q_FUNC_INFO << "Unexpected domain: " << domain();
184 qWarning() << Q_FUNC_INFO << "Unexpected domain: " << domain();
174 }
185 }
175 if ((qAbs(currentAngle - previousAngle) > 180.0)) {
186 if ((qAbs(currentAngle - previousAngle) > 180.0)) {
176 // If the angle between two points is over 180 degrees (half X range),
187 // If the angle between two points is over 180 degrees (half X range),
177 // any direct segment between them becomes meaningless.
188 // any direct segment between them becomes meaningless.
178 // In this case two line segments are drawn instead, from previous
189 // In this case two line segments are drawn instead, from previous
179 // point to the center and from center to current point.
190 // point to the center and from center to current point.
180 if ((previousAngle < 0.0 || (previousAngle <= 180.0 && previousGeometryPoint.x() < rightMarginLine))
191 if ((previousAngle < 0.0 || (previousAngle <= 180.0 && previousGeometryPoint.x() < rightMarginLine))
181 && previousGeometryPoint.y() < horizontal) {
192 && previousGeometryPoint.y() < horizontal) {
182 currentSegmentPath = &linePathRight;
193 currentSegmentPath = &linePathRight;
183 } else if ((previousAngle > 360.0 || (previousAngle > 180.0 && previousGeometryPoint.x() > leftMarginLine))
194 } else if ((previousAngle > 360.0 || (previousAngle > 180.0 && previousGeometryPoint.x() > leftMarginLine))
184 && previousGeometryPoint.y() < horizontal) {
195 && previousGeometryPoint.y() < horizontal) {
185 currentSegmentPath = &linePathLeft;
196 currentSegmentPath = &linePathLeft;
186 } else if (previousAngle > 0.0 && previousAngle < 360.0) {
197 } else if (previousAngle > 0.0 && previousAngle < 360.0) {
187 currentSegmentPath = &linePath;
198 currentSegmentPath = &linePath;
188 } else {
199 } else {
189 currentSegmentPath = 0;
200 currentSegmentPath = 0;
190 }
201 }
191
202
192 if (currentSegmentPath) {
203 if (currentSegmentPath) {
193 if (previousSegmentPath != currentSegmentPath)
204 if (previousSegmentPath != currentSegmentPath)
194 currentSegmentPath->moveTo(previousGeometryPoint);
205 currentSegmentPath->moveTo(previousGeometryPoint);
195 if (previousPointWasOffGrid)
206 if (previousPointWasOffGrid)
196 fullPath.moveTo(intersectionPoint);
207 fullPath.moveTo(intersectionPoint);
197
208
198 currentSegmentPath->lineTo(centerPoint);
209 currentSegmentPath->lineTo(centerPoint);
199 fullPath.lineTo(centerPoint);
210 fullPath.lineTo(centerPoint);
200 }
211 }
201
212
202 previousSegmentPath = currentSegmentPath;
213 previousSegmentPath = currentSegmentPath;
203
214
204 if ((currentAngle < 0.0 || (currentAngle <= 180.0 && currentGeometryPoint.x() < rightMarginLine))
215 if ((currentAngle < 0.0 || (currentAngle <= 180.0 && currentGeometryPoint.x() < rightMarginLine))
205 && currentGeometryPoint.y() < horizontal) {
216 && currentGeometryPoint.y() < horizontal) {
206 currentSegmentPath = &linePathRight;
217 currentSegmentPath = &linePathRight;
207 } else if ((currentAngle > 360.0 || (currentAngle > 180.0 &&currentGeometryPoint.x() > leftMarginLine))
218 } else if ((currentAngle > 360.0 || (currentAngle > 180.0 &&currentGeometryPoint.x() > leftMarginLine))
208 && currentGeometryPoint.y() < horizontal) {
219 && currentGeometryPoint.y() < horizontal) {
209 currentSegmentPath = &linePathLeft;
220 currentSegmentPath = &linePathLeft;
210 } else if (currentAngle > 0.0 && currentAngle < 360.0) {
221 } else if (currentAngle > 0.0 && currentAngle < 360.0) {
211 currentSegmentPath = &linePath;
222 currentSegmentPath = &linePath;
212 } else {
223 } else {
213 currentSegmentPath = 0;
224 currentSegmentPath = 0;
214 }
225 }
215
226
216 if (currentSegmentPath) {
227 if (currentSegmentPath) {
217 if (previousSegmentPath != currentSegmentPath)
228 if (previousSegmentPath != currentSegmentPath)
218 currentSegmentPath->moveTo(centerPoint);
229 currentSegmentPath->moveTo(centerPoint);
219 if (!previousSegmentPath)
230 if (!previousSegmentPath)
220 fullPath.moveTo(centerPoint);
231 fullPath.moveTo(centerPoint);
221
232
222 currentSegmentPath->lineTo(currentGeometryPoint);
233 currentSegmentPath->lineTo(currentGeometryPoint);
223 if (pointOffGrid)
234 if (pointOffGrid)
224 fullPath.lineTo(intersectionPoint);
235 fullPath.lineTo(intersectionPoint);
225 else
236 else
226 fullPath.lineTo(currentGeometryPoint);
237 fullPath.lineTo(currentGeometryPoint);
227 }
238 }
228 } else {
239 } else {
229 if (previousAngle < 0.0 || currentAngle < 0.0
240 if (previousAngle < 0.0 || currentAngle < 0.0
230 || ((previousAngle <= 180.0 && currentAngle <= 180.0)
241 || ((previousAngle <= 180.0 && currentAngle <= 180.0)
231 && ((previousGeometryPoint.x() < rightMarginLine && previousGeometryPoint.y() < horizontal)
242 && ((previousGeometryPoint.x() < rightMarginLine && previousGeometryPoint.y() < horizontal)
232 || (currentGeometryPoint.x() < rightMarginLine && currentGeometryPoint.y() < horizontal)))) {
243 || (currentGeometryPoint.x() < rightMarginLine && currentGeometryPoint.y() < horizontal)))) {
233 currentSegmentPath = &linePathRight;
244 currentSegmentPath = &linePathRight;
234 } else if (previousAngle > 360.0 || currentAngle > 360.0
245 } else if (previousAngle > 360.0 || currentAngle > 360.0
235 || ((previousAngle > 180.0 && currentAngle > 180.0)
246 || ((previousAngle > 180.0 && currentAngle > 180.0)
236 && ((previousGeometryPoint.x() > leftMarginLine && previousGeometryPoint.y() < horizontal)
247 && ((previousGeometryPoint.x() > leftMarginLine && previousGeometryPoint.y() < horizontal)
237 || (currentGeometryPoint.x() > leftMarginLine && currentGeometryPoint.y() < horizontal)))) {
248 || (currentGeometryPoint.x() > leftMarginLine && currentGeometryPoint.y() < horizontal)))) {
238 currentSegmentPath = &linePathLeft;
249 currentSegmentPath = &linePathLeft;
239 } else {
250 } else {
240 currentSegmentPath = &linePath;
251 currentSegmentPath = &linePath;
241 }
252 }
242
253
243 if (currentSegmentPath != previousSegmentPath)
254 if (currentSegmentPath != previousSegmentPath)
244 currentSegmentPath->moveTo(previousGeometryPoint);
255 currentSegmentPath->moveTo(previousGeometryPoint);
245 if (previousPointWasOffGrid)
256 if (previousPointWasOffGrid)
246 fullPath.moveTo(intersectionPoint);
257 fullPath.moveTo(intersectionPoint);
247
258
248 if (pointOffGrid)
259 if (pointOffGrid)
249 fullPath.lineTo(intersectionPoint);
260 fullPath.lineTo(intersectionPoint);
250 else
261 else
251 fullPath.lineTo(currentGeometryPoint);
262 fullPath.lineTo(currentGeometryPoint);
252 currentSegmentPath->lineTo(currentGeometryPoint);
263 currentSegmentPath->lineTo(currentGeometryPoint);
253 }
264 }
254 } else {
265 } else {
255 currentSegmentPath = 0;
266 currentSegmentPath = 0;
256 }
267 }
257
268
258 previousPointWasOffGrid = pointOffGrid;
269 previousPointWasOffGrid = pointOffGrid;
259 if (m_pointsVisible && !pointOffGrid && currentSeriesPoint.y() >= minY) {
270 if (m_pointsVisible && !pointOffGrid && currentSeriesPoint.y() >= minY) {
260 linePath.addEllipse(points.at(i), size, size);
271 linePath.addEllipse(points.at(i), size, size);
261 fullPath.addEllipse(points.at(i), size, size);
272 fullPath.addEllipse(points.at(i), size, size);
262 linePath.moveTo(points.at(i));
273 linePath.moveTo(points.at(i));
263 fullPath.moveTo(points.at(i));
274 fullPath.moveTo(points.at(i));
264 }
275 }
265 previousSegmentPath = currentSegmentPath;
276 previousSegmentPath = currentSegmentPath;
266 previousGeometryPoint = currentGeometryPoint;
277 previousGeometryPoint = currentGeometryPoint;
267 }
278 }
268 m_linePathPolarRight = linePathRight;
279 m_linePathPolarRight = linePathRight;
269 m_linePathPolarLeft = linePathLeft;
280 m_linePathPolarLeft = linePathLeft;
270 // Note: This construction of m_fullpath is not perfect. The partial segments that are
281 // Note: This construction of m_fullpath is not perfect. The partial segments that are
271 // outside left/right clip regions at axis boundary still generate hover/click events,
282 // outside left/right clip regions at axis boundary still generate hover/click events,
272 // because shape doesn't get clipped. It doesn't seem possible to do sensibly.
283 // because shape doesn't get clipped. It doesn't seem possible to do sensibly.
273 } else { // not polar
284 } else { // not polar
274 linePath.moveTo(points.at(0));
285 linePath.moveTo(points.at(0));
275 if (m_pointsVisible) {
286 if (m_pointsVisible) {
276 int size = m_linePen.width();
287 int size = m_linePen.width();
277 linePath.addEllipse(points.at(0), size, size);
288 linePath.addEllipse(points.at(0), size, size);
278 linePath.moveTo(points.at(0));
289 linePath.moveTo(points.at(0));
279 for (int i = 1; i < points.size(); i++) {
290 for (int i = 1; i < points.size(); i++) {
280 linePath.lineTo(points.at(i));
291 linePath.lineTo(points.at(i));
281 linePath.addEllipse(points.at(i), size, size);
292 linePath.addEllipse(points.at(i), size, size);
282 linePath.moveTo(points.at(i));
293 linePath.moveTo(points.at(i));
283 }
294 }
284 } else {
295 } else {
285 for (int i = 1; i < points.size(); i++)
296 for (int i = 1; i < points.size(); i++)
286 linePath.lineTo(points.at(i));
297 linePath.lineTo(points.at(i));
287 }
298 }
288 fullPath = linePath;
299 fullPath = linePath;
289 }
300 }
290
301
291 QPainterPathStroker stroker;
302 QPainterPathStroker stroker;
292 // QPainter::drawLine does not respect join styles, for example BevelJoin becomes MiterJoin.
303 // QPainter::drawLine does not respect join styles, for example BevelJoin becomes MiterJoin.
293 // This is why we are prepared for the "worst case" scenario, i.e. use always MiterJoin and
304 // This is why we are prepared for the "worst case" scenario, i.e. use always MiterJoin and
294 // multiply line width with square root of two when defining shape and bounding rectangle.
305 // multiply line width with square root of two when defining shape and bounding rectangle.
295 stroker.setWidth(margin);
306 stroker.setWidth(margin);
296 stroker.setJoinStyle(Qt::MiterJoin);
307 stroker.setJoinStyle(Qt::MiterJoin);
297 stroker.setCapStyle(Qt::SquareCap);
308 stroker.setCapStyle(Qt::SquareCap);
298 stroker.setMiterLimit(m_linePen.miterLimit());
309 stroker.setMiterLimit(m_linePen.miterLimit());
299
310
300 QPainterPath checkShapePath = stroker.createStroke(fullPath);
311 QPainterPath checkShapePath = stroker.createStroke(fullPath);
301
312
302 // Only zoom in if the bounding rects of the paths fit inside int limits. QWidget::update() uses
313 // Only zoom in if the bounding rects of the paths fit inside int limits. QWidget::update() uses
303 // a region that has to be compatible with QRect.
314 // a region that has to be compatible with QRect.
304 if (checkShapePath.boundingRect().height() <= INT_MAX
315 if (checkShapePath.boundingRect().height() <= INT_MAX
305 && checkShapePath.boundingRect().width() <= INT_MAX
316 && checkShapePath.boundingRect().width() <= INT_MAX
306 && linePath.boundingRect().height() <= INT_MAX
317 && linePath.boundingRect().height() <= INT_MAX
307 && linePath.boundingRect().width() <= INT_MAX
318 && linePath.boundingRect().width() <= INT_MAX
308 && fullPath.boundingRect().height() <= INT_MAX
319 && fullPath.boundingRect().height() <= INT_MAX
309 && fullPath.boundingRect().width() <= INT_MAX) {
320 && fullPath.boundingRect().width() <= INT_MAX) {
310 prepareGeometryChange();
321 prepareGeometryChange();
311
322
312 m_linePath = linePath;
323 m_linePath = linePath;
313 m_fullPath = fullPath;
324 m_fullPath = fullPath;
314 m_shapePath = checkShapePath;
325 m_shapePath = checkShapePath;
315
326
316 m_rect = m_shapePath.boundingRect();
327 m_rect = m_shapePath.boundingRect();
317 } else {
328 } else {
318 update();
329 update();
319 }
330 }
320 }
331 }
321
332
322 void LineChartItem::handleUpdated()
333 void LineChartItem::handleUpdated()
323 {
334 {
324 // If points visibility has changed, a geometry update is needed.
335 // If points visibility has changed, a geometry update is needed.
325 // Also, if pen changes when points are visible, geometry update is needed.
336 // Also, if pen changes when points are visible, geometry update is needed.
326 bool doGeometryUpdate =
337 bool doGeometryUpdate =
327 (m_pointsVisible != m_series->pointsVisible())
338 (m_pointsVisible != m_series->pointsVisible())
328 || (m_series->pointsVisible() && (m_linePen != m_series->pen()));
339 || (m_series->pointsVisible() && (m_linePen != m_series->pen()));
329 setVisible(m_series->isVisible());
340 setVisible(m_series->isVisible());
330 setOpacity(m_series->opacity());
341 setOpacity(m_series->opacity());
331 m_pointsVisible = m_series->pointsVisible();
342 m_pointsVisible = m_series->pointsVisible();
332 m_linePen = m_series->pen();
343 m_linePen = m_series->pen();
333 m_pointLabelsFormat = m_series->pointLabelsFormat();
344 m_pointLabelsFormat = m_series->pointLabelsFormat();
334 m_pointLabelsVisible = m_series->pointLabelsVisible();
345 m_pointLabelsVisible = m_series->pointLabelsVisible();
335 m_pointLabelsFont = m_series->pointLabelsFont();
346 m_pointLabelsFont = m_series->pointLabelsFont();
336 m_pointLabelsColor = m_series->pointLabelsColor();
347 m_pointLabelsColor = m_series->pointLabelsColor();
337 m_pointLabelsClipping = m_series->pointLabelsClipping();
348 m_pointLabelsClipping = m_series->pointLabelsClipping();
338 if (doGeometryUpdate)
349 if (doGeometryUpdate)
339 updateGeometry();
350 updateGeometry();
340 update();
351 update();
341 }
352 }
342
353
343 void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
354 void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
344 {
355 {
345 Q_UNUSED(widget)
356 Q_UNUSED(widget)
346 Q_UNUSED(option)
357 Q_UNUSED(option)
347
358
359 if (m_series->useOpenGL())
360 return;
361
348 QRectF clipRect = QRectF(QPointF(0, 0), domain()->size());
362 QRectF clipRect = QRectF(QPointF(0, 0), domain()->size());
349
363
350 painter->save();
364 painter->save();
351 painter->setPen(m_linePen);
365 painter->setPen(m_linePen);
352 bool alwaysUsePath = false;
366 bool alwaysUsePath = false;
353
367
354 if (m_series->chart()->chartType() == QChart::ChartTypePolar) {
368 if (m_series->chart()->chartType() == QChart::ChartTypePolar) {
355 qreal halfWidth = domain()->size().width() / 2.0;
369 qreal halfWidth = domain()->size().width() / 2.0;
356 QRectF clipRectLeft = QRectF(0, 0, halfWidth, domain()->size().height());
370 QRectF clipRectLeft = QRectF(0, 0, halfWidth, domain()->size().height());
357 QRectF clipRectRight = QRectF(halfWidth, 0, halfWidth, domain()->size().height());
371 QRectF clipRectRight = QRectF(halfWidth, 0, halfWidth, domain()->size().height());
358 QRegion fullPolarClipRegion(clipRect.toRect(), QRegion::Ellipse);
372 QRegion fullPolarClipRegion(clipRect.toRect(), QRegion::Ellipse);
359 QRegion clipRegionLeft(fullPolarClipRegion.intersected(clipRectLeft.toRect()));
373 QRegion clipRegionLeft(fullPolarClipRegion.intersected(clipRectLeft.toRect()));
360 QRegion clipRegionRight(fullPolarClipRegion.intersected(clipRectRight.toRect()));
374 QRegion clipRegionRight(fullPolarClipRegion.intersected(clipRectRight.toRect()));
361 painter->setClipRegion(clipRegionLeft);
375 painter->setClipRegion(clipRegionLeft);
362 painter->drawPath(m_linePathPolarLeft);
376 painter->drawPath(m_linePathPolarLeft);
363 painter->setClipRegion(clipRegionRight);
377 painter->setClipRegion(clipRegionRight);
364 painter->drawPath(m_linePathPolarRight);
378 painter->drawPath(m_linePathPolarRight);
365 painter->setClipRegion(fullPolarClipRegion);
379 painter->setClipRegion(fullPolarClipRegion);
366 alwaysUsePath = true; // required for proper clipping
380 alwaysUsePath = true; // required for proper clipping
367 } else {
381 } else {
368 painter->setClipRect(clipRect);
382 painter->setClipRect(clipRect);
369 }
383 }
370
384
371 reversePainter(painter, clipRect);
385 reversePainter(painter, clipRect);
372
386
373 if (m_pointsVisible) {
387 if (m_pointsVisible) {
374 painter->setBrush(m_linePen.color());
388 painter->setBrush(m_linePen.color());
375 painter->drawPath(m_linePath);
389 painter->drawPath(m_linePath);
376 } else {
390 } else {
377 painter->setBrush(QBrush(Qt::NoBrush));
391 painter->setBrush(QBrush(Qt::NoBrush));
378 if (m_linePen.style() != Qt::SolidLine || alwaysUsePath) {
392 if (m_linePen.style() != Qt::SolidLine || alwaysUsePath) {
379 // If pen style is not solid line, always fall back to path painting
393 // If pen style is not solid line, always fall back to path painting
380 // to ensure proper continuity of the pattern
394 // to ensure proper continuity of the pattern
381 painter->drawPath(m_linePath);
395 painter->drawPath(m_linePath);
382 } else {
396 } else {
383 for (int i(1); i < m_linePoints.size(); i++)
397 for (int i(1); i < m_linePoints.size(); i++)
384 painter->drawLine(m_linePoints.at(i - 1), m_linePoints.at(i));
398 painter->drawLine(m_linePoints.at(i - 1), m_linePoints.at(i));
385 }
399 }
386 }
400 }
387
401
388 reversePainter(painter, clipRect);
402 reversePainter(painter, clipRect);
389
403
390 if (m_pointLabelsVisible) {
404 if (m_pointLabelsVisible) {
391 if (m_pointLabelsClipping)
405 if (m_pointLabelsClipping)
392 painter->setClipping(true);
406 painter->setClipping(true);
393 else
407 else
394 painter->setClipping(false);
408 painter->setClipping(false);
395 m_series->d_func()->drawSeriesPointLabels(painter, m_linePoints, m_linePen.width() / 2);
409 m_series->d_func()->drawSeriesPointLabels(painter, m_linePoints, m_linePen.width() / 2);
396 }
410 }
397
411
398 painter->restore();
412 painter->restore();
399
413
400 }
414 }
401
415
402 void LineChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
416 void LineChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
403 {
417 {
404 emit XYChart::pressed(domain()->calculateDomainPoint(event->pos()));
418 emit XYChart::pressed(domain()->calculateDomainPoint(event->pos()));
405 m_lastMousePos = event->pos();
419 m_lastMousePos = event->pos();
406 m_mousePressed = true;
420 m_mousePressed = true;
407 QGraphicsItem::mousePressEvent(event);
421 QGraphicsItem::mousePressEvent(event);
408 }
422 }
409
423
410 void LineChartItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
424 void LineChartItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
411 {
425 {
412 emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), true);
426 emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), true);
413 // event->accept();
427 // event->accept();
414 QGraphicsItem::hoverEnterEvent(event);
428 QGraphicsItem::hoverEnterEvent(event);
415 }
429 }
416
430
417 void LineChartItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
431 void LineChartItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
418 {
432 {
419 emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), false);
433 emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), false);
420 // event->accept();
434 // event->accept();
421 QGraphicsItem::hoverEnterEvent(event);
435 QGraphicsItem::hoverEnterEvent(event);
422 }
436 }
423
437
424 void LineChartItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
438 void LineChartItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
425 {
439 {
426 emit XYChart::released(domain()->calculateDomainPoint(m_lastMousePos));
440 emit XYChart::released(domain()->calculateDomainPoint(m_lastMousePos));
427 if (m_mousePressed)
441 if (m_mousePressed)
428 emit XYChart::clicked(domain()->calculateDomainPoint(m_lastMousePos));
442 emit XYChart::clicked(domain()->calculateDomainPoint(m_lastMousePos));
429 m_mousePressed = false;
443 m_mousePressed = false;
430 QGraphicsItem::mouseReleaseEvent(event);
444 QGraphicsItem::mouseReleaseEvent(event);
431 }
445 }
432
446
433 void LineChartItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
447 void LineChartItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
434 {
448 {
435 emit XYChart::doubleClicked(domain()->calculateDomainPoint(m_lastMousePos));
449 emit XYChart::doubleClicked(domain()->calculateDomainPoint(m_lastMousePos));
436 QGraphicsItem::mouseDoubleClickEvent(event);
450 QGraphicsItem::mouseDoubleClickEvent(event);
437 }
451 }
438
452
439 #include "moc_linechartitem_p.cpp"
453 #include "moc_linechartitem_p.cpp"
440
454
441 QT_CHARTS_END_NAMESPACE
455 QT_CHARTS_END_NAMESPACE
@@ -1,362 +1,458
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <QtCharts/QAbstractSeries>
19 #include <QtCharts/QAbstractSeries>
20 #include <private/qabstractseries_p.h>
20 #include <private/qabstractseries_p.h>
21 #include <private/chartdataset_p.h>
21 #include <private/chartdataset_p.h>
22 #include <QtCharts/QChart>
22 #include <QtCharts/QChart>
23 #include <private/qchart_p.h>
23 #include <private/qchart_p.h>
24 #include <private/chartitem_p.h>
24 #include <private/chartitem_p.h>
25 #include <private/xydomain_p.h>
25 #include <private/xydomain_p.h>
26 #include <private/xlogydomain_p.h>
26 #include <private/xlogydomain_p.h>
27 #include <private/logxydomain_p.h>
27 #include <private/logxydomain_p.h>
28 #include <private/logxlogydomain_p.h>
28 #include <private/logxlogydomain_p.h>
29
29
30 QT_CHARTS_BEGIN_NAMESPACE
30 QT_CHARTS_BEGIN_NAMESPACE
31
31
32 /*!
32 /*!
33 \class QAbstractSeries
33 \class QAbstractSeries
34 \inmodule Qt Charts
34 \inmodule Qt Charts
35 \brief Base class for all Qt Chart series.
35 \brief Base class for all Qt Chart series.
36
36
37 Usually you use the series type specific inherited classes instead of the base class.
37 Usually you use the series type specific inherited classes instead of the base class.
38 \sa QXYSeries, QLineSeries, QSplineSeries, QScatterSeries, QAreaSeries, QAbstractBarSeries, QStackedBarSeries,
38 \sa QXYSeries, QLineSeries, QSplineSeries, QScatterSeries, QAreaSeries, QAbstractBarSeries, QStackedBarSeries,
39 QPercentBarSeries, QPieSeries
39 QPercentBarSeries, QPieSeries
40 */
40 */
41 /*!
41 /*!
42 \qmltype AbstractSeries
42 \qmltype AbstractSeries
43 \instantiates QAbstractSeries
43 \instantiates QAbstractSeries
44 \inqmlmodule QtCharts
44 \inqmlmodule QtCharts
45
45
46 \brief Base class for all Qt Chart series.
46 \brief Base class for all Qt Chart series.
47
47
48 AbstractSeries is the base class for all series.
48 AbstractSeries is the base class for all series.
49 The class cannot be instantiated by the user.
49 The class cannot be instantiated by the user.
50 */
50 */
51
51
52 /*!
52 /*!
53 \enum QAbstractSeries::SeriesType
53 \enum QAbstractSeries::SeriesType
54
54
55 The type of the series object.
55 The type of the series object.
56
56
57 \value SeriesTypeLine
57 \value SeriesTypeLine
58 \value SeriesTypeArea
58 \value SeriesTypeArea
59 \value SeriesTypeBar
59 \value SeriesTypeBar
60 \value SeriesTypeStackedBar
60 \value SeriesTypeStackedBar
61 \value SeriesTypePercentBar
61 \value SeriesTypePercentBar
62 \value SeriesTypePie
62 \value SeriesTypePie
63 \value SeriesTypeScatter
63 \value SeriesTypeScatter
64 \value SeriesTypeSpline
64 \value SeriesTypeSpline
65 \value SeriesTypeHorizontalBar
65 \value SeriesTypeHorizontalBar
66 \value SeriesTypeHorizontalStackedBar
66 \value SeriesTypeHorizontalStackedBar
67 \value SeriesTypeHorizontalPercentBar
67 \value SeriesTypeHorizontalPercentBar
68 \value SeriesTypeBoxPlot
68 \value SeriesTypeBoxPlot
69 */
69 */
70
70
71 /*!
71 /*!
72 \property QAbstractSeries::type
72 \property QAbstractSeries::type
73 The type of the series.
73 The type of the series.
74 */
74 */
75 /*!
75 /*!
76 \qmlproperty ChartView.SeriesType AbstractSeries::type
76 \qmlproperty ChartView.SeriesType AbstractSeries::type
77 The type of the series.
77 The type of the series.
78 */
78 */
79
79
80 /*!
80 /*!
81 \property QAbstractSeries::name
81 \property QAbstractSeries::name
82 \brief name of the series property. The name is shown in legend for series and supports html formatting.
82 \brief name of the series property. The name is shown in legend for series and supports html formatting.
83 */
83 */
84 /*!
84 /*!
85 \qmlproperty string AbstractSeries::name
85 \qmlproperty string AbstractSeries::name
86 Name of the series. The name is shown in legend for series and supports html formatting.
86 Name of the series. The name is shown in legend for series and supports html formatting.
87 */
87 */
88
88
89 /*!
89 /*!
90 \fn void QAbstractSeries::nameChanged()
90 \fn void QAbstractSeries::nameChanged()
91 This signal is emitted when the series name changes.
91 This signal is emitted when the series name changes.
92 */
92 */
93 /*!
93 /*!
94 \qmlsignal AbstractSeries::onNameChanged()
94 \qmlsignal AbstractSeries::onNameChanged()
95 This signal is emitted when the series name changes.
95 This signal is emitted when the series name changes.
96 */
96 */
97
97
98 /*!
98 /*!
99 \property QAbstractSeries::visible
99 \property QAbstractSeries::visible
100 \brief whether the series is visible or not; true by default.
100 \brief whether the series is visible or not; true by default.
101 */
101 */
102 /*!
102 /*!
103 \qmlproperty bool AbstractSeries::visible
103 \qmlproperty bool AbstractSeries::visible
104 Visibility of the series. True by default.
104 Visibility of the series. True by default.
105 */
105 */
106
106
107 /*!
107 /*!
108 \fn void QAbstractSeries::visibleChanged()
108 \fn void QAbstractSeries::visibleChanged()
109 Emitted when the series visibility changes.
109 Emitted when the series visibility changes.
110 */
110 */
111 /*!
111 /*!
112 \qmlsignal AbstractSeries::onVisibleChanged()
112 \qmlsignal AbstractSeries::onVisibleChanged()
113 Emitted when the series visibility changes.
113 Emitted when the series visibility changes.
114 */
114 */
115
115
116 /*!
116 /*!
117 \property QAbstractSeries::opacity
117 \property QAbstractSeries::opacity
118 \brief The opacity of the series.
118 \brief The opacity of the series.
119
119
120 By default the opacity is 1.0. The valid values range from 0.0 (transparent) to 1.0 (opaque).
120 By default the opacity is 1.0. The valid values range from 0.0 (transparent) to 1.0 (opaque).
121 */
121 */
122 /*!
122 /*!
123 \qmlproperty real AbstractSeries::opacity
123 \qmlproperty real AbstractSeries::opacity
124 The opacity of the series. By default the opacity is 1.0.
124 The opacity of the series. By default the opacity is 1.0.
125 The valid values range from 0.0 (transparent) to 1.0 (opaque).
125 The valid values range from 0.0 (transparent) to 1.0 (opaque).
126 */
126 */
127
127
128 /*!
128 /*!
129 \fn void QAbstractSeries::opacityChanged()
129 \fn void QAbstractSeries::opacityChanged()
130 Emitted when the opacity of the series changes.
130 Emitted when the opacity of the series changes.
131 */
131 */
132 /*!
132 /*!
133 \qmlsignal AbstractSeries::onOpacityChanged()
133 \qmlsignal AbstractSeries::onOpacityChanged()
134 Emitted when the opacity of the series changes.
134 Emitted when the opacity of the series changes.
135 */
135 */
136
136
137 /*!
137 /*!
138 \property QAbstractSeries::useOpenGL
139 \brief Specifies whether or not the series drawing is accelerated with OpenGL.
140
141 Drawing series with OpenGL is supported only for QLineSeries and QScatterSeries.
142 Line series used as edge series for a QAreaSeries cannot use OpenGL acceleration.
143 When a chart contains any series that are drawn with OpenGL, a transparent QOpenGLWidget
144 is created on top of the chart plot area. Specified series are not drawn on the underlying
145 QGraphicsView, but are instead drawn on the created QOpenGLWidget.
146
147 Performance gained from using OpenGL to accelerate series drawing depends on the underlying
148 hardware, but in most cases it is significant. For example, on a standard desktop computer,
149 enabling OpenGL acceleration for a series typically allows rendering at least hundred times
150 more points without reduction on the frame rate.
151 Chart size also has less effect on the frame rate.
152
153 The OpenGL acceleration of series drawing is meant for use cases that need fast drawing of
154 large numbers of points. It is optimized for efficiency, and therefore the series using
155 it lack support for some features available to non-accelerated series.
156
157 There are the following restrictions imposed on charts and series when using OpenGL
158 acceleration:
159
160 \list
161 \li Series animations are not supported for accelerated series.
162 \li Antialiasing is not supported for accelerated series.
163 \li Pen styles and marker shapes are ignored for accelerated series.
164 Only solid lines and plain scatter dots are supported.
165 The scatter dots may be circular or rectangular, depending on the underlying graphics
166 hardware and drivers.
167 \li Polar charts are not supported for accelerated series.
168 \li Since the accelerated series are drawn on top of the entire graphics view, they get drawn
169 on top of any other graphics items that you may have on top chart in the same scene.
170 \li To enable QOpenGLWidget to be partially transparent, it needs to be stacked on top of
171 all other widgets. This means you cannot have other widgets partially covering the
172 chart.
173 \endlist
174
175 The default value is \c{false}.
176 */
177 /*!
178 \qmlproperty bool AbstractSeries::useOpenGL
179 Specifies whether or not the series is drawn with OpenGL.
180
181 Drawing series with OpenGL is supported only for LineSeries and ScatterSeries.
182
183 For more details, see QAbstractSeries::useOpenGL documentation. QML applications have similar
184 restrictions as those listed in QAbstractSeries::useOpenGL documentation,
185 except there is no restriction about covering the ChartView partially with other
186 items due to different rendering mechanism.
187
188 The default value is \c{false}.
189 */
190
191 /*!
192 \fn void QAbstractSeries::useOpenGLChanged()
193 Emitted when the useOpenGL property value changes.
194 */
195 /*!
196 \qmlsignal AbstractSeries::onUseOpenGLChanged()
197 Emitted when the useOpenGL property value changes.
198 */
199
200 /*!
138 \internal
201 \internal
139 \brief Constructs QAbstractSeries object with \a parent.
202 \brief Constructs QAbstractSeries object with \a parent.
140 */
203 */
141 QAbstractSeries::QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent) :
204 QAbstractSeries::QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent) :
142 QObject(parent),
205 QObject(parent),
143 d_ptr(&d)
206 d_ptr(&d)
144 {
207 {
145 }
208 }
146
209
147 /*!
210 /*!
148 \brief Virtual destructor for the chart series.
211 \brief Virtual destructor for the chart series.
149 */
212 */
150 QAbstractSeries::~QAbstractSeries()
213 QAbstractSeries::~QAbstractSeries()
151 {
214 {
152 if (d_ptr->m_chart)
215 if (d_ptr->m_chart)
153 qFatal("Series still bound to a chart when destroyed!");
216 qFatal("Series still bound to a chart when destroyed!");
154 }
217 }
155
218
156 void QAbstractSeries::setName(const QString &name)
219 void QAbstractSeries::setName(const QString &name)
157 {
220 {
158 if (name != d_ptr->m_name) {
221 if (name != d_ptr->m_name) {
159 d_ptr->m_name = name;
222 d_ptr->m_name = name;
160 emit nameChanged();
223 emit nameChanged();
161 }
224 }
162 }
225 }
163
226
164 QString QAbstractSeries::name() const
227 QString QAbstractSeries::name() const
165 {
228 {
166 return d_ptr->m_name;
229 return d_ptr->m_name;
167 }
230 }
168
231
169 void QAbstractSeries::setVisible(bool visible)
232 void QAbstractSeries::setVisible(bool visible)
170 {
233 {
171 if (visible != d_ptr->m_visible) {
234 if (visible != d_ptr->m_visible) {
172 d_ptr->m_visible = visible;
235 d_ptr->m_visible = visible;
173 emit visibleChanged();
236 emit visibleChanged();
174 }
237 }
175 }
238 }
176
239
177 bool QAbstractSeries::isVisible() const
240 bool QAbstractSeries::isVisible() const
178 {
241 {
179 return d_ptr->m_visible;
242 return d_ptr->m_visible;
180 }
243 }
181
244
182 qreal QAbstractSeries::opacity() const
245 qreal QAbstractSeries::opacity() const
183 {
246 {
184 return d_ptr->m_opacity;
247 return d_ptr->m_opacity;
185 }
248 }
186
249
187 void QAbstractSeries::setOpacity(qreal opacity)
250 void QAbstractSeries::setOpacity(qreal opacity)
188 {
251 {
189 if (opacity != d_ptr->m_opacity) {
252 if (opacity != d_ptr->m_opacity) {
190 d_ptr->m_opacity = opacity;
253 d_ptr->m_opacity = opacity;
191 emit opacityChanged();
254 emit opacityChanged();
192 }
255 }
193 }
256 }
194
257
258 void QAbstractSeries::setUseOpenGL(bool enable)
259 {
260 #ifdef QT_NO_OPENGL
261 Q_UNUSED(enable)
262 #else
263 bool polarChart = d_ptr->m_chart && d_ptr->m_chart->chartType() == QChart::ChartTypePolar;
264 bool supportedSeries = (type() == SeriesTypeLine || type() == SeriesTypeScatter);
265 if ((!enable || !d_ptr->m_blockOpenGL)
266 && supportedSeries
267 && enable != d_ptr->m_useOpenGL
268 && (!enable || !polarChart)) {
269 d_ptr->m_useOpenGL = enable;
270 emit useOpenGLChanged();
271 }
272 #endif
273 }
274
275 bool QAbstractSeries::useOpenGL() const
276 {
277 return d_ptr->m_useOpenGL;
278 }
279
195 /*!
280 /*!
196 \brief Returns the chart where series belongs to.
281 \brief Returns the chart where series belongs to.
197
282
198 Set automatically when the series is added to the chart
283 Set automatically when the series is added to the chart
199 and unset when the series is removed from the chart.
284 and unset when the series is removed from the chart.
200 */
285 */
201 QChart *QAbstractSeries::chart() const
286 QChart *QAbstractSeries::chart() const
202 {
287 {
203 return d_ptr->m_chart;
288 return d_ptr->m_chart;
204 }
289 }
205
290
206 /*!
291 /*!
207 \brief Sets the visibility of the series to true.
292 \brief Sets the visibility of the series to true.
208
293
209 \sa setVisible(), isVisible()
294 \sa setVisible(), isVisible()
210 */
295 */
211 void QAbstractSeries::show()
296 void QAbstractSeries::show()
212 {
297 {
213 setVisible(true);
298 setVisible(true);
214 }
299 }
215
300
216 /*!
301 /*!
217 \brief Sets the visibility of the series to false.
302 \brief Sets the visibility of the series to false.
218
303
219 \sa setVisible(), isVisible()
304 \sa setVisible(), isVisible()
220 */
305 */
221 void QAbstractSeries::hide()
306 void QAbstractSeries::hide()
222 {
307 {
223 setVisible(false);
308 setVisible(false);
224 }
309 }
225
310
226 /*!
311 /*!
227 Attach \a axis to the series.
312 Attach \a axis to the series.
228 \return true if the axis was attached successfully, false otherwise.
313 \return true if the axis was attached successfully, false otherwise.
229 \note If multiple axes of same orientation are attached to same series,
314 \note If multiple axes of same orientation are attached to same series,
230 they will have same min/max ranges.
315 they will have same min/max ranges.
231 \sa QChart::addAxis(), QChart::createDefaultAxes()
316 \sa QChart::addAxis(), QChart::createDefaultAxes()
232 */
317 */
233 bool QAbstractSeries::attachAxis(QAbstractAxis* axis)
318 bool QAbstractSeries::attachAxis(QAbstractAxis* axis)
234 {
319 {
235 if(d_ptr->m_chart) {
320 if(d_ptr->m_chart) {
236 return d_ptr->m_chart->d_ptr->m_dataset->attachAxis(this, axis);
321 return d_ptr->m_chart->d_ptr->m_dataset->attachAxis(this, axis);
237 } else {
322 } else {
238 qWarning()<<"Series not in the chart. Please addSeries to chart first.";
323 qWarning()<<"Series not in the chart. Please addSeries to chart first.";
239 return false;
324 return false;
240 }
325 }
241 }
326 }
242
327
243 /*!
328 /*!
244 Detach \a axis from the series.
329 Detach \a axis from the series.
245 \return true if the axis was detached successfully, false otherwise.
330 \return true if the axis was detached successfully, false otherwise.
246 \sa QChart::removeAxis()
331 \sa QChart::removeAxis()
247 */
332 */
248 bool QAbstractSeries::detachAxis(QAbstractAxis* axis)
333 bool QAbstractSeries::detachAxis(QAbstractAxis* axis)
249 {
334 {
250 if(d_ptr->m_chart) {
335 if(d_ptr->m_chart) {
251 return d_ptr->m_chart->d_ptr->m_dataset->detachAxis(this, axis);
336 return d_ptr->m_chart->d_ptr->m_dataset->detachAxis(this, axis);
252 }
337 }
253 else {
338 else {
254 qWarning()<<"Series not in the chart. Please addSeries to chart first.";
339 qWarning()<<"Series not in the chart. Please addSeries to chart first.";
255 return false;
340 return false;
256 }
341 }
257 }
342 }
258
343
259 /*!
344 /*!
260 Returns the list of axes attached to the series. Usually there is an x-axis and a y-axis attached to a series, except
345 Returns the list of axes attached to the series. Usually there is an x-axis and a y-axis attached to a series, except
261 in case of a QPieSeries, which does not have any axes attached.
346 in case of a QPieSeries, which does not have any axes attached.
262 \sa attachAxis(), detachAxis()
347 \sa attachAxis(), detachAxis()
263 */
348 */
264 QList<QAbstractAxis*> QAbstractSeries::attachedAxes()
349 QList<QAbstractAxis*> QAbstractSeries::attachedAxes()
265 {
350 {
266 return d_ptr->m_axes;
351 return d_ptr->m_axes;
267 }
352 }
268
353
269 ///////////////////////////////////////////////////////////////////////////////////////////////////
354 ///////////////////////////////////////////////////////////////////////////////////////////////////
270
355
271 QAbstractSeriesPrivate::QAbstractSeriesPrivate(QAbstractSeries *q)
356 QAbstractSeriesPrivate::QAbstractSeriesPrivate(QAbstractSeries *q)
272 : q_ptr(q),
357 : q_ptr(q),
273 m_chart(0),
358 m_chart(0),
274 m_item(0),
359 m_item(0),
275 m_domain(new XYDomain()),
360 m_domain(new XYDomain()),
276 m_visible(true),
361 m_visible(true),
277 m_opacity(1.0)
362 m_opacity(1.0),
363 m_useOpenGL(false),
364 m_blockOpenGL(false)
278 {
365 {
279 }
366 }
280
367
281 QAbstractSeriesPrivate::~QAbstractSeriesPrivate()
368 QAbstractSeriesPrivate::~QAbstractSeriesPrivate()
282 {
369 {
283 }
370 }
284
371
285 void QAbstractSeriesPrivate::setDomain(AbstractDomain* domain)
372 void QAbstractSeriesPrivate::setDomain(AbstractDomain* domain)
286 {
373 {
287 Q_ASSERT(domain);
374 Q_ASSERT(domain);
288 if(m_domain.data()!=domain) {
375 if(m_domain.data()!=domain) {
289 if(!m_item.isNull()) QObject::disconnect(m_domain.data(), SIGNAL(updated()), m_item.data(), SLOT(handleDomainUpdated()));
376 if(!m_item.isNull()) QObject::disconnect(m_domain.data(), SIGNAL(updated()), m_item.data(), SLOT(handleDomainUpdated()));
290 m_domain.reset(domain);
377 m_domain.reset(domain);
291 if(!m_item.isNull()) {
378 if(!m_item.isNull()) {
292 QObject::connect(m_domain.data(), SIGNAL(updated()),m_item.data(), SLOT(handleDomainUpdated()));
379 QObject::connect(m_domain.data(), SIGNAL(updated()),m_item.data(), SLOT(handleDomainUpdated()));
293 m_item->handleDomainUpdated();
380 m_item->handleDomainUpdated();
294 }
381 }
295 }
382 }
296 }
383 }
297
384
298 void QAbstractSeriesPrivate::setPresenter(ChartPresenter *presenter)
385 void QAbstractSeriesPrivate::setPresenter(ChartPresenter *presenter)
299 {
386 {
300 m_presenter = presenter;
387 m_presenter = presenter;
301 }
388 }
302
389
303 ChartPresenter *QAbstractSeriesPrivate::presenter() const
390 ChartPresenter *QAbstractSeriesPrivate::presenter() const
304 {
391 {
305 return m_presenter;
392 return m_presenter;
306 }
393 }
307
394
308 void QAbstractSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
395 void QAbstractSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
309 {
396 {
310 Q_ASSERT(!m_item.isNull());
397 Q_ASSERT(!m_item.isNull());
311 Q_UNUSED(parent);
398 Q_UNUSED(parent);
312 QObject::connect(m_domain.data(), SIGNAL(updated()),m_item.data(), SLOT(handleDomainUpdated()));
399 QObject::connect(m_domain.data(), SIGNAL(updated()),m_item.data(), SLOT(handleDomainUpdated()));
313 }
400 }
314
401
315 void QAbstractSeriesPrivate::initializeAnimations(QChart::AnimationOptions options, int duration,
402 void QAbstractSeriesPrivate::initializeAnimations(QChart::AnimationOptions options, int duration,
316 QEasingCurve &curve)
403 QEasingCurve &curve)
317 {
404 {
318 Q_UNUSED(options);
405 Q_UNUSED(options);
319 Q_UNUSED(duration);
406 Q_UNUSED(duration);
320 Q_UNUSED(curve);
407 Q_UNUSED(curve);
321 }
408 }
322
409
323 bool QAbstractSeriesPrivate::reverseXAxis()
410 bool QAbstractSeriesPrivate::reverseXAxis()
324 {
411 {
325 bool reverseXAxis = false;
412 bool reverseXAxis = false;
326 if (m_axes.size() != 0 && !(m_chart->chartType() == QChart::ChartTypePolar)) {
413 if (m_axes.size() != 0 && !(m_chart->chartType() == QChart::ChartTypePolar)) {
327 int i = 0;
414 int i = 0;
328 while (i < m_axes.size()) {
415 while (i < m_axes.size()) {
329 if (m_axes.at(i)->orientation() == Qt::Horizontal && m_axes.at(i)->isReverse()) {
416 if (m_axes.at(i)->orientation() == Qt::Horizontal && m_axes.at(i)->isReverse()) {
330 reverseXAxis = true;
417 reverseXAxis = true;
331 break;
418 break;
332 }
419 }
333 i++;
420 i++;
334 }
421 }
335 }
422 }
336
423
337 return reverseXAxis;
424 return reverseXAxis;
338 }
425 }
339
426
340 bool QAbstractSeriesPrivate::reverseYAxis()
427 bool QAbstractSeriesPrivate::reverseYAxis()
341 {
428 {
342 bool reverseYAxis = false;
429 bool reverseYAxis = false;
343 if (m_axes.size() != 0 && !(m_chart->chartType() == QChart::ChartTypePolar)) {
430 if (m_axes.size() != 0 && !(m_chart->chartType() == QChart::ChartTypePolar)) {
344 int i = 0;
431 int i = 0;
345 while (i < m_axes.size()) {
432 while (i < m_axes.size()) {
346 if (m_axes.at(i)->orientation() == Qt::Vertical && m_axes.at(i)->isReverse()) {
433 if (m_axes.at(i)->orientation() == Qt::Vertical && m_axes.at(i)->isReverse()) {
347 reverseYAxis = true;
434 reverseYAxis = true;
348 break;
435 break;
349 }
436 }
350 i++;
437 i++;
351 }
438 }
352 }
439 }
353
440
354 return reverseYAxis;
441 return reverseYAxis;
355 }
442 }
356
443
444 // This function can be used to explicitly block OpenGL use from some otherwise supported series,
445 // such as the line series used as edge series of an area series.
446 void QAbstractSeriesPrivate::setBlockOpenGL(bool enable)
447 {
448 m_blockOpenGL = enable;
449 if (enable)
450 q_ptr->setUseOpenGL(false);
451 }
452
357 #include "moc_qabstractseries.cpp"
453 #include "moc_qabstractseries.cpp"
358 #include "moc_qabstractseries_p.cpp"
454 #include "moc_qabstractseries_p.cpp"
359
455
360 QT_CHARTS_END_NAMESPACE
456 QT_CHARTS_END_NAMESPACE
361
457
362
458
@@ -1,96 +1,101
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #ifndef QABSTRACTSERIES_H
19 #ifndef QABSTRACTSERIES_H
20 #define QABSTRACTSERIES_H
20 #define QABSTRACTSERIES_H
21
21
22 #include <QtCharts/QChartGlobal>
22 #include <QtCharts/QChartGlobal>
23 #include <QtCharts/QAbstractAxis>
23 #include <QtCharts/QAbstractAxis>
24 #include <QtCore/QObject>
24 #include <QtCore/QObject>
25 #include <QtGui/QPen>
25 #include <QtGui/QPen>
26
26
27 QT_CHARTS_BEGIN_NAMESPACE
27 QT_CHARTS_BEGIN_NAMESPACE
28
28
29 class QAbstractSeriesPrivate;
29 class QAbstractSeriesPrivate;
30 class QChart;
30 class QChart;
31
31
32 class QT_CHARTS_EXPORT QAbstractSeries : public QObject
32 class QT_CHARTS_EXPORT QAbstractSeries : public QObject
33 {
33 {
34 Q_OBJECT
34 Q_OBJECT
35 Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
35 Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
36 Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)
36 Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)
37 Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged)
37 Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged)
38 Q_PROPERTY(SeriesType type READ type)
38 Q_PROPERTY(SeriesType type READ type)
39 Q_PROPERTY(bool useOpenGL READ useOpenGL WRITE setUseOpenGL NOTIFY useOpenGLChanged)
39 Q_ENUMS(SeriesType)
40 Q_ENUMS(SeriesType)
40
41
41 public:
42 public:
42 enum SeriesType {
43 enum SeriesType {
43 SeriesTypeLine,
44 SeriesTypeLine,
44 SeriesTypeArea,
45 SeriesTypeArea,
45 SeriesTypeBar,
46 SeriesTypeBar,
46 SeriesTypeStackedBar,
47 SeriesTypeStackedBar,
47 SeriesTypePercentBar,
48 SeriesTypePercentBar,
48 SeriesTypePie,
49 SeriesTypePie,
49 SeriesTypeScatter,
50 SeriesTypeScatter,
50 SeriesTypeSpline,
51 SeriesTypeSpline,
51 SeriesTypeHorizontalBar,
52 SeriesTypeHorizontalBar,
52 SeriesTypeHorizontalStackedBar,
53 SeriesTypeHorizontalStackedBar,
53 SeriesTypeHorizontalPercentBar,
54 SeriesTypeHorizontalPercentBar,
54 SeriesTypeBoxPlot
55 SeriesTypeBoxPlot
55 };
56 };
56
57
57 protected:
58 protected:
58 QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent = 0);
59 QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent = 0);
59
60
60 public:
61 public:
61 ~QAbstractSeries();
62 ~QAbstractSeries();
62 virtual SeriesType type() const = 0;
63 virtual SeriesType type() const = 0;
63
64
64 void setName(const QString &name);
65 void setName(const QString &name);
65 QString name() const;
66 QString name() const;
66 void setVisible(bool visible = true);
67 void setVisible(bool visible = true);
67 bool isVisible() const;
68 bool isVisible() const;
68 qreal opacity() const;
69 qreal opacity() const;
69 void setOpacity(qreal opacity);
70 void setOpacity(qreal opacity);
71 void setUseOpenGL(bool enable = true);
72 bool useOpenGL() const;
70
73
71 QChart *chart() const;
74 QChart *chart() const;
72
75
73 bool attachAxis(QAbstractAxis *axis);
76 bool attachAxis(QAbstractAxis *axis);
74 bool detachAxis(QAbstractAxis *axis);
77 bool detachAxis(QAbstractAxis *axis);
75 QList<QAbstractAxis*> attachedAxes();
78 QList<QAbstractAxis*> attachedAxes();
76
79
77 void show();
80 void show();
78 void hide();
81 void hide();
79
82
80 Q_SIGNALS:
83 Q_SIGNALS:
81 void nameChanged();
84 void nameChanged();
82 void visibleChanged();
85 void visibleChanged();
83 void opacityChanged();
86 void opacityChanged();
87 void useOpenGLChanged();
84
88
85 protected:
89 protected:
86 QScopedPointer<QAbstractSeriesPrivate> d_ptr;
90 QScopedPointer<QAbstractSeriesPrivate> d_ptr;
87 friend class ChartDataSet;
91 friend class ChartDataSet;
88 friend class ChartPresenter;
92 friend class ChartPresenter;
89 friend class ChartThemeManager;
93 friend class ChartThemeManager;
90 friend class QLegendPrivate;
94 friend class QLegendPrivate;
91 friend class DeclarativeChart;
95 friend class DeclarativeChart;
96 friend class QAreaSeries;
92 };
97 };
93
98
94 QT_CHARTS_END_NAMESPACE
99 QT_CHARTS_END_NAMESPACE
95
100
96 #endif // QABSTRACTSERIES_H
101 #endif // QABSTRACTSERIES_H
@@ -1,109 +1,113
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 // W A R N I N G
19 // W A R N I N G
20 // -------------
20 // -------------
21 //
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
24 // version without notice, or even be removed.
25 //
25 //
26 // We mean it.
26 // We mean it.
27
27
28 #ifndef QABSTRACTSERIES_P_H
28 #ifndef QABSTRACTSERIES_P_H
29 #define QABSTRACTSERIES_P_H
29 #define QABSTRACTSERIES_P_H
30
30
31 #include <QtCharts/QAbstractSeries>
31 #include <QtCharts/QAbstractSeries>
32 #include <QtCharts/QChart>
32 #include <QtCharts/QChart>
33 #include <private/abstractdomain_p.h>
33 #include <private/abstractdomain_p.h>
34
34
35 QT_BEGIN_NAMESPACE
35 QT_BEGIN_NAMESPACE
36 class QGraphicsItem;
36 class QGraphicsItem;
37 QT_END_NAMESPACE
37 QT_END_NAMESPACE
38
38
39 QT_CHARTS_BEGIN_NAMESPACE
39 QT_CHARTS_BEGIN_NAMESPACE
40
40
41 class ChartPresenter;
41 class ChartPresenter;
42 class ChartElement;
42 class ChartElement;
43 class LegendMarker;
43 class LegendMarker;
44 class QLegend;
44 class QLegend;
45 class ChartDataSet;
45 class ChartDataSet;
46 class QAbstractAxis;
46 class QAbstractAxis;
47 class QLegendMarker;
47 class QLegendMarker;
48 class ChartTheme;
48 class ChartTheme;
49 class ChartAnimation;
49 class ChartAnimation;
50 class ChartItem;
50 class ChartItem;
51 class BoxPlotChartItem;
51 class BoxPlotChartItem;
52
52
53 class QAbstractSeriesPrivate : public QObject
53 class QAbstractSeriesPrivate : public QObject
54 {
54 {
55 Q_OBJECT
55 Q_OBJECT
56 public:
56 public:
57 QAbstractSeriesPrivate(QAbstractSeries *q);
57 QAbstractSeriesPrivate(QAbstractSeries *q);
58 ~QAbstractSeriesPrivate();
58 ~QAbstractSeriesPrivate();
59
59
60 virtual void initializeDomain() = 0;
60 virtual void initializeDomain() = 0;
61 virtual void initializeAxes() = 0;
61 virtual void initializeAxes() = 0;
62 virtual void initializeTheme(int index, ChartTheme* theme, bool forced = false) = 0;
62 virtual void initializeTheme(int index, ChartTheme* theme, bool forced = false) = 0;
63 virtual void initializeGraphics(QGraphicsItem* parent) = 0;
63 virtual void initializeGraphics(QGraphicsItem* parent) = 0;
64 virtual void initializeAnimations(QChart::AnimationOptions options, int duration,
64 virtual void initializeAnimations(QChart::AnimationOptions options, int duration,
65 QEasingCurve &curve) = 0;
65 QEasingCurve &curve) = 0;
66
66
67 virtual QList<QLegendMarker*> createLegendMarkers(QLegend* legend) = 0;
67 virtual QList<QLegendMarker*> createLegendMarkers(QLegend* legend) = 0;
68
68
69 virtual QAbstractAxis::AxisType defaultAxisType(Qt::Orientation) const = 0;
69 virtual QAbstractAxis::AxisType defaultAxisType(Qt::Orientation) const = 0;
70 virtual QAbstractAxis* createDefaultAxis(Qt::Orientation) const = 0;
70 virtual QAbstractAxis* createDefaultAxis(Qt::Orientation) const = 0;
71
71
72 ChartItem* chartItem() { return m_item.data(); }
72 ChartItem* chartItem() { return m_item.data(); }
73
73
74 virtual void setDomain(AbstractDomain* domain);
74 virtual void setDomain(AbstractDomain* domain);
75 AbstractDomain* domain() { return m_domain.data(); }
75 AbstractDomain* domain() { return m_domain.data(); }
76
76
77 virtual void setPresenter(ChartPresenter *presenter);
77 virtual void setPresenter(ChartPresenter *presenter);
78 ChartPresenter *presenter() const;
78 ChartPresenter *presenter() const;
79
79
80 QChart* chart() { return m_chart; }
80 QChart* chart() { return m_chart; }
81 bool reverseXAxis();
81 bool reverseXAxis();
82 bool reverseYAxis();
82 bool reverseYAxis();
83
83
84 void setBlockOpenGL(bool enable);
85
84 Q_SIGNALS:
86 Q_SIGNALS:
85 void countChanged();
87 void countChanged();
86
88
87 protected:
89 protected:
88 QAbstractSeries *q_ptr;
90 QAbstractSeries *q_ptr;
89 QChart *m_chart;
91 QChart *m_chart;
90 QScopedPointer<ChartItem> m_item;
92 QScopedPointer<ChartItem> m_item;
91 QList<QAbstractAxis*> m_axes;
93 QList<QAbstractAxis*> m_axes;
92
94
93 private:
95 private:
94 QScopedPointer<AbstractDomain> m_domain;
96 QScopedPointer<AbstractDomain> m_domain;
95 QString m_name;
97 QString m_name;
96 bool m_visible;
98 bool m_visible;
97 qreal m_opacity;
99 qreal m_opacity;
98 ChartPresenter *m_presenter;
100 ChartPresenter *m_presenter;
101 bool m_useOpenGL;
102 bool m_blockOpenGL;
99
103
100 friend class QAbstractSeries;
104 friend class QAbstractSeries;
101 friend class ChartDataSet;
105 friend class ChartDataSet;
102 friend class ChartPresenter;
106 friend class ChartPresenter;
103 friend class QLegendPrivate;
107 friend class QLegendPrivate;
104 friend class BoxPlotChartItem;
108 friend class BoxPlotChartItem;
105 };
109 };
106
110
107 QT_CHARTS_END_NAMESPACE
111 QT_CHARTS_END_NAMESPACE
108
112
109 #endif
113 #endif
@@ -1,268 +1,283
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/scatterchartitem_p.h>
19 #include <private/scatterchartitem_p.h>
20 #include <QtCharts/QScatterSeries>
20 #include <QtCharts/QScatterSeries>
21 #include <private/qscatterseries_p.h>
21 #include <private/qscatterseries_p.h>
22 #include <private/chartpresenter_p.h>
22 #include <private/chartpresenter_p.h>
23 #include <private/abstractdomain_p.h>
23 #include <private/abstractdomain_p.h>
24 #include <QtCharts/QChart>
24 #include <QtCharts/QChart>
25 #include <QtGui/QPainter>
25 #include <QtGui/QPainter>
26 #include <QtWidgets/QGraphicsScene>
26 #include <QtWidgets/QGraphicsScene>
27 #include <QtCore/QDebug>
27 #include <QtCore/QDebug>
28 #include <QtWidgets/QGraphicsSceneMouseEvent>
28 #include <QtWidgets/QGraphicsSceneMouseEvent>
29
29
30 QT_CHARTS_BEGIN_NAMESPACE
30 QT_CHARTS_BEGIN_NAMESPACE
31
31
32 ScatterChartItem::ScatterChartItem(QScatterSeries *series, QGraphicsItem *item)
32 ScatterChartItem::ScatterChartItem(QScatterSeries *series, QGraphicsItem *item)
33 : XYChart(series,item),
33 : XYChart(series,item),
34 m_series(series),
34 m_series(series),
35 m_items(this),
35 m_items(this),
36 m_visible(true),
36 m_visible(true),
37 m_shape(QScatterSeries::MarkerShapeRectangle),
37 m_shape(QScatterSeries::MarkerShapeRectangle),
38 m_size(15),
38 m_size(15),
39 m_pointLabelsVisible(false),
39 m_pointLabelsVisible(false),
40 m_pointLabelsFormat(series->pointLabelsFormat()),
40 m_pointLabelsFormat(series->pointLabelsFormat()),
41 m_pointLabelsFont(series->pointLabelsFont()),
41 m_pointLabelsFont(series->pointLabelsFont()),
42 m_pointLabelsColor(series->pointLabelsColor()),
42 m_pointLabelsColor(series->pointLabelsColor()),
43 m_pointLabelsClipping(true),
43 m_pointLabelsClipping(true),
44 m_mousePressed(false)
44 m_mousePressed(false)
45 {
45 {
46 QObject::connect(m_series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdated()));
46 QObject::connect(m_series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdated()));
47 QObject::connect(m_series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
47 QObject::connect(m_series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
48 QObject::connect(m_series, SIGNAL(opacityChanged()), this, SLOT(handleUpdated()));
48 QObject::connect(m_series, SIGNAL(opacityChanged()), this, SLOT(handleUpdated()));
49 QObject::connect(series, SIGNAL(pointLabelsFormatChanged(QString)),
49 QObject::connect(series, SIGNAL(pointLabelsFormatChanged(QString)),
50 this, SLOT(handleUpdated()));
50 this, SLOT(handleUpdated()));
51 QObject::connect(series, SIGNAL(pointLabelsVisibilityChanged(bool)),
51 QObject::connect(series, SIGNAL(pointLabelsVisibilityChanged(bool)),
52 this, SLOT(handleUpdated()));
52 this, SLOT(handleUpdated()));
53 QObject::connect(series, SIGNAL(pointLabelsFontChanged(QFont)), this, SLOT(handleUpdated()));
53 QObject::connect(series, SIGNAL(pointLabelsFontChanged(QFont)), this, SLOT(handleUpdated()));
54 QObject::connect(series, SIGNAL(pointLabelsColorChanged(QColor)), this, SLOT(handleUpdated()));
54 QObject::connect(series, SIGNAL(pointLabelsColorChanged(QColor)), this, SLOT(handleUpdated()));
55 QObject::connect(series, SIGNAL(pointLabelsClippingChanged(bool)), this, SLOT(handleUpdated()));
55 QObject::connect(series, SIGNAL(pointLabelsClippingChanged(bool)), this, SLOT(handleUpdated()));
56
56
57 setZValue(ChartPresenter::ScatterSeriesZValue);
57 setZValue(ChartPresenter::ScatterSeriesZValue);
58 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
58 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
59
59
60 handleUpdated();
60 handleUpdated();
61
61
62 m_items.setHandlesChildEvents(false);
62 m_items.setHandlesChildEvents(false);
63 }
63 }
64
64
65 QRectF ScatterChartItem::boundingRect() const
65 QRectF ScatterChartItem::boundingRect() const
66 {
66 {
67 return m_rect;
67 return m_rect;
68 }
68 }
69
69
70 void ScatterChartItem::createPoints(int count)
70 void ScatterChartItem::createPoints(int count)
71 {
71 {
72 for (int i = 0; i < count; ++i) {
72 for (int i = 0; i < count; ++i) {
73
73
74 QGraphicsItem *item = 0;
74 QGraphicsItem *item = 0;
75
75
76 switch (m_shape) {
76 switch (m_shape) {
77 case QScatterSeries::MarkerShapeCircle: {
77 case QScatterSeries::MarkerShapeCircle: {
78 item = new CircleMarker(0, 0, m_size, m_size, this);
78 item = new CircleMarker(0, 0, m_size, m_size, this);
79 const QRectF &rect = item->boundingRect();
79 const QRectF &rect = item->boundingRect();
80 item->setPos(-rect.width() / 2, -rect.height() / 2);
80 item->setPos(-rect.width() / 2, -rect.height() / 2);
81 break;
81 break;
82 }
82 }
83 case QScatterSeries::MarkerShapeRectangle:
83 case QScatterSeries::MarkerShapeRectangle:
84 item = new RectangleMarker(0, 0, m_size, m_size, this);
84 item = new RectangleMarker(0, 0, m_size, m_size, this);
85 item->setPos(-m_size / 2, -m_size / 2);
85 item->setPos(-m_size / 2, -m_size / 2);
86 break;
86 break;
87 default:
87 default:
88 qWarning() << "Unsupported marker type";
88 qWarning() << "Unsupported marker type";
89 break;
89 break;
90 }
90 }
91 m_items.addToGroup(item);
91 m_items.addToGroup(item);
92 }
92 }
93 }
93 }
94
94
95 void ScatterChartItem::deletePoints(int count)
95 void ScatterChartItem::deletePoints(int count)
96 {
96 {
97 QList<QGraphicsItem *> items = m_items.childItems();
97 QList<QGraphicsItem *> items = m_items.childItems();
98
98
99 for (int i = 0; i < count; ++i) {
99 for (int i = 0; i < count; ++i) {
100 QGraphicsItem *item = items.takeLast();
100 QGraphicsItem *item = items.takeLast();
101 m_markerMap.remove(item);
101 m_markerMap.remove(item);
102 delete(item);
102 delete(item);
103 }
103 }
104 }
104 }
105
105
106 void ScatterChartItem::markerSelected(QGraphicsItem *marker)
106 void ScatterChartItem::markerSelected(QGraphicsItem *marker)
107 {
107 {
108 emit XYChart::clicked(m_markerMap[marker]);
108 emit XYChart::clicked(m_markerMap[marker]);
109 }
109 }
110
110
111 void ScatterChartItem::markerHovered(QGraphicsItem *marker, bool state)
111 void ScatterChartItem::markerHovered(QGraphicsItem *marker, bool state)
112 {
112 {
113 emit XYChart::hovered(m_markerMap[marker], state);
113 emit XYChart::hovered(m_markerMap[marker], state);
114 }
114 }
115
115
116 void ScatterChartItem::markerPressed(QGraphicsItem *marker)
116 void ScatterChartItem::markerPressed(QGraphicsItem *marker)
117 {
117 {
118 emit XYChart::pressed(m_markerMap[marker]);
118 emit XYChart::pressed(m_markerMap[marker]);
119 }
119 }
120
120
121 void ScatterChartItem::markerReleased(QGraphicsItem *marker)
121 void ScatterChartItem::markerReleased(QGraphicsItem *marker)
122 {
122 {
123 emit XYChart::released(m_markerMap[marker]);
123 emit XYChart::released(m_markerMap[marker]);
124 }
124 }
125
125
126 void ScatterChartItem::markerDoubleClicked(QGraphicsItem *marker)
126 void ScatterChartItem::markerDoubleClicked(QGraphicsItem *marker)
127 {
127 {
128 emit XYChart::doubleClicked(m_markerMap[marker]);
128 emit XYChart::doubleClicked(m_markerMap[marker]);
129 }
129 }
130
130
131 void ScatterChartItem::updateGeometry()
131 void ScatterChartItem::updateGeometry()
132 {
132 {
133 static const QRectF dummyRect = QRectF(0.0, 0.0, 0.001, 0.001);
134 if (m_series->useOpenGL()) {
135 if (m_items.childItems().count())
136 deletePoints(m_items.childItems().count());
137 // Fake a miniscule region, so we trigger changed signal.
138 if (m_rect.width() != dummyRect.width()) {
139 prepareGeometryChange();
140 m_rect = dummyRect;
141 }
142 update();
143 return;
144 }
133
145
134 const QVector<QPointF>& points = geometryPoints();
146 const QVector<QPointF>& points = geometryPoints();
135
147
136 if (points.size() == 0) {
148 if (points.size() == 0) {
137 deletePoints(m_items.childItems().count());
149 deletePoints(m_items.childItems().count());
138 return;
150 return;
139 }
151 }
140
152
141 int diff = m_items.childItems().size() - points.size();
153 int diff = m_items.childItems().size() - points.size();
142
154
143 if (diff > 0)
155 if (diff > 0)
144 deletePoints(diff);
156 deletePoints(diff);
145 else if (diff < 0)
157 else if (diff < 0)
146 createPoints(-diff);
158 createPoints(-diff);
147
159
148 if (diff != 0)
160 if (diff != 0)
149 handleUpdated();
161 handleUpdated();
150
162
151 QList<QGraphicsItem *> items = m_items.childItems();
163 QList<QGraphicsItem *> items = m_items.childItems();
152
164
153 QRectF clipRect(QPointF(0,0),domain()->size());
165 QRectF clipRect(QPointF(0,0),domain()->size());
154
166
155 // Only zoom in if the clipRect fits inside int limits. QWidget::update() uses
167 // Only zoom in if the clipRect fits inside int limits. QWidget::update() uses
156 // a region that has to be compatible with QRect.
168 // a region that has to be compatible with QRect.
157 if (clipRect.height() <= INT_MAX
169 if (clipRect.height() <= INT_MAX
158 && clipRect.width() <= INT_MAX) {
170 && clipRect.width() <= INT_MAX) {
159 QVector<bool> offGridStatus = offGridStatusVector();
171 QVector<bool> offGridStatus = offGridStatusVector();
160 const int seriesLastIndex = m_series->count() - 1;
172 const int seriesLastIndex = m_series->count() - 1;
161
173
162 for (int i = 0; i < points.size(); i++) {
174 for (int i = 0; i < points.size(); i++) {
163 QGraphicsItem *item = items.at(i);
175 QGraphicsItem *item = items.at(i);
164 const QPointF &point = points.at(i);
176 const QPointF &point = points.at(i);
165 const QRectF &rect = item->boundingRect();
177 const QRectF &rect = item->boundingRect();
166 // During remove animation series may have different number of points,
178 // During remove animation series may have different number of points,
167 // so ensure we don't go over the index. Animation handling itself ensures that
179 // so ensure we don't go over the index. Animation handling itself ensures that
168 // if there is actually no points in the series, then it won't generate a fake point,
180 // if there is actually no points in the series, then it won't generate a fake point,
169 // so we can be assured there is always at least one point in m_series here.
181 // so we can be assured there is always at least one point in m_series here.
170 // Note that marker map values can be technically incorrect during the animation,
182 // Note that marker map values can be technically incorrect during the animation,
171 // if it was caused by an insert, but this shouldn't be a problem as the points are
183 // if it was caused by an insert, but this shouldn't be a problem as the points are
172 // fake anyway. After remove animation stops, geometry is updated to correct one.
184 // fake anyway. After remove animation stops, geometry is updated to correct one.
173 m_markerMap[item] = m_series->at(qMin(seriesLastIndex, i));
185 m_markerMap[item] = m_series->at(qMin(seriesLastIndex, i));
174 QPointF position;
186 QPointF position;
175 if (seriesPrivate()->reverseXAxis())
187 if (seriesPrivate()->reverseXAxis())
176 position.setX(domain()->size().width() - point.x() - rect.width() / 2);
188 position.setX(domain()->size().width() - point.x() - rect.width() / 2);
177 else
189 else
178 position.setX(point.x() - rect.width() / 2);
190 position.setX(point.x() - rect.width() / 2);
179 if (seriesPrivate()->reverseYAxis())
191 if (seriesPrivate()->reverseYAxis())
180 position.setY(domain()->size().height() - point.y() - rect.height() / 2);
192 position.setY(domain()->size().height() - point.y() - rect.height() / 2);
181 else
193 else
182 position.setY(point.y() - rect.height() / 2);
194 position.setY(point.y() - rect.height() / 2);
183 item->setPos(position);
195 item->setPos(position);
184
196
185
197
186 if (!m_visible || offGridStatus.at(i))
198 if (!m_visible || offGridStatus.at(i))
187 item->setVisible(false);
199 item->setVisible(false);
188 else
200 else
189 item->setVisible(true);
201 item->setVisible(true);
190 }
202 }
191
203
192 prepareGeometryChange();
204 prepareGeometryChange();
193 m_rect = clipRect;
205 m_rect = clipRect;
194 }
206 }
195 }
207 }
196
208
197 void ScatterChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
209 void ScatterChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
198 {
210 {
199 Q_UNUSED(option)
211 Q_UNUSED(option)
200 Q_UNUSED(widget)
212 Q_UNUSED(widget)
201
213
214 if (m_series->useOpenGL())
215 return;
216
202 QRectF clipRect = QRectF(QPointF(0, 0), domain()->size());
217 QRectF clipRect = QRectF(QPointF(0, 0), domain()->size());
203
218
204 painter->save();
219 painter->save();
205 painter->setClipRect(clipRect);
220 painter->setClipRect(clipRect);
206
221
207 if (m_pointLabelsVisible) {
222 if (m_pointLabelsVisible) {
208 if (m_pointLabelsClipping)
223 if (m_pointLabelsClipping)
209 painter->setClipping(true);
224 painter->setClipping(true);
210 else
225 else
211 painter->setClipping(false);
226 painter->setClipping(false);
212 m_series->d_func()->drawSeriesPointLabels(painter, m_points,
227 m_series->d_func()->drawSeriesPointLabels(painter, m_points,
213 m_series->markerSize() / 2
228 m_series->markerSize() / 2
214 + m_series->pen().width());
229 + m_series->pen().width());
215 }
230 }
216
231
217 painter->restore();
232 painter->restore();
218 }
233 }
219
234
220 void ScatterChartItem::setPen(const QPen &pen)
235 void ScatterChartItem::setPen(const QPen &pen)
221 {
236 {
222 foreach (QGraphicsItem *item , m_items.childItems())
237 foreach (QGraphicsItem *item , m_items.childItems())
223 static_cast<QAbstractGraphicsShapeItem*>(item)->setPen(pen);
238 static_cast<QAbstractGraphicsShapeItem*>(item)->setPen(pen);
224 }
239 }
225
240
226 void ScatterChartItem::setBrush(const QBrush &brush)
241 void ScatterChartItem::setBrush(const QBrush &brush)
227 {
242 {
228 foreach (QGraphicsItem *item , m_items.childItems())
243 foreach (QGraphicsItem *item , m_items.childItems())
229 static_cast<QAbstractGraphicsShapeItem*>(item)->setBrush(brush);
244 static_cast<QAbstractGraphicsShapeItem*>(item)->setBrush(brush);
230 }
245 }
231
246
232 void ScatterChartItem::handleUpdated()
247 void ScatterChartItem::handleUpdated()
233 {
248 {
234 int count = m_items.childItems().count();
249 int count = m_items.childItems().count();
235
250
236 if (count == 0)
251 if (count == 0)
237 return;
252 return;
238
253
239 bool recreate = m_visible != m_series->isVisible()
254 bool recreate = m_visible != m_series->isVisible()
240 || m_size != m_series->markerSize()
255 || m_size != m_series->markerSize()
241 || m_shape != m_series->markerShape();
256 || m_shape != m_series->markerShape();
242
257
243 m_visible = m_series->isVisible();
258 m_visible = m_series->isVisible();
244 m_size = m_series->markerSize();
259 m_size = m_series->markerSize();
245 m_shape = m_series->markerShape();
260 m_shape = m_series->markerShape();
246 setOpacity(m_series->opacity());
261 setOpacity(m_series->opacity());
247 m_pointLabelsFormat = m_series->pointLabelsFormat();
262 m_pointLabelsFormat = m_series->pointLabelsFormat();
248 m_pointLabelsVisible = m_series->pointLabelsVisible();
263 m_pointLabelsVisible = m_series->pointLabelsVisible();
249 m_pointLabelsFont = m_series->pointLabelsFont();
264 m_pointLabelsFont = m_series->pointLabelsFont();
250 m_pointLabelsColor = m_series->pointLabelsColor();
265 m_pointLabelsColor = m_series->pointLabelsColor();
251 m_pointLabelsClipping = m_series->pointLabelsClipping();
266 m_pointLabelsClipping = m_series->pointLabelsClipping();
252
267
253 if (recreate) {
268 if (recreate) {
254 deletePoints(count);
269 deletePoints(count);
255 createPoints(count);
270 createPoints(count);
256
271
257 // Updating geometry is now safe, because it won't call handleUpdated unless it creates/deletes points
272 // Updating geometry is now safe, because it won't call handleUpdated unless it creates/deletes points
258 updateGeometry();
273 updateGeometry();
259 }
274 }
260
275
261 setPen(m_series->pen());
276 setPen(m_series->pen());
262 setBrush(m_series->brush());
277 setBrush(m_series->brush());
263 update();
278 update();
264 }
279 }
265
280
266 #include "moc_scatterchartitem_p.cpp"
281 #include "moc_scatterchartitem_p.cpp"
267
282
268 QT_CHARTS_END_NAMESPACE
283 QT_CHARTS_END_NAMESPACE
@@ -1,963 +1,980
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <QtCharts/QXYSeries>
19 #include <QtCharts/QXYSeries>
20 #include <private/qxyseries_p.h>
20 #include <private/qxyseries_p.h>
21 #include <private/abstractdomain_p.h>
21 #include <private/abstractdomain_p.h>
22 #include <QtCharts/QValueAxis>
22 #include <QtCharts/QValueAxis>
23 #include <private/xychart_p.h>
23 #include <private/xychart_p.h>
24 #include <QtCharts/QXYLegendMarker>
24 #include <QtCharts/QXYLegendMarker>
25 #include <private/charthelpers_p.h>
25 #include <private/charthelpers_p.h>
26 #include <private/qchart_p.h>
26 #include <private/qchart_p.h>
27 #include <QtGui/QPainter>
27 #include <QtGui/QPainter>
28
28
29 QT_CHARTS_BEGIN_NAMESPACE
29 QT_CHARTS_BEGIN_NAMESPACE
30
30
31 /*!
31 /*!
32 \class QXYSeries
32 \class QXYSeries
33 \inmodule Qt Charts
33 \inmodule Qt Charts
34 \brief The QXYSeries class is a base class for line, spline and scatter series.
34 \brief The QXYSeries class is a base class for line, spline and scatter series.
35 */
35 */
36 /*!
36 /*!
37 \qmltype XYSeries
37 \qmltype XYSeries
38 \instantiates QXYSeries
38 \instantiates QXYSeries
39 \inqmlmodule QtCharts
39 \inqmlmodule QtCharts
40
40
41 \inherits AbstractSeries
41 \inherits AbstractSeries
42
42
43 \brief The XYSeries type is a base type for line, spline and scatter series.
43 \brief The XYSeries type is a base type for line, spline and scatter series.
44
44
45 The XYSeries class is a base class for line, spline and scatter series.
45 The XYSeries class is a base class for line, spline and scatter series.
46 The class cannot be instantiated directly.
46 The class cannot be instantiated directly.
47 */
47 */
48
48
49 /*!
49 /*!
50 \qmlproperty AbstractAxis XYSeries::axisX
50 \qmlproperty AbstractAxis XYSeries::axisX
51 The x axis used for the series. If you leave both axisX and axisXTop undefined, a ValueAxis is created for
51 The x axis used for the series. If you leave both axisX and axisXTop undefined, a ValueAxis is created for
52 the series.
52 the series.
53 \sa axisXTop
53 \sa axisXTop
54 */
54 */
55
55
56 /*!
56 /*!
57 \qmlproperty AbstractAxis XYSeries::axisY
57 \qmlproperty AbstractAxis XYSeries::axisY
58 The y axis used for the series. If you leave both axisY and axisYRight undefined, a ValueAxis is created for
58 The y axis used for the series. If you leave both axisY and axisYRight undefined, a ValueAxis is created for
59 the series.
59 the series.
60 \sa axisYRight
60 \sa axisYRight
61 */
61 */
62
62
63 /*!
63 /*!
64 \qmlproperty AbstractAxis XYSeries::axisXTop
64 \qmlproperty AbstractAxis XYSeries::axisXTop
65 The x axis used for the series, drawn on top of the chart view. Note that you can only provide either axisX or
65 The x axis used for the series, drawn on top of the chart view. Note that you can only provide either axisX or
66 axisXTop, but not both.
66 axisXTop, but not both.
67 \sa axisX
67 \sa axisX
68 */
68 */
69
69
70 /*!
70 /*!
71 \qmlproperty AbstractAxis XYSeries::axisYRight
71 \qmlproperty AbstractAxis XYSeries::axisYRight
72 The y axis used for the series, drawn to the right on the chart view. Note that you can only provide either axisY
72 The y axis used for the series, drawn to the right on the chart view. Note that you can only provide either axisY
73 or axisYRight, but not both.
73 or axisYRight, but not both.
74 \sa axisY
74 \sa axisY
75 */
75 */
76
76
77 /*!
77 /*!
78 \qmlproperty AbstractAxis XYSeries::axisAngular
78 \qmlproperty AbstractAxis XYSeries::axisAngular
79 The angular axis used for the series, drawn around the polar chart view.
79 The angular axis used for the series, drawn around the polar chart view.
80 \sa axisX
80 \sa axisX
81 */
81 */
82
82
83 /*!
83 /*!
84 \qmlproperty AbstractAxis XYSeries::axisRadial
84 \qmlproperty AbstractAxis XYSeries::axisRadial
85 The radial axis used for the series, drawn inside the polar chart view.
85 The radial axis used for the series, drawn inside the polar chart view.
86 \sa axisY
86 \sa axisY
87 */
87 */
88
88
89 /*!
89 /*!
90 \property QXYSeries::pointsVisible
90 \property QXYSeries::pointsVisible
91 Controls if the data points are visible and should be drawn.
91 Controls if the data points are visible and should be drawn.
92 */
92 */
93 /*!
93 /*!
94 \qmlproperty bool XYSeries::pointsVisible
94 \qmlproperty bool XYSeries::pointsVisible
95 Controls if the data points are visible and should be drawn.
95 Controls if the data points are visible and should be drawn.
96 */
96 */
97
97
98 /*!
98 /*!
99 \fn QPen QXYSeries::pen() const
99 \fn QPen QXYSeries::pen() const
100 \brief Returns pen used to draw points for series.
100 \brief Returns pen used to draw points for series.
101 \sa setPen()
101 \sa setPen()
102 */
102 */
103
103
104 /*!
104 /*!
105 \fn QBrush QXYSeries::brush() const
105 \fn QBrush QXYSeries::brush() const
106 \brief Returns brush used to draw points for series.
106 \brief Returns brush used to draw points for series.
107 \sa setBrush()
107 \sa setBrush()
108 */
108 */
109
109
110 /*!
110 /*!
111 \property QXYSeries::color
111 \property QXYSeries::color
112 The color of the series. This is line (pen) color in case of QLineSeries or QSplineSeries and
112 The color of the series. This is line (pen) color in case of QLineSeries or QSplineSeries and
113 fill (brush) color in case of QScatterSeries or QAreaSeries.
113 fill (brush) color in case of QScatterSeries or QAreaSeries.
114 \sa pen(), brush()
114 \sa pen(), brush()
115 */
115 */
116 /*!
116 /*!
117 \qmlproperty color XYSeries::color
117 \qmlproperty color XYSeries::color
118 The color of the series. This is line (pen) color in case of LineSeries or SplineSeries and
118 The color of the series. This is line (pen) color in case of LineSeries or SplineSeries and
119 fill (brush) color in case of ScatterSeries or AreaSeries.
119 fill (brush) color in case of ScatterSeries or AreaSeries.
120 */
120 */
121
121
122 /*!
122 /*!
123 \property QXYSeries::pointLabelsFormat
123 \property QXYSeries::pointLabelsFormat
124 The \a format used for showing labels with series points.
124 The \a format used for showing labels with series points.
125
125
126 QXYSeries supports the following format tags:
126 QXYSeries supports the following format tags:
127 \table
127 \table
128 \row
128 \row
129 \li @xPoint \li The x value of the data point
129 \li @xPoint \li The x value of the data point
130 \row
130 \row
131 \li @yPoint \li The y value of the data point
131 \li @yPoint \li The y value of the data point
132 \endtable
132 \endtable
133
133
134 For example, the following usage of the format tags would produce labels that have the data
134 For example, the following usage of the format tags would produce labels that have the data
135 point (x, y) shown inside brackets separated by a comma:
135 point (x, y) shown inside brackets separated by a comma:
136 \code
136 \code
137 series->setPointLabelsFormat("(@xPoint, @yPoint)");
137 series->setPointLabelsFormat("(@xPoint, @yPoint)");
138 \endcode
138 \endcode
139
139
140 By default, the labels format is set to '@xPoint, @yPoint'. The labels are shown on the plot
140 By default, the labels format is set to '@xPoint, @yPoint'. The labels are shown on the plot
141 area, labels on the edge of the plot area are cut. If the points are close to each other the
141 area, labels on the edge of the plot area are cut. If the points are close to each other the
142 labels may overlap.
142 labels may overlap.
143
143
144 \sa pointLabelsVisible, pointLabelsFont, pointLabelsColor
144 \sa pointLabelsVisible, pointLabelsFont, pointLabelsColor
145 */
145 */
146 /*!
146 /*!
147 \qmlproperty string XYSeries::pointLabelsFormat
147 \qmlproperty string XYSeries::pointLabelsFormat
148 The \a format used for showing labels with series points.
148 The \a format used for showing labels with series points.
149
149
150 \sa pointLabelsFormat, pointLabelsVisible, pointLabelsFont, pointLabelsColor
150 \sa pointLabelsFormat, pointLabelsVisible, pointLabelsFont, pointLabelsColor
151 */
151 */
152 /*!
152 /*!
153 \fn void QXYSeries::pointLabelsFormatChanged(const QString &format)
153 \fn void QXYSeries::pointLabelsFormatChanged(const QString &format)
154 Signal is emitted when the \a format of data point labels is changed.
154 Signal is emitted when the \a format of data point labels is changed.
155 */
155 */
156 /*!
156 /*!
157 \qmlsignal XYSeries::onPointLabelsFormatChanged(string format)
157 \qmlsignal XYSeries::onPointLabelsFormatChanged(string format)
158 Signal is emitted when the \a format of data point labels is changed.
158 Signal is emitted when the \a format of data point labels is changed.
159 */
159 */
160
160
161 /*!
161 /*!
162 \property QXYSeries::pointLabelsVisible
162 \property QXYSeries::pointLabelsVisible
163 Defines the visibility for data point labels. False by default.
163 Defines the visibility for data point labels. False by default.
164
164
165 \sa pointLabelsFormat, pointLabelsClipping
165 \sa pointLabelsFormat, pointLabelsClipping
166 */
166 */
167 /*!
167 /*!
168 \qmlproperty bool XYSeries::pointLabelsVisible
168 \qmlproperty bool XYSeries::pointLabelsVisible
169 Defines the visibility for data point labels.
169 Defines the visibility for data point labels.
170
170
171 \sa pointLabelsFormat, pointLabelsClipping
171 \sa pointLabelsFormat, pointLabelsClipping
172 */
172 */
173 /*!
173 /*!
174 \fn void QXYSeries::pointLabelsVisibilityChanged(bool visible)
174 \fn void QXYSeries::pointLabelsVisibilityChanged(bool visible)
175 The visibility of the data point labels is changed to \a visible.
175 The visibility of the data point labels is changed to \a visible.
176 */
176 */
177 /*!
177 /*!
178 \qmlsignal XYSeries::onPointLabelsVisibilityChanged(bool visible)
178 \qmlsignal XYSeries::onPointLabelsVisibilityChanged(bool visible)
179 The visibility of the data point labels is changed to \a visible.
179 The visibility of the data point labels is changed to \a visible.
180 */
180 */
181
181
182 /*!
182 /*!
183 \property QXYSeries::pointLabelsFont
183 \property QXYSeries::pointLabelsFont
184 Defines the font used for data point labels.
184 Defines the font used for data point labels.
185
185
186 \sa pointLabelsFormat
186 \sa pointLabelsFormat
187 */
187 */
188 /*!
188 /*!
189 \qmlproperty font XYSeries::pointLabelsFont
189 \qmlproperty font XYSeries::pointLabelsFont
190 Defines the font used for data point labels.
190 Defines the font used for data point labels.
191
191
192 \sa pointLabelsFormat
192 \sa pointLabelsFormat
193 */
193 */
194 /*!
194 /*!
195 \fn void QXYSeries::pointLabelsFontChanged(const QFont &font);
195 \fn void QXYSeries::pointLabelsFontChanged(const QFont &font);
196 The font used for data point labels is changed to \a font.
196 The font used for data point labels is changed to \a font.
197 */
197 */
198 /*!
198 /*!
199 \qmlsignal XYSeries::onPointLabelsFontChanged(Font font)
199 \qmlsignal XYSeries::onPointLabelsFontChanged(Font font)
200 The font used for data point labels is changed to \a font.
200 The font used for data point labels is changed to \a font.
201 */
201 */
202
202
203 /*!
203 /*!
204 \property QXYSeries::pointLabelsColor
204 \property QXYSeries::pointLabelsColor
205 Defines the color used for data point labels. By default, the color is the color of the brush
205 Defines the color used for data point labels. By default, the color is the color of the brush
206 defined in theme for labels.
206 defined in theme for labels.
207
207
208 \sa pointLabelsFormat
208 \sa pointLabelsFormat
209 */
209 */
210 /*!
210 /*!
211 \qmlproperty font XYSeries::pointLabelsColor
211 \qmlproperty font XYSeries::pointLabelsColor
212 Defines the color used for data point labels. By default, the color is the color of the brush
212 Defines the color used for data point labels. By default, the color is the color of the brush
213 defined in theme for labels.
213 defined in theme for labels.
214
214
215 \sa pointLabelsFormat
215 \sa pointLabelsFormat
216 */
216 */
217 /*!
217 /*!
218 \fn void QXYSeries::pointLabelsColorChanged(const QColor &color);
218 \fn void QXYSeries::pointLabelsColorChanged(const QColor &color);
219 The color used for data point labels is changed to \a color.
219 The color used for data point labels is changed to \a color.
220 */
220 */
221 /*!
221 /*!
222 \qmlsignal XYSeries::onPointLabelsColorChanged(Color color)
222 \qmlsignal XYSeries::onPointLabelsColorChanged(Color color)
223 The color used for data point labels is changed to \a color.
223 The color used for data point labels is changed to \a color.
224 */
224 */
225
225
226 /*!
226 /*!
227 \property QXYSeries::pointLabelsClipping
227 \property QXYSeries::pointLabelsClipping
228 Defines the clipping for data point labels. True by default. The labels on the edge of the plot
228 Defines the clipping for data point labels. True by default. The labels on the edge of the plot
229 area are cut when clipping is enabled.
229 area are cut when clipping is enabled.
230
230
231 \sa pointLabelsVisible
231 \sa pointLabelsVisible
232 */
232 */
233 /*!
233 /*!
234 \qmlproperty bool XYSeries::pointLabelsClipping
234 \qmlproperty bool XYSeries::pointLabelsClipping
235 Defines the clipping for data point labels. True by default. The labels on the edge of the plot
235 Defines the clipping for data point labels. True by default. The labels on the edge of the plot
236 area are cut when clipping is enabled.
236 area are cut when clipping is enabled.
237
237
238 \sa pointLabelsVisible
238 \sa pointLabelsVisible
239 */
239 */
240 /*!
240 /*!
241 \fn void QXYSeries::pointLabelsClippintChanged(bool clipping)
241 \fn void QXYSeries::pointLabelsClippingChanged(bool clipping)
242 The clipping of the data point labels is changed to \a clipping.
242 The clipping of the data point labels is changed to \a clipping.
243 */
243 */
244 /*!
244 /*!
245 \qmlsignal XYSeries::onPointLabelsClippingChanged(bool clipping)
245 \qmlsignal XYSeries::onPointLabelsClippingChanged(bool clipping)
246 The clipping of the data point labels is changed to \a clipping.
246 The clipping of the data point labels is changed to \a clipping.
247 */
247 */
248
248
249 /*!
249 /*!
250 \fn void QXYSeries::clicked(const QPointF& point)
250 \fn void QXYSeries::clicked(const QPointF& point)
251 \brief Signal is emitted when user clicks the \a point on chart. The \a point is the point
251 \brief Signal is emitted when user clicks the \a point on chart. The \a point is the point
252 where the press was triggered.
252 where the press was triggered.
253 \sa pressed, released, doubleClicked
253 \sa pressed, released, doubleClicked
254 */
254 */
255 /*!
255 /*!
256 \qmlsignal XYSeries::onClicked(QPointF point)
256 \qmlsignal XYSeries::onClicked(QPointF point)
257 Signal is emitted when user clicks the \a point on chart. The \a point is the point where the
257 Signal is emitted when user clicks the \a point on chart. The \a point is the point where the
258 press was triggered. For example:
258 press was triggered. For example:
259 \code
259 \code
260 LineSeries {
260 LineSeries {
261 XYPoint { x: 0; y: 0 }
261 XYPoint { x: 0; y: 0 }
262 XYPoint { x: 1.1; y: 2.1 }
262 XYPoint { x: 1.1; y: 2.1 }
263 onClicked: console.log("onClicked: " + point.x + ", " + point.y);
263 onClicked: console.log("onClicked: " + point.x + ", " + point.y);
264 }
264 }
265 \endcode
265 \endcode
266 \sa onPressed, onReleased, onDoubleClicked
266 \sa onPressed, onReleased, onDoubleClicked
267 */
267 */
268
268
269 /*!
269 /*!
270 \fn void QXYSeries::hovered(const QPointF &point, bool state)
270 \fn void QXYSeries::hovered(const QPointF &point, bool state)
271 This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
271 This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
272 of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
272 of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
273 the series.
273 the series.
274 */
274 */
275 /*!
275 /*!
276 \qmlsignal XYSeries::onHovered(point point, bool state)
276 \qmlsignal XYSeries::onHovered(point point, bool state)
277 This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
277 This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
278 of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
278 of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
279 the series.
279 the series.
280 */
280 */
281
281
282 /*!
282 /*!
283 \fn void QXYSeries::pressed(const QPointF& point)
283 \fn void QXYSeries::pressed(const QPointF& point)
284 \brief Signal is emitted when user presses the \a point on chart.
284 \brief Signal is emitted when user presses the \a point on chart.
285 \sa clicked, released, doubleClicked
285 \sa clicked, released, doubleClicked
286 */
286 */
287 /*!
287 /*!
288 \qmlsignal XYSeries::onPressed(QPointF point)
288 \qmlsignal XYSeries::onPressed(QPointF point)
289 Signal is emitted when user presses the \a point on chart. For example:
289 Signal is emitted when user presses the \a point on chart. For example:
290 \code
290 \code
291 LineSeries {
291 LineSeries {
292 XYPoint { x: 0; y: 0 }
292 XYPoint { x: 0; y: 0 }
293 XYPoint { x: 1.1; y: 2.1 }
293 XYPoint { x: 1.1; y: 2.1 }
294 onPressed: console.log("onPressed: " + point.x + ", " + point.y);
294 onPressed: console.log("onPressed: " + point.x + ", " + point.y);
295 }
295 }
296 \endcode
296 \endcode
297 \sa onClicked, onReleased, onDoubleClicked
297 \sa onClicked, onReleased, onDoubleClicked
298 */
298 */
299
299
300 /*!
300 /*!
301 \fn void QXYSeries::released(const QPointF& point)
301 \fn void QXYSeries::released(const QPointF& point)
302 \brief Signal is emitted when user releases a press that was triggered on a \a point on chart.
302 \brief Signal is emitted when user releases a press that was triggered on a \a point on chart.
303 \sa pressed, clicked, doubleClicked
303 \sa pressed, clicked, doubleClicked
304 */
304 */
305 /*!
305 /*!
306 \qmlsignal XYSeries::onReleased(QPointF point)
306 \qmlsignal XYSeries::onReleased(QPointF point)
307 Signal is emitted when user releases a press that was triggered on a \a point on chart.
307 Signal is emitted when user releases a press that was triggered on a \a point on chart.
308 For example:
308 For example:
309 \code
309 \code
310 LineSeries {
310 LineSeries {
311 XYPoint { x: 0; y: 0 }
311 XYPoint { x: 0; y: 0 }
312 XYPoint { x: 1.1; y: 2.1 }
312 XYPoint { x: 1.1; y: 2.1 }
313 onReleased: console.log("onReleased: " + point.x + ", " + point.y);
313 onReleased: console.log("onReleased: " + point.x + ", " + point.y);
314 }
314 }
315 \endcode
315 \endcode
316 \sa onPressed, onClicked, onDoubleClicked
316 \sa onPressed, onClicked, onDoubleClicked
317 */
317 */
318
318
319 /*!
319 /*!
320 \fn void QXYSeries::doubleClicked(const QPointF& point)
320 \fn void QXYSeries::doubleClicked(const QPointF& point)
321 \brief Signal is emitted when user doubleclicks the \a point on chart. The \a point is the
321 \brief Signal is emitted when user doubleclicks the \a point on chart. The \a point is the
322 point where the first press was triggered.
322 point where the first press was triggered.
323 \sa pressed, released, clicked
323 \sa pressed, released, clicked
324 */
324 */
325 /*!
325 /*!
326 \qmlsignal XYSeries::onDoubleClicked(QPointF point)
326 \qmlsignal XYSeries::onDoubleClicked(QPointF point)
327 Signal is emitted when user doubleclicks the \a point on chart. The \a point is the point where
327 Signal is emitted when user doubleclicks the \a point on chart. The \a point is the point where
328 the first press was triggered. For example:
328 the first press was triggered. For example:
329 \code
329 \code
330 LineSeries {
330 LineSeries {
331 XYPoint { x: 0; y: 0 }
331 XYPoint { x: 0; y: 0 }
332 XYPoint { x: 1.1; y: 2.1 }
332 XYPoint { x: 1.1; y: 2.1 }
333 onDoubleClicked: console.log("onDoubleClicked: " + point.x + ", " + point.y);
333 onDoubleClicked: console.log("onDoubleClicked: " + point.x + ", " + point.y);
334 }
334 }
335 \endcode
335 \endcode
336 \sa onPressed, onReleased, onClicked
336 \sa onPressed, onReleased, onClicked
337 */
337 */
338
338
339 /*!
339 /*!
340 \fn void QXYSeries::pointReplaced(int index)
340 \fn void QXYSeries::pointReplaced(int index)
341 Signal is emitted when a point has been replaced at \a index.
341 Signal is emitted when a point has been replaced at \a index.
342 \sa replace()
342 \sa replace()
343 */
343 */
344 /*!
344 /*!
345 \qmlsignal XYSeries::onPointReplaced(int index)
345 \qmlsignal XYSeries::onPointReplaced(int index)
346 Signal is emitted when a point has been replaced at \a index.
346 Signal is emitted when a point has been replaced at \a index.
347 */
347 */
348
348
349 /*!
349 /*!
350 \fn void QXYSeries::pointsReplaced()
350 \fn void QXYSeries::pointsReplaced()
351 Signal is emitted when all points have been replaced with other points.
351 Signal is emitted when all points have been replaced with other points.
352 \sa replace()
352 \sa replace()
353 */
353 */
354 /*!
354 /*!
355 \qmlsignal XYSeries::onPointsReplaced()
355 \qmlsignal XYSeries::onPointsReplaced()
356 Signal is emitted when all points have been replaced with other points.
356 Signal is emitted when all points have been replaced with other points.
357 */
357 */
358
358
359 /*!
359 /*!
360 \fn void QXYSeries::pointAdded(int index)
360 \fn void QXYSeries::pointAdded(int index)
361 Signal is emitted when a point has been added at \a index.
361 Signal is emitted when a point has been added at \a index.
362 \sa append(), insert()
362 \sa append(), insert()
363 */
363 */
364 /*!
364 /*!
365 \qmlsignal XYSeries::onPointAdded(int index)
365 \qmlsignal XYSeries::onPointAdded(int index)
366 Signal is emitted when a point has been added at \a index.
366 Signal is emitted when a point has been added at \a index.
367 */
367 */
368
368
369 /*!
369 /*!
370 \fn void QXYSeries::pointRemoved(int index)
370 \fn void QXYSeries::pointRemoved(int index)
371 Signal is emitted when a point has been removed from \a index.
371 Signal is emitted when a point has been removed from \a index.
372 \sa remove()
372 \sa remove()
373 */
373 */
374
374
375 /*!
375 /*!
376 \qmlsignal XYSeries::onPointRemoved(int index)
376 \qmlsignal XYSeries::onPointRemoved(int index)
377 Signal is emitted when a point has been removed from \a index.
377 Signal is emitted when a point has been removed from \a index.
378 */
378 */
379
379
380 /*!
380 /*!
381 \fn void QXYSeries::pointsRemoved(int index, int count)
381 \fn void QXYSeries::pointsRemoved(int index, int count)
382 Signal is emitted when a \a count of points has been removed starting at \a index.
382 Signal is emitted when a \a count of points has been removed starting at \a index.
383 \sa removePoints(), clear()
383 \sa removePoints(), clear()
384 */
384 */
385
385
386 /*!
386 /*!
387 \qmlsignal XYSeries::onPointsRemoved(int index, int count)
387 \qmlsignal XYSeries::onPointsRemoved(int index, int count)
388 Signal is emitted when a \a count of points has been removed starting at \a index.
388 Signal is emitted when a \a count of points has been removed starting at \a index.
389 */
389 */
390
390
391 /*!
391 /*!
392 \fn void QXYSeries::colorChanged(QColor color)
392 \fn void QXYSeries::colorChanged(QColor color)
393 \brief Signal is emitted when the line (pen) color has changed to \a color.
393 \brief Signal is emitted when the line (pen) color has changed to \a color.
394 */
394 */
395 /*!
395 /*!
396 \qmlsignal XYSeries::onColorChanged(color color)
396 \qmlsignal XYSeries::onColorChanged(color color)
397 Signal is emitted when the line (pen) color has changed to \a color.
397 Signal is emitted when the line (pen) color has changed to \a color.
398 */
398 */
399
399
400 /*!
400 /*!
401 \fn void QXYSeries::penChanged(const QPen &pen)
402 \brief Signal is emitted when the line pen has changed to \a pen.
403 */
404
405 /*!
401 \fn void QXYSeriesPrivate::updated()
406 \fn void QXYSeriesPrivate::updated()
402 \brief \internal
407 \brief \internal
403 */
408 */
404
409
405 /*!
410 /*!
406 \qmlmethod XYSeries::append(real x, real y)
411 \qmlmethod XYSeries::append(real x, real y)
407 Append point (\a x, \a y) to the series
412 Append point (\a x, \a y) to the series
408 */
413 */
409
414
410 /*!
415 /*!
411 \qmlmethod XYSeries::replace(real oldX, real oldY, real newX, real newY)
416 \qmlmethod XYSeries::replace(real oldX, real oldY, real newX, real newY)
412 Replaces point (\a oldX, \a oldY) with point (\a newX, \a newY). Does nothing, if point (oldX, oldY) does not
417 Replaces point (\a oldX, \a oldY) with point (\a newX, \a newY). Does nothing, if point (oldX, oldY) does not
413 exist.
418 exist.
414 */
419 */
415
420
416 /*!
421 /*!
417 \qmlmethod XYSeries::remove(real x, real y)
422 \qmlmethod XYSeries::remove(real x, real y)
418 Removes point (\a x, \a y) from the series. Does nothing, if point (x, y) does not exist.
423 Removes point (\a x, \a y) from the series. Does nothing, if point (x, y) does not exist.
419 */
424 */
420
425
421 /*!
426 /*!
422 \qmlmethod XYSeries::remove(int index)
427 \qmlmethod XYSeries::remove(int index)
423 Removes a point from the series at \a index.
428 Removes a point from the series at \a index.
424 */
429 */
425
430
426 /*!
431 /*!
427 \qmlmethod XYSeries::removePoints(int index, int count)
432 \qmlmethod XYSeries::removePoints(int index, int count)
428 Removes \a count points from the series starting at \a index.
433 Removes \a count points from the series starting at \a index.
429 */
434 */
430
435
431 /*!
436 /*!
432 \qmlmethod XYSeries::insert(int index, real x, real y)
437 \qmlmethod XYSeries::insert(int index, real x, real y)
433 Inserts point (\a x, \a y) to the \a index. If index is 0 or smaller than 0 the point is prepended to the list of
438 Inserts point (\a x, \a y) to the \a index. If index is 0 or smaller than 0 the point is prepended to the list of
434 points. If index is the same as or bigger than count, the point is appended to the list of points.
439 points. If index is the same as or bigger than count, the point is appended to the list of points.
435 */
440 */
436
441
437 /*!
442 /*!
438 \qmlmethod QPointF XYSeries::at(int index)
443 \qmlmethod QPointF XYSeries::at(int index)
439 Returns point at \a index. Returns (0, 0) if the index is not valid.
444 Returns point at \a index. Returns (0, 0) if the index is not valid.
440 */
445 */
441
446
442 /*!
447 /*!
443 \internal
448 \internal
444
449
445 Constructs empty series object which is a child of \a parent.
450 Constructs empty series object which is a child of \a parent.
446 When series object is added to QChart instance ownerships is transferred.
451 When series object is added to QChart instance ownerships is transferred.
447 */
452 */
448 QXYSeries::QXYSeries(QXYSeriesPrivate &d, QObject *parent)
453 QXYSeries::QXYSeries(QXYSeriesPrivate &d, QObject *parent)
449 : QAbstractSeries(d, parent)
454 : QAbstractSeries(d, parent)
450 {
455 {
451 }
456 }
452
457
453 /*!
458 /*!
454 Destroys the object. Series added to QChart instances are owned by those,
459 Destroys the object. Series added to QChart instances are owned by those,
455 and are destroyed when QChart instances are destroyed.
460 and are destroyed when QChart instances are destroyed.
456 */
461 */
457 QXYSeries::~QXYSeries()
462 QXYSeries::~QXYSeries()
458 {
463 {
459 }
464 }
460
465
461 /*!
466 /*!
462 Adds data point (\a x, \a y) to the series.
467 Adds data point (\a x, \a y) to the series.
463 */
468 */
464 void QXYSeries::append(qreal x, qreal y)
469 void QXYSeries::append(qreal x, qreal y)
465 {
470 {
466 append(QPointF(x, y));
471 append(QPointF(x, y));
467 }
472 }
468
473
469 /*!
474 /*!
470 This is an overloaded function.
475 This is an overloaded function.
471 Adds data \a point to the series.
476 Adds data \a point to the series.
472 */
477 */
473 void QXYSeries::append(const QPointF &point)
478 void QXYSeries::append(const QPointF &point)
474 {
479 {
475 Q_D(QXYSeries);
480 Q_D(QXYSeries);
476
481
477 if (isValidValue(point)) {
482 if (isValidValue(point)) {
478 d->m_points << point;
483 d->m_points << point;
479 emit pointAdded(d->m_points.count() - 1);
484 emit pointAdded(d->m_points.count() - 1);
480 }
485 }
481 }
486 }
482
487
483 /*!
488 /*!
484 This is an overloaded function.
489 This is an overloaded function.
485 Adds list of data \a points to the series.
490 Adds list of data \a points to the series.
486 */
491 */
487 void QXYSeries::append(const QList<QPointF> &points)
492 void QXYSeries::append(const QList<QPointF> &points)
488 {
493 {
489 foreach (const QPointF &point , points)
494 foreach (const QPointF &point , points)
490 append(point);
495 append(point);
491 }
496 }
492
497
493 /*!
498 /*!
494 Replaces data point (\a oldX, \a oldY) with data point (\a newX, \a newY).
499 Replaces data point (\a oldX, \a oldY) with data point (\a newX, \a newY).
495 \sa pointReplaced()
500 \sa pointReplaced()
496 */
501 */
497 void QXYSeries::replace(qreal oldX, qreal oldY, qreal newX, qreal newY)
502 void QXYSeries::replace(qreal oldX, qreal oldY, qreal newX, qreal newY)
498 {
503 {
499 replace(QPointF(oldX, oldY), QPointF(newX, newY));
504 replace(QPointF(oldX, oldY), QPointF(newX, newY));
500 }
505 }
501
506
502 /*!
507 /*!
503 Replaces \a oldPoint with \a newPoint.
508 Replaces \a oldPoint with \a newPoint.
504 \sa pointReplaced()
509 \sa pointReplaced()
505 */
510 */
506 void QXYSeries::replace(const QPointF &oldPoint, const QPointF &newPoint)
511 void QXYSeries::replace(const QPointF &oldPoint, const QPointF &newPoint)
507 {
512 {
508 Q_D(QXYSeries);
513 Q_D(QXYSeries);
509 int index = d->m_points.indexOf(oldPoint);
514 int index = d->m_points.indexOf(oldPoint);
510 if (index == -1)
515 if (index == -1)
511 return;
516 return;
512 replace(index, newPoint);
517 replace(index, newPoint);
513 }
518 }
514
519
515 /*!
520 /*!
516 Replaces the point at \a index with data point (\a newX, \a newY).
521 Replaces the point at \a index with data point (\a newX, \a newY).
517 \sa pointReplaced()
522 \sa pointReplaced()
518 */
523 */
519 void QXYSeries::replace(int index, qreal newX, qreal newY)
524 void QXYSeries::replace(int index, qreal newX, qreal newY)
520 {
525 {
521 replace(index, QPointF(newX, newY));
526 replace(index, QPointF(newX, newY));
522 }
527 }
523
528
524 /*!
529 /*!
525 Replaces the point at \a index with \a newPoint.
530 Replaces the point at \a index with \a newPoint.
526 \sa pointReplaced()
531 \sa pointReplaced()
527 */
532 */
528 void QXYSeries::replace(int index, const QPointF &newPoint)
533 void QXYSeries::replace(int index, const QPointF &newPoint)
529 {
534 {
530 Q_D(QXYSeries);
535 Q_D(QXYSeries);
531 if (isValidValue(newPoint)) {
536 if (isValidValue(newPoint)) {
532 d->m_points[index] = newPoint;
537 d->m_points[index] = newPoint;
533 emit pointReplaced(index);
538 emit pointReplaced(index);
534 }
539 }
535 }
540 }
536
541
537 /*!
542 /*!
538 Replaces the current points with \a points.
543 Replaces the current points with \a points.
539 \note This is much faster than replacing data points one by one,
544 \note This is much faster than replacing data points one by one,
540 or first clearing all data, and then appending the new data. Emits QXYSeries::pointsReplaced()
545 or first clearing all data, and then appending the new data. Emits QXYSeries::pointsReplaced()
541 when the points have been replaced. However, note that using the overload that takes
546 when the points have been replaced. However, note that using the overload that takes
542 \c{QVector<QPointF>} as parameter is slightly faster than using this overload.
547 \c{QVector<QPointF>} as parameter is faster than using this overload.
543 \sa pointsReplaced()
548 \sa pointsReplaced()
544 */
549 */
545 void QXYSeries::replace(QList<QPointF> points)
550 void QXYSeries::replace(QList<QPointF> points)
546 {
551 {
547 replace(points.toVector());
552 replace(points.toVector());
548 }
553 }
549
554
550 /*!
555 /*!
551 Replaces the current points with \a points.
556 Replaces the current points with \a points.
552 \note This is much faster than replacing data points one by one,
557 \note This is much faster than replacing data points one by one,
553 or first clearing all data, and then appending the new data. Emits QXYSeries::pointsReplaced()
558 or first clearing all data, and then appending the new data. Emits QXYSeries::pointsReplaced()
554 when the points have been replaced.
559 when the points have been replaced.
555 \sa pointsReplaced()
560 \sa pointsReplaced()
556 */
561 */
557 void QXYSeries::replace(QVector<QPointF> points)
562 void QXYSeries::replace(QVector<QPointF> points)
558 {
563 {
559 Q_D(QXYSeries);
564 Q_D(QXYSeries);
560 d->m_points = points;
565 d->m_points = points;
561 emit pointsReplaced();
566 emit pointsReplaced();
562 }
567 }
563
568
564 /*!
569 /*!
565 Removes the point (\a x, \a y) from the series.
570 Removes the point (\a x, \a y) from the series.
566 \sa pointRemoved()
571 \sa pointRemoved()
567 */
572 */
568 void QXYSeries::remove(qreal x, qreal y)
573 void QXYSeries::remove(qreal x, qreal y)
569 {
574 {
570 remove(QPointF(x, y));
575 remove(QPointF(x, y));
571 }
576 }
572
577
573 /*!
578 /*!
574 Removes the \a point from the series.
579 Removes the \a point from the series.
575 \sa pointRemoved()
580 \sa pointRemoved()
576 */
581 */
577 void QXYSeries::remove(const QPointF &point)
582 void QXYSeries::remove(const QPointF &point)
578 {
583 {
579 Q_D(QXYSeries);
584 Q_D(QXYSeries);
580 int index = d->m_points.indexOf(point);
585 int index = d->m_points.indexOf(point);
581 if (index == -1)
586 if (index == -1)
582 return;
587 return;
583 remove(index);
588 remove(index);
584 }
589 }
585
590
586 /*!
591 /*!
587 Removes the point at \a index from the series.
592 Removes the point at \a index from the series.
588 \sa pointRemoved()
593 \sa pointRemoved()
589 */
594 */
590 void QXYSeries::remove(int index)
595 void QXYSeries::remove(int index)
591 {
596 {
592 Q_D(QXYSeries);
597 Q_D(QXYSeries);
593 d->m_points.remove(index);
598 d->m_points.remove(index);
594 emit pointRemoved(index);
599 emit pointRemoved(index);
595 }
600 }
596
601
597 /*!
602 /*!
598 Removes \a count number of points from the series starting at \a index.
603 Removes \a count number of points from the series starting at \a index.
599 \sa pointsRemoved()
604 \sa pointsRemoved()
600 */
605 */
601 void QXYSeries::removePoints(int index, int count)
606 void QXYSeries::removePoints(int index, int count)
602 {
607 {
603 // This function doesn't overload remove as there is chance for it to get mixed up with
608 // This function doesn't overload remove as there is chance for it to get mixed up with
604 // remove(qreal, qreal) overload in some implicit casting cases.
609 // remove(qreal, qreal) overload in some implicit casting cases.
605 Q_D(QXYSeries);
610 Q_D(QXYSeries);
606 if (count > 0) {
611 if (count > 0) {
607 d->m_points.remove(index, count);
612 d->m_points.remove(index, count);
608 emit pointsRemoved(index, count);
613 emit pointsRemoved(index, count);
609 }
614 }
610 }
615 }
611
616
612 /*!
617 /*!
613 Inserts a \a point in the series at \a index position.
618 Inserts a \a point in the series at \a index position.
614 \sa pointAdded()
619 \sa pointAdded()
615 */
620 */
616 void QXYSeries::insert(int index, const QPointF &point)
621 void QXYSeries::insert(int index, const QPointF &point)
617 {
622 {
618 Q_D(QXYSeries);
623 Q_D(QXYSeries);
619 if (isValidValue(point)) {
624 if (isValidValue(point)) {
620 index = qMax(0, qMin(index, d->m_points.size()));
625 index = qMax(0, qMin(index, d->m_points.size()));
621 d->m_points.insert(index, point);
626 d->m_points.insert(index, point);
622 emit pointAdded(index);
627 emit pointAdded(index);
623 }
628 }
624 }
629 }
625
630
626 /*!
631 /*!
627 Removes all points from the series.
632 Removes all points from the series.
628 \sa pointsRemoved()
633 \sa pointsRemoved()
629 */
634 */
630 void QXYSeries::clear()
635 void QXYSeries::clear()
631 {
636 {
632 Q_D(QXYSeries);
637 Q_D(QXYSeries);
633 removePoints(0, d->m_points.size());
638 removePoints(0, d->m_points.size());
634 }
639 }
635
640
636 /*!
641 /*!
637 Returns list of points in the series.
642 Returns the points in the series as a list.
643 Use QXYSeries::pointsVector() for better performance.
638 */
644 */
639 QList<QPointF> QXYSeries::points() const
645 QList<QPointF> QXYSeries::points() const
640 {
646 {
641 Q_D(const QXYSeries);
647 Q_D(const QXYSeries);
642 return d->m_points.toList();
648 return d->m_points.toList();
643 }
649 }
644
650
645 /*!
651 /*!
652 Returns the points in the series as a vector.
653 This is more efficient that calling QXYSeries::points();
654 */
655 QVector<QPointF> QXYSeries::pointsVector() const
656 {
657 Q_D(const QXYSeries);
658 return d->m_points;
659 }
660
661 /*!
646 Returns point at \a index in internal points vector.
662 Returns point at \a index in internal points vector.
647 */
663 */
648 const QPointF &QXYSeries::at(int index) const
664 const QPointF &QXYSeries::at(int index) const
649 {
665 {
650 Q_D(const QXYSeries);
666 Q_D(const QXYSeries);
651 return d->m_points.at(index);
667 return d->m_points.at(index);
652 }
668 }
653
669
654 /*!
670 /*!
655 Returns number of data points within series.
671 Returns number of data points within series.
656 */
672 */
657 int QXYSeries::count() const
673 int QXYSeries::count() const
658 {
674 {
659 Q_D(const QXYSeries);
675 Q_D(const QXYSeries);
660 return d->m_points.count();
676 return d->m_points.count();
661 }
677 }
662
678
663
679
664 /*!
680 /*!
665 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
681 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
666 pen from chart theme is used.
682 pen from chart theme is used.
667 \sa QChart::setTheme()
683 \sa QChart::setTheme()
668 */
684 */
669 void QXYSeries::setPen(const QPen &pen)
685 void QXYSeries::setPen(const QPen &pen)
670 {
686 {
671 Q_D(QXYSeries);
687 Q_D(QXYSeries);
672 if (d->m_pen != pen) {
688 if (d->m_pen != pen) {
673 bool emitColorChanged = d->m_pen.color() != pen.color();
689 bool emitColorChanged = d->m_pen.color() != pen.color();
674 d->m_pen = pen;
690 d->m_pen = pen;
675 emit d->updated();
691 emit d->updated();
676 if (emitColorChanged)
692 if (emitColorChanged)
677 emit colorChanged(pen.color());
693 emit colorChanged(pen.color());
694 emit penChanged(pen);
678 }
695 }
679 }
696 }
680
697
681 QPen QXYSeries::pen() const
698 QPen QXYSeries::pen() const
682 {
699 {
683 Q_D(const QXYSeries);
700 Q_D(const QXYSeries);
684 if (d->m_pen == QChartPrivate::defaultPen())
701 if (d->m_pen == QChartPrivate::defaultPen())
685 return QPen();
702 return QPen();
686 else
703 else
687 return d->m_pen;
704 return d->m_pen;
688 }
705 }
689
706
690 /*!
707 /*!
691 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
708 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
692 from chart theme setting is used.
709 from chart theme setting is used.
693 \sa QChart::setTheme()
710 \sa QChart::setTheme()
694 */
711 */
695 void QXYSeries::setBrush(const QBrush &brush)
712 void QXYSeries::setBrush(const QBrush &brush)
696 {
713 {
697 Q_D(QXYSeries);
714 Q_D(QXYSeries);
698 if (d->m_brush != brush) {
715 if (d->m_brush != brush) {
699 d->m_brush = brush;
716 d->m_brush = brush;
700 emit d->updated();
717 emit d->updated();
701 }
718 }
702 }
719 }
703
720
704 QBrush QXYSeries::brush() const
721 QBrush QXYSeries::brush() const
705 {
722 {
706 Q_D(const QXYSeries);
723 Q_D(const QXYSeries);
707 if (d->m_brush == QChartPrivate::defaultBrush())
724 if (d->m_brush == QChartPrivate::defaultBrush())
708 return QBrush();
725 return QBrush();
709 else
726 else
710 return d->m_brush;
727 return d->m_brush;
711 }
728 }
712
729
713 void QXYSeries::setColor(const QColor &color)
730 void QXYSeries::setColor(const QColor &color)
714 {
731 {
715 QPen p = pen();
732 QPen p = pen();
716 if (p.color() != color) {
733 if (p.color() != color) {
717 p.setColor(color);
734 p.setColor(color);
718 setPen(p);
735 setPen(p);
719 }
736 }
720 }
737 }
721
738
722 QColor QXYSeries::color() const
739 QColor QXYSeries::color() const
723 {
740 {
724 return pen().color();
741 return pen().color();
725 }
742 }
726
743
727 void QXYSeries::setPointsVisible(bool visible)
744 void QXYSeries::setPointsVisible(bool visible)
728 {
745 {
729 Q_D(QXYSeries);
746 Q_D(QXYSeries);
730 if (d->m_pointsVisible != visible) {
747 if (d->m_pointsVisible != visible) {
731 d->m_pointsVisible = visible;
748 d->m_pointsVisible = visible;
732 emit d->updated();
749 emit d->updated();
733 }
750 }
734 }
751 }
735
752
736 bool QXYSeries::pointsVisible() const
753 bool QXYSeries::pointsVisible() const
737 {
754 {
738 Q_D(const QXYSeries);
755 Q_D(const QXYSeries);
739 return d->m_pointsVisible;
756 return d->m_pointsVisible;
740 }
757 }
741
758
742 void QXYSeries::setPointLabelsFormat(const QString &format)
759 void QXYSeries::setPointLabelsFormat(const QString &format)
743 {
760 {
744 Q_D(QXYSeries);
761 Q_D(QXYSeries);
745 if (d->m_pointLabelsFormat != format) {
762 if (d->m_pointLabelsFormat != format) {
746 d->m_pointLabelsFormat = format;
763 d->m_pointLabelsFormat = format;
747 emit pointLabelsFormatChanged(format);
764 emit pointLabelsFormatChanged(format);
748 }
765 }
749 }
766 }
750
767
751 QString QXYSeries::pointLabelsFormat() const
768 QString QXYSeries::pointLabelsFormat() const
752 {
769 {
753 Q_D(const QXYSeries);
770 Q_D(const QXYSeries);
754 return d->m_pointLabelsFormat;
771 return d->m_pointLabelsFormat;
755 }
772 }
756
773
757 void QXYSeries::setPointLabelsVisible(bool visible)
774 void QXYSeries::setPointLabelsVisible(bool visible)
758 {
775 {
759 Q_D(QXYSeries);
776 Q_D(QXYSeries);
760 if (d->m_pointLabelsVisible != visible) {
777 if (d->m_pointLabelsVisible != visible) {
761 d->m_pointLabelsVisible = visible;
778 d->m_pointLabelsVisible = visible;
762 emit pointLabelsVisibilityChanged(visible);
779 emit pointLabelsVisibilityChanged(visible);
763 }
780 }
764 }
781 }
765
782
766 bool QXYSeries::pointLabelsVisible() const
783 bool QXYSeries::pointLabelsVisible() const
767 {
784 {
768 Q_D(const QXYSeries);
785 Q_D(const QXYSeries);
769 return d->m_pointLabelsVisible;
786 return d->m_pointLabelsVisible;
770 }
787 }
771
788
772 void QXYSeries::setPointLabelsFont(const QFont &font)
789 void QXYSeries::setPointLabelsFont(const QFont &font)
773 {
790 {
774 Q_D(QXYSeries);
791 Q_D(QXYSeries);
775 if (d->m_pointLabelsFont != font) {
792 if (d->m_pointLabelsFont != font) {
776 d->m_pointLabelsFont = font;
793 d->m_pointLabelsFont = font;
777 emit pointLabelsFontChanged(font);
794 emit pointLabelsFontChanged(font);
778 }
795 }
779 }
796 }
780
797
781 QFont QXYSeries::pointLabelsFont() const
798 QFont QXYSeries::pointLabelsFont() const
782 {
799 {
783 Q_D(const QXYSeries);
800 Q_D(const QXYSeries);
784 return d->m_pointLabelsFont;
801 return d->m_pointLabelsFont;
785 }
802 }
786
803
787 void QXYSeries::setPointLabelsColor(const QColor &color)
804 void QXYSeries::setPointLabelsColor(const QColor &color)
788 {
805 {
789 Q_D(QXYSeries);
806 Q_D(QXYSeries);
790 if (d->m_pointLabelsColor != color) {
807 if (d->m_pointLabelsColor != color) {
791 d->m_pointLabelsColor = color;
808 d->m_pointLabelsColor = color;
792 emit pointLabelsColorChanged(color);
809 emit pointLabelsColorChanged(color);
793 }
810 }
794 }
811 }
795
812
796 QColor QXYSeries::pointLabelsColor() const
813 QColor QXYSeries::pointLabelsColor() const
797 {
814 {
798 Q_D(const QXYSeries);
815 Q_D(const QXYSeries);
799 if (d->m_pointLabelsColor == QChartPrivate::defaultPen().color())
816 if (d->m_pointLabelsColor == QChartPrivate::defaultPen().color())
800 return QPen().color();
817 return QPen().color();
801 else
818 else
802 return d->m_pointLabelsColor;
819 return d->m_pointLabelsColor;
803 }
820 }
804
821
805 void QXYSeries::setPointLabelsClipping(bool enabled)
822 void QXYSeries::setPointLabelsClipping(bool enabled)
806 {
823 {
807 Q_D(QXYSeries);
824 Q_D(QXYSeries);
808 if (d->m_pointLabelsClipping != enabled) {
825 if (d->m_pointLabelsClipping != enabled) {
809 d->m_pointLabelsClipping = enabled;
826 d->m_pointLabelsClipping = enabled;
810 emit pointLabelsClippingChanged(enabled);
827 emit pointLabelsClippingChanged(enabled);
811 }
828 }
812 }
829 }
813
830
814 bool QXYSeries::pointLabelsClipping() const
831 bool QXYSeries::pointLabelsClipping() const
815 {
832 {
816 Q_D(const QXYSeries);
833 Q_D(const QXYSeries);
817 return d->m_pointLabelsClipping;
834 return d->m_pointLabelsClipping;
818 }
835 }
819
836
820 /*!
837 /*!
821 Stream operator for adding a data \a point to the series.
838 Stream operator for adding a data \a point to the series.
822 \sa append()
839 \sa append()
823 */
840 */
824 QXYSeries &QXYSeries::operator<< (const QPointF &point)
841 QXYSeries &QXYSeries::operator<< (const QPointF &point)
825 {
842 {
826 append(point);
843 append(point);
827 return *this;
844 return *this;
828 }
845 }
829
846
830
847
831 /*!
848 /*!
832 Stream operator for adding a list of \a points to the series.
849 Stream operator for adding a list of \a points to the series.
833 \sa append()
850 \sa append()
834 */
851 */
835
852
836 QXYSeries &QXYSeries::operator<< (const QList<QPointF>& points)
853 QXYSeries &QXYSeries::operator<< (const QList<QPointF>& points)
837 {
854 {
838 append(points);
855 append(points);
839 return *this;
856 return *this;
840 }
857 }
841
858
842 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
859 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
843
860
844
861
845 QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q)
862 QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q)
846 : QAbstractSeriesPrivate(q),
863 : QAbstractSeriesPrivate(q),
847 m_pen(QChartPrivate::defaultPen()),
864 m_pen(QChartPrivate::defaultPen()),
848 m_brush(QChartPrivate::defaultBrush()),
865 m_brush(QChartPrivate::defaultBrush()),
849 m_pointsVisible(false),
866 m_pointsVisible(false),
850 m_pointLabelsFormat(QLatin1String("@xPoint, @yPoint")),
867 m_pointLabelsFormat(QLatin1String("@xPoint, @yPoint")),
851 m_pointLabelsVisible(false),
868 m_pointLabelsVisible(false),
852 m_pointLabelsFont(QChartPrivate::defaultFont()),
869 m_pointLabelsFont(QChartPrivate::defaultFont()),
853 m_pointLabelsColor(QChartPrivate::defaultPen().color()),
870 m_pointLabelsColor(QChartPrivate::defaultPen().color()),
854 m_pointLabelsClipping(true)
871 m_pointLabelsClipping(true)
855 {
872 {
856 }
873 }
857
874
858 void QXYSeriesPrivate::initializeDomain()
875 void QXYSeriesPrivate::initializeDomain()
859 {
876 {
860 qreal minX(0);
877 qreal minX(0);
861 qreal minY(0);
878 qreal minY(0);
862 qreal maxX(1);
879 qreal maxX(1);
863 qreal maxY(1);
880 qreal maxY(1);
864
881
865 Q_Q(QXYSeries);
882 Q_Q(QXYSeries);
866
883
867 const QList<QPointF>& points = q->points();
884 const QVector<QPointF> &points = q->pointsVector();
868
885
869 if (!points.isEmpty()) {
886 if (!points.isEmpty()) {
870 minX = points[0].x();
887 minX = points[0].x();
871 minY = points[0].y();
888 minY = points[0].y();
872 maxX = minX;
889 maxX = minX;
873 maxY = minY;
890 maxY = minY;
874
891
875 for (int i = 0; i < points.count(); i++) {
892 for (int i = 0; i < points.count(); i++) {
876 qreal x = points[i].x();
893 qreal x = points[i].x();
877 qreal y = points[i].y();
894 qreal y = points[i].y();
878 minX = qMin(minX, x);
895 minX = qMin(minX, x);
879 minY = qMin(minY, y);
896 minY = qMin(minY, y);
880 maxX = qMax(maxX, x);
897 maxX = qMax(maxX, x);
881 maxY = qMax(maxY, y);
898 maxY = qMax(maxY, y);
882 }
899 }
883 }
900 }
884
901
885 domain()->setRange(minX, maxX, minY, maxY);
902 domain()->setRange(minX, maxX, minY, maxY);
886 }
903 }
887
904
888 QList<QLegendMarker*> QXYSeriesPrivate::createLegendMarkers(QLegend* legend)
905 QList<QLegendMarker*> QXYSeriesPrivate::createLegendMarkers(QLegend* legend)
889 {
906 {
890 Q_Q(QXYSeries);
907 Q_Q(QXYSeries);
891 QList<QLegendMarker*> list;
908 QList<QLegendMarker*> list;
892 return list << new QXYLegendMarker(q,legend);
909 return list << new QXYLegendMarker(q,legend);
893 }
910 }
894
911
895 void QXYSeriesPrivate::initializeAxes()
912 void QXYSeriesPrivate::initializeAxes()
896 {
913 {
897
914
898 }
915 }
899
916
900 QAbstractAxis::AxisType QXYSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
917 QAbstractAxis::AxisType QXYSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
901 {
918 {
902 Q_UNUSED(orientation);
919 Q_UNUSED(orientation);
903 return QAbstractAxis::AxisTypeValue;
920 return QAbstractAxis::AxisTypeValue;
904 }
921 }
905
922
906 QAbstractAxis* QXYSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
923 QAbstractAxis* QXYSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
907 {
924 {
908 Q_UNUSED(orientation);
925 Q_UNUSED(orientation);
909 return new QValueAxis;
926 return new QValueAxis;
910 }
927 }
911
928
912 void QXYSeriesPrivate::initializeAnimations(QtCharts::QChart::AnimationOptions options,
929 void QXYSeriesPrivate::initializeAnimations(QtCharts::QChart::AnimationOptions options,
913 int duration, QEasingCurve &curve)
930 int duration, QEasingCurve &curve)
914 {
931 {
915 XYChart *item = static_cast<XYChart *>(m_item.data());
932 XYChart *item = static_cast<XYChart *>(m_item.data());
916 Q_ASSERT(item);
933 Q_ASSERT(item);
917 if (item->animation())
934 if (item->animation())
918 item->animation()->stopAndDestroyLater();
935 item->animation()->stopAndDestroyLater();
919
936
920 if (options.testFlag(QChart::SeriesAnimations))
937 if (options.testFlag(QChart::SeriesAnimations))
921 item->setAnimation(new XYAnimation(item, duration, curve));
938 item->setAnimation(new XYAnimation(item, duration, curve));
922 else
939 else
923 item->setAnimation(0);
940 item->setAnimation(0);
924 QAbstractSeriesPrivate::initializeAnimations(options, duration, curve);
941 QAbstractSeriesPrivate::initializeAnimations(options, duration, curve);
925 }
942 }
926
943
927 void QXYSeriesPrivate::drawSeriesPointLabels(QPainter *painter, const QVector<QPointF> &points,
944 void QXYSeriesPrivate::drawSeriesPointLabels(QPainter *painter, const QVector<QPointF> &points,
928 const int offset)
945 const int offset)
929 {
946 {
930 static const QString xPointTag(QLatin1String("@xPoint"));
947 static const QString xPointTag(QLatin1String("@xPoint"));
931 static const QString yPointTag(QLatin1String("@yPoint"));
948 static const QString yPointTag(QLatin1String("@yPoint"));
932 const int labelOffset = offset + 2;
949 const int labelOffset = offset + 2;
933
950
934 painter->setFont(m_pointLabelsFont);
951 painter->setFont(m_pointLabelsFont);
935 painter->setPen(QPen(m_pointLabelsColor));
952 painter->setPen(QPen(m_pointLabelsColor));
936 QFontMetrics fm(painter->font());
953 QFontMetrics fm(painter->font());
937 // m_points is used for the label here as it has the series point information
954 // m_points is used for the label here as it has the series point information
938 // points variable passed is used for positioning because it has the coordinates
955 // points variable passed is used for positioning because it has the coordinates
939 for (int i(0); i < m_points.size(); i++) {
956 for (int i(0); i < m_points.size(); i++) {
940 QString pointLabel = m_pointLabelsFormat;
957 QString pointLabel = m_pointLabelsFormat;
941 pointLabel.replace(xPointTag, presenter()->numberToString(m_points.at(i).x()));
958 pointLabel.replace(xPointTag, presenter()->numberToString(m_points.at(i).x()));
942 pointLabel.replace(yPointTag, presenter()->numberToString(m_points.at(i).y()));
959 pointLabel.replace(yPointTag, presenter()->numberToString(m_points.at(i).y()));
943
960
944 // Position text in relation to the point
961 // Position text in relation to the point
945 int pointLabelWidth = fm.width(pointLabel);
962 int pointLabelWidth = fm.width(pointLabel);
946 QPointF position(points.at(i));
963 QPointF position(points.at(i));
947 if (!reverseXAxis())
964 if (!reverseXAxis())
948 position.setX(position.x() - pointLabelWidth / 2);
965 position.setX(position.x() - pointLabelWidth / 2);
949 else
966 else
950 position.setX(domain()->size().width() - position.x() - pointLabelWidth / 2);
967 position.setX(domain()->size().width() - position.x() - pointLabelWidth / 2);
951 if (!reverseYAxis())
968 if (!reverseYAxis())
952 position.setY(position.y() - labelOffset);
969 position.setY(position.y() - labelOffset);
953 else
970 else
954 position.setY(domain()->size().height() - position.y() - labelOffset);
971 position.setY(domain()->size().height() - position.y() - labelOffset);
955
972
956 painter->drawText(position, pointLabel);
973 painter->drawText(position, pointLabel);
957 }
974 }
958 }
975 }
959
976
960 #include "moc_qxyseries.cpp"
977 #include "moc_qxyseries.cpp"
961 #include "moc_qxyseries_p.cpp"
978 #include "moc_qxyseries_p.cpp"
962
979
963 QT_CHARTS_END_NAMESPACE
980 QT_CHARTS_END_NAMESPACE
@@ -1,131 +1,133
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #ifndef QXYSERIES_H
19 #ifndef QXYSERIES_H
20 #define QXYSERIES_H
20 #define QXYSERIES_H
21
21
22 #include <QtCharts/QChartGlobal>
22 #include <QtCharts/QChartGlobal>
23 #include <QtCharts/QAbstractSeries>
23 #include <QtCharts/QAbstractSeries>
24 #include <QtGui/QPen>
24 #include <QtGui/QPen>
25 #include <QtGui/QBrush>
25 #include <QtGui/QBrush>
26
26
27 QT_BEGIN_NAMESPACE
27 QT_BEGIN_NAMESPACE
28 class QModelIndex;
28 class QModelIndex;
29 QT_END_NAMESPACE
29 QT_END_NAMESPACE
30
30
31 QT_CHARTS_BEGIN_NAMESPACE
31 QT_CHARTS_BEGIN_NAMESPACE
32
32
33 class QXYSeriesPrivate;
33 class QXYSeriesPrivate;
34 class QXYModelMapper;
34 class QXYModelMapper;
35
35
36 class QT_CHARTS_EXPORT QXYSeries : public QAbstractSeries
36 class QT_CHARTS_EXPORT QXYSeries : public QAbstractSeries
37 {
37 {
38 Q_OBJECT
38 Q_OBJECT
39 Q_PROPERTY(bool pointsVisible READ pointsVisible WRITE setPointsVisible)
39 Q_PROPERTY(bool pointsVisible READ pointsVisible WRITE setPointsVisible)
40 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
40 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
41 Q_PROPERTY(QString pointLabelsFormat READ pointLabelsFormat WRITE setPointLabelsFormat NOTIFY pointLabelsFormatChanged)
41 Q_PROPERTY(QString pointLabelsFormat READ pointLabelsFormat WRITE setPointLabelsFormat NOTIFY pointLabelsFormatChanged)
42 Q_PROPERTY(bool pointLabelsVisible READ pointLabelsVisible WRITE setPointLabelsVisible NOTIFY pointLabelsVisibilityChanged)
42 Q_PROPERTY(bool pointLabelsVisible READ pointLabelsVisible WRITE setPointLabelsVisible NOTIFY pointLabelsVisibilityChanged)
43 Q_PROPERTY(QFont pointLabelsFont READ pointLabelsFont WRITE setPointLabelsFont NOTIFY pointLabelsFontChanged)
43 Q_PROPERTY(QFont pointLabelsFont READ pointLabelsFont WRITE setPointLabelsFont NOTIFY pointLabelsFontChanged)
44 Q_PROPERTY(QColor pointLabelsColor READ pointLabelsColor WRITE setPointLabelsColor NOTIFY pointLabelsColorChanged)
44 Q_PROPERTY(QColor pointLabelsColor READ pointLabelsColor WRITE setPointLabelsColor NOTIFY pointLabelsColorChanged)
45 Q_PROPERTY(bool pointLabelsClipping READ pointLabelsClipping WRITE setPointLabelsClipping NOTIFY pointLabelsClippingChanged)
45 Q_PROPERTY(bool pointLabelsClipping READ pointLabelsClipping WRITE setPointLabelsClipping NOTIFY pointLabelsClippingChanged)
46
46
47 protected:
47 protected:
48 explicit QXYSeries(QXYSeriesPrivate &d, QObject *parent = 0);
48 explicit QXYSeries(QXYSeriesPrivate &d, QObject *parent = 0);
49
49
50 public:
50 public:
51 ~QXYSeries();
51 ~QXYSeries();
52 void append(qreal x, qreal y);
52 void append(qreal x, qreal y);
53 void append(const QPointF &point);
53 void append(const QPointF &point);
54 void append(const QList<QPointF> &points);
54 void append(const QList<QPointF> &points);
55 void replace(qreal oldX, qreal oldY, qreal newX, qreal newY);
55 void replace(qreal oldX, qreal oldY, qreal newX, qreal newY);
56 void replace(const QPointF &oldPoint, const QPointF &newPoint);
56 void replace(const QPointF &oldPoint, const QPointF &newPoint);
57 void replace(int index, qreal newX, qreal newY);
57 void replace(int index, qreal newX, qreal newY);
58 void replace(int index, const QPointF &newPoint);
58 void replace(int index, const QPointF &newPoint);
59 void remove(qreal x, qreal y);
59 void remove(qreal x, qreal y);
60 void remove(const QPointF &point);
60 void remove(const QPointF &point);
61 void remove(int index);
61 void remove(int index);
62 void removePoints(int index, int count);
62 void removePoints(int index, int count);
63 void insert(int index, const QPointF &point);
63 void insert(int index, const QPointF &point);
64 void clear();
64 void clear();
65
65
66 int count() const;
66 int count() const;
67 QList<QPointF> points() const;
67 QList<QPointF> points() const;
68 QVector<QPointF> pointsVector() const;
68 const QPointF &at(int index) const;
69 const QPointF &at(int index) const;
69
70
70 QXYSeries &operator << (const QPointF &point);
71 QXYSeries &operator << (const QPointF &point);
71 QXYSeries &operator << (const QList<QPointF> &points);
72 QXYSeries &operator << (const QList<QPointF> &points);
72
73
73 virtual void setPen(const QPen &pen);
74 virtual void setPen(const QPen &pen);
74 QPen pen() const;
75 QPen pen() const;
75
76
76 virtual void setBrush(const QBrush &brush);
77 virtual void setBrush(const QBrush &brush);
77 QBrush brush() const;
78 QBrush brush() const;
78
79
79 virtual void setColor(const QColor &color);
80 virtual void setColor(const QColor &color);
80 virtual QColor color() const;
81 virtual QColor color() const;
81
82
82 void setPointsVisible(bool visible = true);
83 void setPointsVisible(bool visible = true);
83 bool pointsVisible() const;
84 bool pointsVisible() const;
84
85
85 void setPointLabelsFormat(const QString &format);
86 void setPointLabelsFormat(const QString &format);
86 QString pointLabelsFormat() const;
87 QString pointLabelsFormat() const;
87
88
88 void setPointLabelsVisible(bool visible = true);
89 void setPointLabelsVisible(bool visible = true);
89 bool pointLabelsVisible() const;
90 bool pointLabelsVisible() const;
90
91
91 void setPointLabelsFont(const QFont &font);
92 void setPointLabelsFont(const QFont &font);
92 QFont pointLabelsFont() const;
93 QFont pointLabelsFont() const;
93
94
94 void setPointLabelsColor(const QColor &color);
95 void setPointLabelsColor(const QColor &color);
95 QColor pointLabelsColor() const;
96 QColor pointLabelsColor() const;
96
97
97 void setPointLabelsClipping(bool enabled = true);
98 void setPointLabelsClipping(bool enabled = true);
98 bool pointLabelsClipping() const;
99 bool pointLabelsClipping() const;
99
100
100 void replace(QList<QPointF> points);
101 void replace(QList<QPointF> points);
101 void replace(QVector<QPointF> points);
102 void replace(QVector<QPointF> points);
102
103
103 Q_SIGNALS:
104 Q_SIGNALS:
104 void clicked(const QPointF &point);
105 void clicked(const QPointF &point);
105 void hovered(const QPointF &point, bool state);
106 void hovered(const QPointF &point, bool state);
106 void pressed(const QPointF &point);
107 void pressed(const QPointF &point);
107 void released(const QPointF &point);
108 void released(const QPointF &point);
108 void doubleClicked(const QPointF &point);
109 void doubleClicked(const QPointF &point);
109 void pointReplaced(int index);
110 void pointReplaced(int index);
110 void pointRemoved(int index);
111 void pointRemoved(int index);
111 void pointAdded(int index);
112 void pointAdded(int index);
112 void colorChanged(QColor color);
113 void colorChanged(QColor color);
113 void pointsReplaced();
114 void pointsReplaced();
114 void pointLabelsFormatChanged(const QString &format);
115 void pointLabelsFormatChanged(const QString &format);
115 void pointLabelsVisibilityChanged(bool visible);
116 void pointLabelsVisibilityChanged(bool visible);
116 void pointLabelsFontChanged(const QFont &font);
117 void pointLabelsFontChanged(const QFont &font);
117 void pointLabelsColorChanged(const QColor &color);
118 void pointLabelsColorChanged(const QColor &color);
118 void pointLabelsClippingChanged(bool clipping);
119 void pointLabelsClippingChanged(bool clipping);
119 void pointsRemoved(int index, int count);
120 void pointsRemoved(int index, int count);
121 void penChanged(const QPen &pen);
120
122
121 private:
123 private:
122 Q_DECLARE_PRIVATE(QXYSeries)
124 Q_DECLARE_PRIVATE(QXYSeries)
123 Q_DISABLE_COPY(QXYSeries)
125 Q_DISABLE_COPY(QXYSeries)
124 friend class QXYLegendMarkerPrivate;
126 friend class QXYLegendMarkerPrivate;
125 friend class XYLegendMarker;
127 friend class XYLegendMarker;
126 friend class XYChart;
128 friend class XYChart;
127 };
129 };
128
130
129 QT_CHARTS_END_NAMESPACE
131 QT_CHARTS_END_NAMESPACE
130
132
131 #endif // QXYSERIES_H
133 #endif // QXYSERIES_H
@@ -1,208 +1,235
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include <private/xychart_p.h>
19 #include <private/xychart_p.h>
20 #include <QtCharts/QXYSeries>
20 #include <QtCharts/QXYSeries>
21 #include <private/qxyseries_p.h>
21 #include <private/qxyseries_p.h>
22 #include <private/chartpresenter_p.h>
22 #include <private/chartpresenter_p.h>
23 #include <private/abstractdomain_p.h>
23 #include <private/abstractdomain_p.h>
24 #include <private/chartdataset_p.h>
25 #include <private/glxyseriesdata_p.h>
24 #include <QtCharts/QXYModelMapper>
26 #include <QtCharts/QXYModelMapper>
25 #include <private/qabstractaxis_p.h>
27 #include <private/qabstractaxis_p.h>
26 #include <QtGui/QPainter>
28 #include <QtGui/QPainter>
27 #include <QtCore/QAbstractItemModel>
29 #include <QtCore/QAbstractItemModel>
28
30
29
31
30 QT_CHARTS_BEGIN_NAMESPACE
32 QT_CHARTS_BEGIN_NAMESPACE
31
33
32 XYChart::XYChart(QXYSeries *series, QGraphicsItem *item):
34 XYChart::XYChart(QXYSeries *series, QGraphicsItem *item):
33 ChartItem(series->d_func(),item),
35 ChartItem(series->d_func(),item),
34 m_series(series),
36 m_series(series),
35 m_animation(0),
37 m_animation(0),
36 m_dirty(true)
38 m_dirty(true)
37 {
39 {
38 QObject::connect(series, SIGNAL(pointReplaced(int)), this, SLOT(handlePointReplaced(int)));
40 QObject::connect(series, SIGNAL(pointReplaced(int)), this, SLOT(handlePointReplaced(int)));
39 QObject::connect(series, SIGNAL(pointsReplaced()), this, SLOT(handlePointsReplaced()));
41 QObject::connect(series, SIGNAL(pointsReplaced()), this, SLOT(handlePointsReplaced()));
40 QObject::connect(series, SIGNAL(pointAdded(int)), this, SLOT(handlePointAdded(int)));
42 QObject::connect(series, SIGNAL(pointAdded(int)), this, SLOT(handlePointAdded(int)));
41 QObject::connect(series, SIGNAL(pointRemoved(int)), this, SLOT(handlePointRemoved(int)));
43 QObject::connect(series, SIGNAL(pointRemoved(int)), this, SLOT(handlePointRemoved(int)));
42 QObject::connect(series, SIGNAL(pointsRemoved(int, int)), this, SLOT(handlePointsRemoved(int, int)));
44 QObject::connect(series, SIGNAL(pointsRemoved(int, int)), this, SLOT(handlePointsRemoved(int, int)));
43 QObject::connect(this, SIGNAL(clicked(QPointF)), series, SIGNAL(clicked(QPointF)));
45 QObject::connect(this, SIGNAL(clicked(QPointF)), series, SIGNAL(clicked(QPointF)));
44 QObject::connect(this, SIGNAL(hovered(QPointF,bool)), series, SIGNAL(hovered(QPointF,bool)));
46 QObject::connect(this, SIGNAL(hovered(QPointF,bool)), series, SIGNAL(hovered(QPointF,bool)));
45 QObject::connect(this, SIGNAL(pressed(QPointF)), series, SIGNAL(pressed(QPointF)));
47 QObject::connect(this, SIGNAL(pressed(QPointF)), series, SIGNAL(pressed(QPointF)));
46 QObject::connect(this, SIGNAL(released(QPointF)), series, SIGNAL(released(QPointF)));
48 QObject::connect(this, SIGNAL(released(QPointF)), series, SIGNAL(released(QPointF)));
47 QObject::connect(this, SIGNAL(doubleClicked(QPointF)), series, SIGNAL(doubleClicked(QPointF)));
49 QObject::connect(this, SIGNAL(doubleClicked(QPointF)), series, SIGNAL(doubleClicked(QPointF)));
48 }
50 }
49
51
50 void XYChart::setGeometryPoints(const QVector<QPointF> &points)
52 void XYChart::setGeometryPoints(const QVector<QPointF> &points)
51 {
53 {
52 m_points = points;
54 m_points = points;
53 }
55 }
54
56
55 void XYChart::setAnimation(XYAnimation *animation)
57 void XYChart::setAnimation(XYAnimation *animation)
56 {
58 {
57 m_animation = animation;
59 m_animation = animation;
58 }
60 }
59
61
60 void XYChart::setDirty(bool dirty)
62 void XYChart::setDirty(bool dirty)
61 {
63 {
62 m_dirty = dirty;
64 m_dirty = dirty;
63 }
65 }
64
66
65 // Returns a vector with same size as geometryPoints vector, indicating
67 // Returns a vector with same size as geometryPoints vector, indicating
66 // the off grid status of points.
68 // the off grid status of points.
67 QVector<bool> XYChart::offGridStatusVector()
69 QVector<bool> XYChart::offGridStatusVector()
68 {
70 {
69 qreal minX = domain()->minX();
71 qreal minX = domain()->minX();
70 qreal maxX = domain()->maxX();
72 qreal maxX = domain()->maxX();
71 qreal minY = domain()->minY();
73 qreal minY = domain()->minY();
72 qreal maxY = domain()->maxY();
74 qreal maxY = domain()->maxY();
73
75
74 QVector<bool> returnVector;
76 QVector<bool> returnVector;
75 returnVector.resize(m_points.size());
77 returnVector.resize(m_points.size());
76 // During remove animation series may have different number of points,
78 // During remove animation series may have different number of points,
77 // so ensure we don't go over the index. No need to check for zero points, this
79 // so ensure we don't go over the index. No need to check for zero points, this
78 // will not be called in such a situation.
80 // will not be called in such a situation.
79 const int seriesLastIndex = m_series->count() - 1;
81 const int seriesLastIndex = m_series->count() - 1;
80
82
81 for (int i = 0; i < m_points.size(); i++) {
83 for (int i = 0; i < m_points.size(); i++) {
82 const QPointF &seriesPoint = m_series->at(qMin(seriesLastIndex, i));
84 const QPointF &seriesPoint = m_series->at(qMin(seriesLastIndex, i));
83 if (seriesPoint.x() < minX
85 if (seriesPoint.x() < minX
84 || seriesPoint.x() > maxX
86 || seriesPoint.x() > maxX
85 || seriesPoint.y() < minY
87 || seriesPoint.y() < minY
86 || seriesPoint.y() > maxY) {
88 || seriesPoint.y() > maxY) {
87 returnVector[i] = true;
89 returnVector[i] = true;
88 } else {
90 } else {
89 returnVector[i] = false;
91 returnVector[i] = false;
90 }
92 }
91 }
93 }
92 return returnVector;
94 return returnVector;
93 }
95 }
94
96
95 void XYChart::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
97 void XYChart::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
96 {
98 {
97
99
98 if (m_animation) {
100 if (m_animation) {
99 m_animation->setup(oldPoints, newPoints, index);
101 m_animation->setup(oldPoints, newPoints, index);
100 m_points = newPoints;
102 m_points = newPoints;
101 setDirty(false);
103 setDirty(false);
102 presenter()->startAnimation(m_animation);
104 presenter()->startAnimation(m_animation);
103 } else {
105 } else {
104 m_points = newPoints;
106 m_points = newPoints;
105 updateGeometry();
107 updateGeometry();
106 }
108 }
107 }
109 }
108
110
111 void XYChart::updateGlChart()
112 {
113 presenter()->ensureGLWidget();
114 dataSet()->glXYSeriesDataManager()->setPoints(m_series, domain());
115 updateGeometry();
116 }
117
109 //handlers
118 //handlers
110
119
111 void XYChart::handlePointAdded(int index)
120 void XYChart::handlePointAdded(int index)
112 {
121 {
113 Q_ASSERT(index < m_series->count());
122 Q_ASSERT(index < m_series->count());
114 Q_ASSERT(index >= 0);
123 Q_ASSERT(index >= 0);
115
124
116 QVector<QPointF> points;
125 if (m_series->useOpenGL()) {
117
126 updateGlChart();
118 if (m_dirty || m_points.isEmpty()) {
119 points = domain()->calculateGeometryPoints(m_series->points());
120 } else {
127 } else {
121 points = m_points;
128 QVector<QPointF> points;
122 QPointF point = domain()->calculateGeometryPoint(m_series->points()[index], m_validData);
129 if (m_dirty || m_points.isEmpty()) {
123 if (!m_validData)
130 points = domain()->calculateGeometryPoints(m_series->pointsVector());
124 m_points.clear();
131 } else {
125 else
132 points = m_points;
126 points.insert(index, point);
133 QPointF point = domain()->calculateGeometryPoint(m_series->pointsVector().at(index),
134 m_validData);
135 if (!m_validData)
136 m_points.clear();
137 else
138 points.insert(index, point);
139 }
140 updateChart(m_points, points, index);
127 }
141 }
128
129 updateChart(m_points, points, index);
130 }
142 }
131
143
132 void XYChart::handlePointRemoved(int index)
144 void XYChart::handlePointRemoved(int index)
133 {
145 {
134 Q_ASSERT(index <= m_series->count());
146 Q_ASSERT(index <= m_series->count());
135 Q_ASSERT(index >= 0);
147 Q_ASSERT(index >= 0);
136
148
137 QVector<QPointF> points;
149 if (m_series->useOpenGL()) {
138
150 updateGlChart();
139 if (m_dirty || m_points.isEmpty()) {
140 points = domain()->calculateGeometryPoints(m_series->points());
141 } else {
151 } else {
142 points = m_points;
152 QVector<QPointF> points;
143 points.remove(index);
153 if (m_dirty || m_points.isEmpty()) {
154 points = domain()->calculateGeometryPoints(m_series->pointsVector());
155 } else {
156 points = m_points;
157 points.remove(index);
158 }
159 updateChart(m_points, points, index);
144 }
160 }
145
146 updateChart(m_points, points, index);
147 }
161 }
148
162
149 void XYChart::handlePointsRemoved(int index, int count)
163 void XYChart::handlePointsRemoved(int index, int count)
150 {
164 {
151 Q_ASSERT(index <= m_series->count());
165 Q_ASSERT(index <= m_series->count());
152 Q_ASSERT(index >= 0);
166 Q_ASSERT(index >= 0);
153
167
154 QVector<QPointF> points;
168 if (m_series->useOpenGL()) {
155
169 updateGlChart();
156 if (m_dirty || m_points.isEmpty()) {
157 points = domain()->calculateGeometryPoints(m_series->points());
158 } else {
170 } else {
159 points = m_points;
171 QVector<QPointF> points;
160 points.remove(index, count);
172 if (m_dirty || m_points.isEmpty()) {
173 points = domain()->calculateGeometryPoints(m_series->pointsVector());
174 } else {
175 points = m_points;
176 points.remove(index, count);
177 }
178 updateChart(m_points, points, index);
161 }
179 }
162
163 updateChart(m_points, points, index);
164 }
180 }
165
181
166 void XYChart::handlePointReplaced(int index)
182 void XYChart::handlePointReplaced(int index)
167 {
183 {
168 Q_ASSERT(index < m_series->count());
184 Q_ASSERT(index < m_series->count());
169 Q_ASSERT(index >= 0);
185 Q_ASSERT(index >= 0);
170
186
171 QVector<QPointF> points;
187 if (m_series->useOpenGL()) {
172
188 updateGlChart();
173 if (m_dirty || m_points.isEmpty()) {
174 points = domain()->calculateGeometryPoints(m_series->points());
175 } else {
189 } else {
176 QPointF point = domain()->calculateGeometryPoint(m_series->points()[index], m_validData);
190 QVector<QPointF> points;
177 if (!m_validData)
191 if (m_dirty || m_points.isEmpty()) {
178 m_points.clear();
192 points = domain()->calculateGeometryPoints(m_series->pointsVector());
179 points = m_points;
193 } else {
180 if (m_validData)
194 QPointF point = domain()->calculateGeometryPoint(m_series->pointsVector().at(index),
181 points.replace(index, point);
195 m_validData);
196 if (!m_validData)
197 m_points.clear();
198 points = m_points;
199 if (m_validData)
200 points.replace(index, point);
201 }
202 updateChart(m_points, points, index);
182 }
203 }
183
184 updateChart(m_points, points, index);
185 }
204 }
186
205
187 void XYChart::handlePointsReplaced()
206 void XYChart::handlePointsReplaced()
188 {
207 {
189 // All the points were replaced -> recalculate
208 if (m_series->useOpenGL()) {
190 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->points());
209 updateGlChart();
191 updateChart(m_points, points, -1);
210 } else {
211 // All the points were replaced -> recalculate
212 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->pointsVector());
213 updateChart(m_points, points, -1);
214 }
192 }
215 }
193
216
194 void XYChart::handleDomainUpdated()
217 void XYChart::handleDomainUpdated()
195 {
218 {
196 if (isEmpty()) return;
219 if (m_series->useOpenGL()) {
197 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->points());
220 updateGlChart();
198 updateChart(m_points, points);
221 } else {
222 if (isEmpty()) return;
223 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->pointsVector());
224 updateChart(m_points, points);
225 }
199 }
226 }
200
227
201 bool XYChart::isEmpty()
228 bool XYChart::isEmpty()
202 {
229 {
203 return domain()->isEmpty() || m_series->points().isEmpty();
230 return domain()->isEmpty() || m_series->points().isEmpty();
204 }
231 }
205
232
206 #include "moc_xychart_p.cpp"
233 #include "moc_xychart_p.cpp"
207
234
208 QT_CHARTS_END_NAMESPACE
235 QT_CHARTS_END_NAMESPACE
@@ -1,20 +1,22
1 #INCLUDEPATH += $$PWD
1 #INCLUDEPATH += $$PWD
2 #DEPENDPATH += $$PWD
2 #DEPENDPATH += $$PWD
3
3
4 SOURCES += \
4 SOURCES += \
5 $$PWD/xychart.cpp \
5 $$PWD/xychart.cpp \
6 $$PWD/qxyseries.cpp \
6 $$PWD/qxyseries.cpp \
7 $$PWD/qxymodelmapper.cpp \
7 $$PWD/qxymodelmapper.cpp \
8 $$PWD/qvxymodelmapper.cpp \
8 $$PWD/qvxymodelmapper.cpp \
9 $$PWD/qhxymodelmapper.cpp
9 $$PWD/qhxymodelmapper.cpp \
10 $$PWD/glxyseriesdata.cpp
10
11
11 PRIVATE_HEADERS += \
12 PRIVATE_HEADERS += \
12 $$PWD/xychart_p.h \
13 $$PWD/xychart_p.h \
13 $$PWD/qxyseries_p.h \
14 $$PWD/qxyseries_p.h \
14 $$PWD/qxymodelmapper_p.h
15 $$PWD/qxymodelmapper_p.h \
16 $$PWD/glxyseriesdata_p.h
15
17
16 PUBLIC_HEADERS += \
18 PUBLIC_HEADERS += \
17 $$PWD/qxyseries.h \
19 $$PWD/qxyseries.h \
18 $$PWD/qxymodelmapper.h \
20 $$PWD/qxymodelmapper.h \
19 $$PWD/qvxymodelmapper.h \
21 $$PWD/qvxymodelmapper.h \
20 $$PWD/qhxymodelmapper.h
22 $$PWD/qhxymodelmapper.h
@@ -1,94 +1,95
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 // W A R N I N G
19 // W A R N I N G
20 // -------------
20 // -------------
21 //
21 //
22 // This file is not part of the Qt Chart API. It exists purely as an
22 // This file is not part of the Qt Chart API. It exists purely as an
23 // implementation detail. This header file may change from version to
23 // implementation detail. This header file may change from version to
24 // version without notice, or even be removed.
24 // version without notice, or even be removed.
25 //
25 //
26 // We mean it.
26 // We mean it.
27
27
28 #ifndef XYCHART_H
28 #ifndef XYCHART_H
29 #define XYCHART_H
29 #define XYCHART_H
30
30
31 #include <QtCharts/QChartGlobal>
31 #include <QtCharts/QChartGlobal>
32 #include <private/chartitem_p.h>
32 #include <private/chartitem_p.h>
33 #include <private/xyanimation_p.h>
33 #include <private/xyanimation_p.h>
34 #include <QtCharts/QValueAxis>
34 #include <QtCharts/QValueAxis>
35 #include <QtGui/QPen>
35 #include <QtGui/QPen>
36
36
37 QT_CHARTS_BEGIN_NAMESPACE
37 QT_CHARTS_BEGIN_NAMESPACE
38
38
39 class ChartPresenter;
39 class ChartPresenter;
40 class QXYSeries;
40 class QXYSeries;
41
41
42 class XYChart : public ChartItem
42 class XYChart : public ChartItem
43 {
43 {
44 Q_OBJECT
44 Q_OBJECT
45 public:
45 public:
46 explicit XYChart(QXYSeries *series,QGraphicsItem *item = 0);
46 explicit XYChart(QXYSeries *series,QGraphicsItem *item = 0);
47 ~XYChart() {}
47 ~XYChart() {}
48
48
49 void setGeometryPoints(const QVector<QPointF> &points);
49 void setGeometryPoints(const QVector<QPointF> &points);
50 QVector<QPointF> geometryPoints() const { return m_points; }
50 QVector<QPointF> geometryPoints() const { return m_points; }
51
51
52 void setAnimation(XYAnimation *animation);
52 void setAnimation(XYAnimation *animation);
53 ChartAnimation *animation() const { return m_animation; }
53 ChartAnimation *animation() const { return m_animation; }
54 virtual void updateGeometry() = 0;
54 virtual void updateGeometry() = 0;
55
55
56 bool isDirty() const { return m_dirty; }
56 bool isDirty() const { return m_dirty; }
57 void setDirty(bool dirty);
57 void setDirty(bool dirty);
58
58
59 void getSeriesRanges(qreal &minX, qreal &maxX, qreal &minY, qreal &maxY);
59 void getSeriesRanges(qreal &minX, qreal &maxX, qreal &minY, qreal &maxY);
60 QVector<bool> offGridStatusVector();
60 QVector<bool> offGridStatusVector();
61
61
62 public Q_SLOTS:
62 public Q_SLOTS:
63 void handlePointAdded(int index);
63 void handlePointAdded(int index);
64 void handlePointRemoved(int index);
64 void handlePointRemoved(int index);
65 void handlePointsRemoved(int index, int count);
65 void handlePointsRemoved(int index, int count);
66 void handlePointReplaced(int index);
66 void handlePointReplaced(int index);
67 void handlePointsReplaced();
67 void handlePointsReplaced();
68 void handleDomainUpdated();
68 void handleDomainUpdated();
69
69
70 Q_SIGNALS:
70 Q_SIGNALS:
71 void clicked(const QPointF &point);
71 void clicked(const QPointF &point);
72 void hovered(const QPointF &point, bool state);
72 void hovered(const QPointF &point, bool state);
73 void pressed(const QPointF &point);
73 void pressed(const QPointF &point);
74 void released(const QPointF &point);
74 void released(const QPointF &point);
75 void doubleClicked(const QPointF &point);
75 void doubleClicked(const QPointF &point);
76
76
77 protected:
77 protected:
78 virtual void updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index = -1);
78 virtual void updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index = -1);
79 virtual void updateGlChart();
79
80
80 private:
81 private:
81 inline bool isEmpty();
82 inline bool isEmpty();
82
83
83 protected:
84 protected:
84 QXYSeries *m_series;
85 QXYSeries *m_series;
85 QVector<QPointF> m_points;
86 QVector<QPointF> m_points;
86 XYAnimation *m_animation;
87 XYAnimation *m_animation;
87 bool m_dirty;
88 bool m_dirty;
88
89
89 friend class AreaChartItem;
90 friend class AreaChartItem;
90 };
91 };
91
92
92 QT_CHARTS_END_NAMESPACE
93 QT_CHARTS_END_NAMESPACE
93
94
94 #endif
95 #endif
@@ -1,78 +1,82
1
1
2 TARGET = qtchartsqml2
2 TARGET = qtchartsqml2
3 QT += qml quick
3 QT += qml quick
4 QT += charts charts-private
4 QT += charts charts-private
5 TARGETPATH = QtCharts
5 TARGETPATH = QtCharts
6
6
7 IMPORT_VERSION = $$MODULE_VERSION
7 IMPORT_VERSION = $$MODULE_VERSION
8
8
9 # Only build qml plugin static if Qt itself is also built static
9 # Only build qml plugin static if Qt itself is also built static
10 !contains(QT_CONFIG, static): CONFIG -= static staticlib
10 !contains(QT_CONFIG, static): CONFIG -= static staticlib
11
11
12 include($$PWD/designer/designer.pri)
12 include($$PWD/designer/designer.pri)
13
13
14 INCLUDEPATH += ../../include \
14 INCLUDEPATH += ../../include \
15 ../../include/QtCharts \
15 ../../include/QtCharts \
16 ../charts \
16 ../charts \
17 ../charts/animations \
17 ../charts/animations \
18 ../charts/axis \
18 ../charts/axis \
19 ../charts/domain
19 ../charts/domain
20
20
21 SOURCES += \
21 SOURCES += \
22 chartsqml2_plugin.cpp \
22 chartsqml2_plugin.cpp \
23 declarativechart.cpp \
23 declarativechart.cpp \
24 declarativexypoint.cpp \
24 declarativexypoint.cpp \
25 declarativexyseries.cpp \
25 declarativexyseries.cpp \
26 declarativelineseries.cpp \
26 declarativelineseries.cpp \
27 declarativesplineseries.cpp \
27 declarativesplineseries.cpp \
28 declarativeareaseries.cpp \
28 declarativeareaseries.cpp \
29 declarativescatterseries.cpp \
29 declarativescatterseries.cpp \
30 declarativepieseries.cpp \
30 declarativepieseries.cpp \
31 declarativebarseries.cpp \
31 declarativebarseries.cpp \
32 declarativecategoryaxis.cpp \
32 declarativecategoryaxis.cpp \
33 declarativemargins.cpp \
33 declarativemargins.cpp \
34 declarativeaxes.cpp \
34 declarativeaxes.cpp \
35 declarativepolarchart.cpp \
35 declarativepolarchart.cpp \
36 declarativeboxplotseries.cpp
36 declarativeboxplotseries.cpp \
37 declarativechartnode.cpp \
38 declarativerendernode.cpp
37
39
38 HEADERS += \
40 HEADERS += \
39 declarativechart.h \
41 declarativechart.h \
40 declarativexypoint.h \
42 declarativexypoint.h \
41 declarativexyseries.h \
43 declarativexyseries.h \
42 declarativelineseries.h \
44 declarativelineseries.h \
43 declarativesplineseries.h \
45 declarativesplineseries.h \
44 declarativeareaseries.h \
46 declarativeareaseries.h \
45 declarativescatterseries.h \
47 declarativescatterseries.h \
46 declarativepieseries.h \
48 declarativepieseries.h \
47 declarativebarseries.h \
49 declarativebarseries.h \
48 declarativecategoryaxis.h \
50 declarativecategoryaxis.h \
49 declarativemargins.h \
51 declarativemargins.h \
50 declarativeaxes.h \
52 declarativeaxes.h \
51 declarativepolarchart.h \
53 declarativepolarchart.h \
52 declarativeboxplotseries.h
54 declarativeboxplotseries.h \
55 declarativechartnode.h \
56 declarativerendernode.h
53
57
54 OTHER_FILES = qmldir
58 OTHER_FILES = qmldir
55
59
56 CONFIG += no_cxx_module
60 CONFIG += no_cxx_module
57
61
58 load(qml_plugin)
62 load(qml_plugin)
59
63
60 win32 {
64 win32 {
61 CONFIG += skip_target_version_ext
65 CONFIG += skip_target_version_ext
62 VERSION = $$MODULE_VERSION
66 VERSION = $$MODULE_VERSION
63 QMAKE_TARGET_PRODUCT = "Qt Charts (Qt $$QT_VERSION)"
67 QMAKE_TARGET_PRODUCT = "Qt Charts (Qt $$QT_VERSION)"
64 QMAKE_TARGET_DESCRIPTION = "Charts QML plugin for Qt."
68 QMAKE_TARGET_DESCRIPTION = "Charts QML plugin for Qt."
65 }
69 }
66
70
67 # Copy qmldir to DESTDIR so we can use the plugin directly from there in our examples
71 # Copy qmldir to DESTDIR so we can use the plugin directly from there in our examples
68 # without having to do 'make install'.
72 # without having to do 'make install'.
69 !android:!ios {
73 !android:!ios {
70 copy_qmldir.target = $$DESTDIR/qmldir
74 copy_qmldir.target = $$DESTDIR/qmldir
71 copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir
75 copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir
72 copy_qmldir.commands = $(COPY_FILE) \"$$replace(copy_qmldir.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_qmldir.target, /, $$QMAKE_DIR_SEP)\"
76 copy_qmldir.commands = $(COPY_FILE) \"$$replace(copy_qmldir.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_qmldir.target, /, $$QMAKE_DIR_SEP)\"
73 QMAKE_EXTRA_TARGETS += copy_qmldir
77 QMAKE_EXTRA_TARGETS += copy_qmldir
74 PRE_TARGETDEPS += $$copy_qmldir.target
78 PRE_TARGETDEPS += $$copy_qmldir.target
75 }
79 }
76
80
77 QML_FILES += \
81 QML_FILES += \
78 $$PWD/plugins.qmltypes
82 $$PWD/plugins.qmltypes
@@ -1,1180 +1,1226
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include "declarativechart.h"
19 #include "declarativechart.h"
20 #include <QtGui/QPainter>
20 #include <QtGui/QPainter>
21 #include "declarativelineseries.h"
21 #include "declarativelineseries.h"
22 #include "declarativeareaseries.h"
22 #include "declarativeareaseries.h"
23 #include "declarativebarseries.h"
23 #include "declarativebarseries.h"
24 #include "declarativepieseries.h"
24 #include "declarativepieseries.h"
25 #include "declarativesplineseries.h"
25 #include "declarativesplineseries.h"
26 #include "declarativeboxplotseries.h"
26 #include "declarativeboxplotseries.h"
27 #include "declarativescatterseries.h"
27 #include "declarativescatterseries.h"
28 #include "declarativechartnode.h"
29 #include "declarativerendernode.h"
28 #include <QtCharts/QBarCategoryAxis>
30 #include <QtCharts/QBarCategoryAxis>
29 #include <QtCharts/QValueAxis>
31 #include <QtCharts/QValueAxis>
30 #include <QtCharts/QLogValueAxis>
32 #include <QtCharts/QLogValueAxis>
31 #include <QtCharts/QCategoryAxis>
33 #include <QtCharts/QCategoryAxis>
32 #include <private/qabstractseries_p.h>
34 #include <private/qabstractseries_p.h>
33 #include "declarativemargins.h"
35 #include "declarativemargins.h"
34 #include <private/chartdataset_p.h>
36 #include <private/chartdataset_p.h>
35 #include "declarativeaxes.h"
37 #include "declarativeaxes.h"
36 #include <private/qchart_p.h>
38 #include <private/qchart_p.h>
39 #include <private/chartpresenter_p.h>
37 #include <QtCharts/QPolarChart>
40 #include <QtCharts/QPolarChart>
38
41
39 #ifndef QT_ON_ARM
42 #ifndef QT_ON_ARM
40 #include <QtCharts/QDateTimeAxis>
43 #include <QtCharts/QDateTimeAxis>
41 #endif
44 #endif
42
45
43 #include <QtWidgets/QGraphicsSceneMouseEvent>
46 #include <QtWidgets/QGraphicsSceneMouseEvent>
44 #include <QtWidgets/QGraphicsSceneHoverEvent>
47 #include <QtWidgets/QGraphicsSceneHoverEvent>
45 #include <QtWidgets/QApplication>
48 #include <QtWidgets/QApplication>
46 #include <QtCore/QTimer>
49 #include <QtCore/QTimer>
47 #include <QtCore/QThread>
50 #include <QtCore/QThread>
48
51
49 QT_CHARTS_BEGIN_NAMESPACE
52 QT_CHARTS_BEGIN_NAMESPACE
50
53
51 /*!
54 /*!
52 \qmltype ChartView
55 \qmltype ChartView
53 \instantiates DeclarativeChart
56 \instantiates DeclarativeChart
54 \inqmlmodule QtCharts
57 \inqmlmodule QtCharts
55
58
56 \brief Chart element.
59 \brief Chart element.
57
60
58 ChartView element is the parent that is responsible for showing different chart series types.
61 ChartView element is the parent that is responsible for showing different chart series types.
59
62
60 The following QML shows how to create a simple chart with one pie series:
63 The following QML shows how to create a simple chart with one pie series:
61 \snippet qmlpiechart/qml/qmlpiechart/main.qml 1
64 \snippet qmlpiechart/qml/qmlpiechart/main.qml 1
62 \snippet qmlpiechart/qml/qmlpiechart/main.qml 2
65 \snippet qmlpiechart/qml/qmlpiechart/main.qml 2
63 \snippet qmlpiechart/qml/qmlpiechart/main.qml 3
66 \snippet qmlpiechart/qml/qmlpiechart/main.qml 3
64
67
65 \beginfloatleft
68 \beginfloatleft
66 \image examples_qmlpiechart.png
69 \image examples_qmlpiechart.png
67 \endfloat
70 \endfloat
68 \clearfloat
71 \clearfloat
69 */
72 */
70
73
71 /*!
74 /*!
72 \qmlproperty Theme ChartView::theme
75 \qmlproperty Theme ChartView::theme
73 Theme defines the visual appearance of the chart, including for example colors, fonts, line
76 Theme defines the visual appearance of the chart, including for example colors, fonts, line
74 widths and chart background.
77 widths and chart background.
75 */
78 */
76
79
77 /*!
80 /*!
78 \qmlproperty Animation ChartView::animationOptions
81 \qmlproperty Animation ChartView::animationOptions
79 Animation configuration of the chart. One of ChartView.NoAnimation, ChartView.GridAxisAnimations,
82 Animation configuration of the chart. One of ChartView.NoAnimation, ChartView.GridAxisAnimations,
80 ChartView.SeriesAnimations or ChartView.AllAnimations.
83 ChartView.SeriesAnimations or ChartView.AllAnimations.
81 */
84 */
82
85
83 /*!
86 /*!
84 \qmlproperty int ChartView::animationDuration
87 \qmlproperty int ChartView::animationDuration
85 The duration of the animation for the chart.
88 The duration of the animation for the chart.
86 */
89 */
87
90
88 /*!
91 /*!
89 \qmlproperty easing ChartView::animationEasingCurve
92 \qmlproperty easing ChartView::animationEasingCurve
90 The easing curve of the animation for the chart.
93 The easing curve of the animation for the chart.
94 */
91
95
92 /*!
96 /*!
93 \qmlproperty Font ChartView::titleFont
97 \qmlproperty Font ChartView::titleFont
94 The title font of the chart.
98 The title font of the chart.
95
99
96 See the Qt documentation for more details of Font.
100 See the Qt documentation for more details of Font.
97 */
101 */
98
102
99 /*!
103 /*!
100 \qmlproperty string ChartView::title
104 \qmlproperty string ChartView::title
101 The title of the chart, shown on top of the chart.
105 The title of the chart, shown on top of the chart.
102 \sa ChartView::titleColor
106 \sa ChartView::titleColor
103 */
107 */
104
108
105 /*!
109 /*!
106 \qmlproperty color ChartView::titleColor
110 \qmlproperty color ChartView::titleColor
107 The color of the title text.
111 The color of the title text.
108 */
112 */
109
113
110 /*!
114 /*!
111 \qmlproperty Legend ChartView::legend
115 \qmlproperty Legend ChartView::legend
112 The legend of the chart. Legend lists all the series, pie slices and bar sets added on the chart.
116 The legend of the chart. Legend lists all the series, pie slices and bar sets added on the chart.
113 */
117 */
114
118
115 /*!
119 /*!
116 \qmlproperty int ChartView::count
120 \qmlproperty int ChartView::count
117 The count of series added to the chart.
121 The count of series added to the chart.
118 */
122 */
119
123
120 /*!
124 /*!
121 \qmlproperty color ChartView::backgroundColor
125 \qmlproperty color ChartView::backgroundColor
122 The color of the chart's background. By default background color is defined by chart theme.
126 The color of the chart's background. By default background color is defined by chart theme.
123 \sa ChartView::theme
127 \sa ChartView::theme
124 */
128 */
125
129
126 /*!
130 /*!
127 \qmlproperty real ChartView::backgroundRoundness
131 \qmlproperty real ChartView::backgroundRoundness
128 The diameter of the rounding circle at the corners of the chart background.
132 The diameter of the rounding circle at the corners of the chart background.
129 */
133 */
130
134
131 /*!
135 /*!
132 \qmlproperty color ChartView::plotAreaColor
136 \qmlproperty color ChartView::plotAreaColor
133 The color of the background of the chart's plot area. By default plot area background uses chart's
137 The color of the background of the chart's plot area. By default plot area background uses chart's
134 background color.
138 background color.
135 \sa ChartView::backgroundColor
139 \sa ChartView::backgroundColor
136 */
140 */
137
141
138 /*!
142 /*!
139 \qmlproperty list<AbstractAxis> ChartView::axes
143 \qmlproperty list<AbstractAxis> ChartView::axes
140 The axes of the ChartView.
144 The axes of the ChartView.
141 */
145 */
142
146
143 /*!
147 /*!
144 \qmlproperty bool ChartView::dropShadowEnabled
148 \qmlproperty bool ChartView::dropShadowEnabled
145 The chart's border drop shadow. Set to true to enable drop shadow.
149 The chart's border drop shadow. Set to true to enable drop shadow.
146 */
150 */
147
151
148 /*!
152 /*!
149 \qmlproperty rect ChartView::plotArea
153 \qmlproperty rect ChartView::plotArea
150 The area on the ChartView that is used for drawing series. This is the ChartView rect without the
154 The area on the ChartView that is used for drawing series. This is the ChartView rect without the
151 margins.
155 margins.
152 \sa ChartView::margins
156 \sa ChartView::margins
153 */
157 */
154
158
155 /*!
159 /*!
156 \qmlproperty Margins ChartView::margins
160 \qmlproperty Margins ChartView::margins
157 The minimum margins allowed between the outer bounds and the plotArea of the ChartView. Margins
161 The minimum margins allowed between the outer bounds and the plotArea of the ChartView. Margins
158 area of ChartView is used for drawing title, axes and legend.
162 area of ChartView is used for drawing title, axes and legend.
159 */
163 */
160
164
161 /*!
165 /*!
162 \qmlproperty bool ChartView::localizeNumbers
166 \qmlproperty bool ChartView::localizeNumbers
163 \since QtCharts 2.0
167 \since QtCharts 2.0
164 When \c{true}, all generated numbers appearing in various series and axis labels will be
168 When \c{true}, all generated numbers appearing in various series and axis labels will be
165 localized using the default QLocale of the application, which defaults to the system locale.
169 localized using the default QLocale of the application, which defaults to the system locale.
166 When \c{false}, the "C" locale is always used.
170 When \c{false}, the "C" locale is always used.
167 Defaults to \c{false}.
171 Defaults to \c{false}.
168
172
169 \sa locale
173 \sa locale
170 */
174 */
171
175
172 /*!
176 /*!
173 \qmlproperty locale ChartView::locale
177 \qmlproperty locale ChartView::locale
174 \since QtCharts 2.0
178 \since QtCharts 2.0
175 Sets the locale used to format various chart labels when localizeNumbers is \c{true}.
179 Sets the locale used to format various chart labels when localizeNumbers is \c{true}.
176 This also determines the locale used to format DateTimeAxis labels regardless of
180 This also determines the locale used to format DateTimeAxis labels regardless of
177 localizeNumbers property.
181 localizeNumbers property.
178 Defaults to application default locale at the time the chart is constructed.
182 Defaults to application default locale at the time the chart is constructed.
179
183
180 \sa localizeNumbers
184 \sa localizeNumbers
181 */
185 */
182
186
183 /*!
187 /*!
184 \qmlmethod AbstractSeries ChartView::series(int index)
188 \qmlmethod AbstractSeries ChartView::series(int index)
185 Returns the series with \a index on the chart. This allows you to loop through the series of a chart together with
189 Returns the series with \a index on the chart. This allows you to loop through the series of a chart together with
186 the count property of the chart.
190 the count property of the chart.
187 */
191 */
188
192
189 /*!
193 /*!
190 \qmlmethod AbstractSeries ChartView::series(string name)
194 \qmlmethod AbstractSeries ChartView::series(string name)
191 Returns the first series on the chart with \a name. If there is no series with that name, returns null.
195 Returns the first series on the chart with \a name. If there is no series with that name, returns null.
192 */
196 */
193
197
194 /*!
198 /*!
195 \qmlmethod AbstractSeries ChartView::createSeries(SeriesType type, string name, AbstractAxis axisX, AbstractAxis axisY)
199 \qmlmethod AbstractSeries ChartView::createSeries(SeriesType type, string name, AbstractAxis axisX, AbstractAxis axisY)
196 Creates a series object of \a type to the chart with name \a name, optional axis \a axisX and
200 Creates a series object of \a type to the chart with name \a name, optional axis \a axisX and
197 optional axis \a axisY. For example:
201 optional axis \a axisY. For example:
198 \code
202 \code
199 // lineSeries is a LineSeries object that has already been added to the ChartView; re-use it's axes
203 // lineSeries is a LineSeries object that has already been added to the ChartView; re-use it's axes
200 var myAxisX = chartView.axisX(lineSeries);
204 var myAxisX = chartView.axisX(lineSeries);
201 var myAxisY = chartView.axisY(lineSeries);
205 var myAxisY = chartView.axisY(lineSeries);
202 var scatter = chartView.createSeries(ChartView.SeriesTypeScatter, "scatter series", myAxisX, myAxisY);
206 var scatter = chartView.createSeries(ChartView.SeriesTypeScatter, "scatter series", myAxisX, myAxisY);
203 \endcode
207 \endcode
204 */
208 */
205
209
206 /*!
210 /*!
207 \qmlmethod ChartView::removeSeries(AbstractSeries series)
211 \qmlmethod ChartView::removeSeries(AbstractSeries series)
208 Removes the \a series from the chart. The series object is also destroyed.
212 Removes the \a series from the chart. The series object is also destroyed.
209 */
213 */
210
214
211 /*!
215 /*!
212 \qmlmethod ChartView::removeAllSeries()
216 \qmlmethod ChartView::removeAllSeries()
213 Removes all series from the chart. All the series objects are also destroyed.
217 Removes all series from the chart. All the series objects are also destroyed.
214 */
218 */
215
219
216 /*!
220 /*!
217 \qmlmethod Axis ChartView::axisX(AbstractSeries series)
221 \qmlmethod Axis ChartView::axisX(AbstractSeries series)
218 The x-axis of the series.
222 The x-axis of the series.
219 */
223 */
220
224
221 /*!
225 /*!
222 \qmlmethod ChartView::setAxisX(AbstractAxis axis, AbstractSeries series)
226 \qmlmethod ChartView::setAxisX(AbstractAxis axis, AbstractSeries series)
223 Set the x-axis of the series.
227 Set the x-axis of the series.
224 */
228 */
225
229
226 /*!
230 /*!
227 \qmlmethod Axis ChartView::axisY(AbstractSeries series)
231 \qmlmethod Axis ChartView::axisY(AbstractSeries series)
228 The y-axis of the series.
232 The y-axis of the series.
229 */
233 */
230
234
231 /*!
235 /*!
232 \qmlmethod ChartView::setAxisY(AbstractAxis axis, AbstractSeries series)
236 \qmlmethod ChartView::setAxisY(AbstractAxis axis, AbstractSeries series)
233 Set the y-axis of the series.
237 Set the y-axis of the series.
234 */
238 */
235
239
236 /*!
240 /*!
237 \qmlmethod ChartView::zoom(real factor)
241 \qmlmethod ChartView::zoom(real factor)
238 Zooms in by \a factor on the center of the chart.
242 Zooms in by \a factor on the center of the chart.
239
243
240 A factor over 1.0 zooms the view in and factor between 0.0 and 1.0 zooms out.
244 A factor over 1.0 zooms the view in and factor between 0.0 and 1.0 zooms out.
241 */
245 */
242
246
243 /*!
247 /*!
244 \qmlmethod ChartView::zoomIn()
248 \qmlmethod ChartView::zoomIn()
245 Zooms in the view by a factor of two.
249 Zooms in the view by a factor of two.
246 */
250 */
247
251
248 /*!
252 /*!
249 \qmlmethod ChartView::zoomIn(rect rectangle)
253 \qmlmethod ChartView::zoomIn(rect rectangle)
250 Zooms in the view to a maximum level at which \a rectangle is still fully visible.
254 Zooms in the view to a maximum level at which \a rectangle is still fully visible.
251 \note This is not supported for polar charts.
255 \note This is not supported for polar charts.
252 */
256 */
253
257
254 /*!
258 /*!
255 \qmlmethod ChartView::zoomOut()
259 \qmlmethod ChartView::zoomOut()
256 Zooms out the view by a factor of two.
260 Zooms out the view by a factor of two.
257 */
261 */
258
262
259 /*!
263 /*!
260 \qmlmethod ChartView::zoomReset()
264 \qmlmethod ChartView::zoomReset()
261 Resets the series domains to what they were before any zoom method was called.
265 Resets the series domains to what they were before any zoom method was called.
262 Note that this will also reset any scrolls and explicit axis range settings done between
266 Note that this will also reset any scrolls and explicit axis range settings done between
263 the first zoom operation and calling this method. If no zoom operation has been
267 the first zoom operation and calling this method. If no zoom operation has been
264 done, this method does nothing.
268 done, this method does nothing.
265 */
269 */
266
270
267 /*!
271 /*!
268 \qmlmethod ChartView::isZoomed()
272 \qmlmethod ChartView::isZoomed()
269 Returns true if any series has a zoomed domain.
273 Returns true if any series has a zoomed domain.
270 */
274 */
271
275
272 /*!
276 /*!
273 \qmlmethod ChartView::scrollLeft(real pixels)
277 \qmlmethod ChartView::scrollLeft(real pixels)
274 Scrolls to left by \a pixels. This is a convenience function that suits for example for key navigation.
278 Scrolls to left by \a pixels. This is a convenience function that suits for example for key navigation.
275 */
279 */
276
280
277 /*!
281 /*!
278 \qmlmethod ChartView::scrollRight(real pixels)
282 \qmlmethod ChartView::scrollRight(real pixels)
279 Scrolls to right by \a pixels. This is a convenience function that suits for example for key navigation.
283 Scrolls to right by \a pixels. This is a convenience function that suits for example for key navigation.
280 */
284 */
281
285
282 /*!
286 /*!
283 \qmlmethod ChartView::scrollUp(real pixels)
287 \qmlmethod ChartView::scrollUp(real pixels)
284 Scrolls up by \a pixels. This is a convenience function that suits for example for key navigation.
288 Scrolls up by \a pixels. This is a convenience function that suits for example for key navigation.
285 */
289 */
286
290
287 /*!
291 /*!
288 \qmlmethod ChartView::scrollDown(real pixels)
292 \qmlmethod ChartView::scrollDown(real pixels)
289 Scrolls down by \a pixels. This is a convenience function that suits for example for key navigation.
293 Scrolls down by \a pixels. This is a convenience function that suits for example for key navigation.
290 */
294 */
291
295
292 /*!
296 /*!
293 \qmlmethod point ChartView::mapToValue(point position, AbstractSeries series)
297 \qmlmethod point ChartView::mapToValue(point position, AbstractSeries series)
294 Returns the value in the \a series domain that corresponds to the \a position relative to the
298 Returns the value in the \a series domain that corresponds to the \a position relative to the
295 chart.
299 chart.
296 */
300 */
297
301
298 /*!
302 /*!
299 \qmlmethod point ChartView::mapToPosition(point value, AbstractSeries series)
303 \qmlmethod point ChartView::mapToPosition(point value, AbstractSeries series)
300 Returns the position on the chart that corresponds to the \a value in the \a series domain.
304 Returns the position on the chart that corresponds to the \a value in the \a series domain.
301 */
305 */
302
306
303 /*!
307 /*!
304 \qmlsignal ChartView::seriesAdded(AbstractSeries series)
308 \qmlsignal ChartView::seriesAdded(AbstractSeries series)
305 The \a series has been added to the chart.
309 The \a series has been added to the chart.
306 */
310 */
307
311
308 /*!
312 /*!
309 \qmlsignal ChartView::seriesRemoved(AbstractSeries series)
313 \qmlsignal ChartView::seriesRemoved(AbstractSeries series)
310 The \a series has been removed from the chart. Please note that \a series is no longer a valid
314 The \a series has been removed from the chart. Please note that \a series is no longer a valid
311 object after the signal handler has completed.
315 object after the signal handler has completed.
312 */
316 */
313
317
314 DeclarativeChart::DeclarativeChart(QQuickItem *parent)
318 DeclarativeChart::DeclarativeChart(QQuickItem *parent)
315 : QQuickPaintedItem(parent)
319 : QQuickItem(parent)
316 {
320 {
317 initChart(QChart::ChartTypeCartesian);
321 initChart(QChart::ChartTypeCartesian);
318 }
322 }
319
323
320 DeclarativeChart::DeclarativeChart(QChart::ChartType type, QQuickItem *parent)
324 DeclarativeChart::DeclarativeChart(QChart::ChartType type, QQuickItem *parent)
321 : QQuickPaintedItem(parent)
325 : QQuickItem(parent)
322 {
326 {
323 initChart(type);
327 initChart(type);
324 }
328 }
325
329
326 void DeclarativeChart::initChart(QChart::ChartType type)
330 void DeclarativeChart::initChart(QChart::ChartType type)
327 {
331 {
328 m_currentSceneImage = 0;
332 m_sceneImage = 0;
333 m_sceneImageDirty = false;
329 m_guiThreadId = QThread::currentThreadId();
334 m_guiThreadId = QThread::currentThreadId();
330 m_paintThreadId = 0;
335 m_paintThreadId = 0;
331 m_updatePending = false;
336 m_updatePending = false;
332
337
338 setFlag(ItemHasContents, true);
339
333 if (type == QChart::ChartTypePolar)
340 if (type == QChart::ChartTypePolar)
334 m_chart = new QPolarChart();
341 m_chart = new QPolarChart();
335 else
342 else
336 m_chart = new QChart();
343 m_chart = new QChart();
337
344
345 m_chart->d_ptr->m_presenter->glSetUseWidget(false);
346 m_glXYDataManager = m_chart->d_ptr->m_dataset->glXYSeriesDataManager();
347
338 m_scene = new QGraphicsScene(this);
348 m_scene = new QGraphicsScene(this);
339 m_scene->addItem(m_chart);
349 m_scene->addItem(m_chart);
340
350
341 setAntialiasing(QQuickItem::antialiasing());
351 setAntialiasing(QQuickItem::antialiasing());
342 connect(m_scene, SIGNAL(changed(QList<QRectF>)), this, SLOT(sceneChanged(QList<QRectF>)));
352 connect(m_scene, &QGraphicsScene::changed, this, &DeclarativeChart::sceneChanged);
353 connect(this, &DeclarativeChart::needRender, this, &DeclarativeChart::renderScene,
354 Qt::QueuedConnection);
343 connect(this, SIGNAL(antialiasingChanged(bool)), this, SLOT(handleAntialiasingChanged(bool)));
355 connect(this, SIGNAL(antialiasingChanged(bool)), this, SLOT(handleAntialiasingChanged(bool)));
344
356
345 setAcceptedMouseButtons(Qt::AllButtons);
357 setAcceptedMouseButtons(Qt::AllButtons);
346 setAcceptHoverEvents(true);
358 setAcceptHoverEvents(true);
347
359
348 m_margins = new DeclarativeMargins(this);
360 m_margins = new DeclarativeMargins(this);
349 m_margins->setTop(m_chart->margins().top());
361 m_margins->setTop(m_chart->margins().top());
350 m_margins->setLeft(m_chart->margins().left());
362 m_margins->setLeft(m_chart->margins().left());
351 m_margins->setRight(m_chart->margins().right());
363 m_margins->setRight(m_chart->margins().right());
352 m_margins->setBottom(m_chart->margins().bottom());
364 m_margins->setBottom(m_chart->margins().bottom());
353 connect(m_margins, SIGNAL(topChanged(int,int,int,int)),
365 connect(m_margins, SIGNAL(topChanged(int,int,int,int)),
354 this, SLOT(changeMargins(int,int,int,int)));
366 this, SLOT(changeMargins(int,int,int,int)));
355 connect(m_margins, SIGNAL(bottomChanged(int,int,int,int)),
367 connect(m_margins, SIGNAL(bottomChanged(int,int,int,int)),
356 this, SLOT(changeMargins(int,int,int,int)));
368 this, SLOT(changeMargins(int,int,int,int)));
357 connect(m_margins, SIGNAL(leftChanged(int,int,int,int)),
369 connect(m_margins, SIGNAL(leftChanged(int,int,int,int)),
358 this, SLOT(changeMargins(int,int,int,int)));
370 this, SLOT(changeMargins(int,int,int,int)));
359 connect(m_margins, SIGNAL(rightChanged(int,int,int,int)),
371 connect(m_margins, SIGNAL(rightChanged(int,int,int,int)),
360 this, SLOT(changeMargins(int,int,int,int)));
372 this, SLOT(changeMargins(int,int,int,int)));
361 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesAdded(QAbstractSeries*)));
373 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesAdded(QAbstractSeries*)));
362 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SIGNAL(seriesRemoved(QAbstractSeries*)));
374 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SIGNAL(seriesRemoved(QAbstractSeries*)));
363 connect(m_chart, &QChart::plotAreaChanged, this, &DeclarativeChart::plotAreaChanged);
375 connect(m_chart, &QChart::plotAreaChanged, this, &DeclarativeChart::plotAreaChanged);
364 }
376 }
365
377
366 void DeclarativeChart::handleSeriesAdded(QAbstractSeries *series)
378 void DeclarativeChart::handleSeriesAdded(QAbstractSeries *series)
367 {
379 {
368 emit seriesAdded(series);
380 emit seriesAdded(series);
369 }
381 }
370
382
371 void DeclarativeChart::changeMargins(int top, int bottom, int left, int right)
383 void DeclarativeChart::changeMargins(int top, int bottom, int left, int right)
372 {
384 {
373 m_chart->setMargins(QMargins(left, top, right, bottom));
385 m_chart->setMargins(QMargins(left, top, right, bottom));
374 emit marginsChanged();
386 emit marginsChanged();
375 }
387 }
376
388
377 DeclarativeChart::~DeclarativeChart()
389 DeclarativeChart::~DeclarativeChart()
378 {
390 {
379 delete m_chart;
391 delete m_chart;
380 m_sceneImageLock.lock();
392 delete m_sceneImage;
381 delete m_currentSceneImage;
382 m_currentSceneImage = 0;
383 m_sceneImageLock.unlock();
384 }
393 }
385
394
386 void DeclarativeChart::childEvent(QChildEvent *event)
395 void DeclarativeChart::childEvent(QChildEvent *event)
387 {
396 {
388 if (event->type() == QEvent::ChildAdded) {
397 if (event->type() == QEvent::ChildAdded) {
389 if (qobject_cast<QAbstractSeries *>(event->child())) {
398 if (qobject_cast<QAbstractSeries *>(event->child())) {
390 m_chart->addSeries(qobject_cast<QAbstractSeries *>(event->child()));
399 m_chart->addSeries(qobject_cast<QAbstractSeries *>(event->child()));
391 }
400 }
392 }
401 }
393 }
402 }
394
403
395 void DeclarativeChart::componentComplete()
404 void DeclarativeChart::componentComplete()
396 {
405 {
397 foreach (QObject *child, children()) {
406 foreach (QObject *child, children()) {
398 if (qobject_cast<QAbstractSeries *>(child)) {
407 if (qobject_cast<QAbstractSeries *>(child)) {
399 // Add series to the chart
408 // Add series to the chart
400 QAbstractSeries *series = qobject_cast<QAbstractSeries *>(child);
409 QAbstractSeries *series = qobject_cast<QAbstractSeries *>(child);
401 m_chart->addSeries(series);
410 m_chart->addSeries(series);
402
411
403 // Connect to axis changed signals (unless this is a pie series)
412 // Connect to axis changed signals (unless this is a pie series)
404 if (!qobject_cast<DeclarativePieSeries *>(series)) {
413 if (!qobject_cast<DeclarativePieSeries *>(series)) {
405 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
414 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
406 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXTopSet(QAbstractAxis*)));
415 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXTopSet(QAbstractAxis*)));
407 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
416 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
408 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
417 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
409 }
418 }
410
419
411 initializeAxes(series);
420 initializeAxes(series);
412 }
421 }
413 }
422 }
414
423
415 QQuickItem::componentComplete();
424 QQuickItem::componentComplete();
416 }
425 }
417
426
418 void DeclarativeChart::seriesAxisAttachHelper(QAbstractSeries *series, QAbstractAxis *axis,
427 void DeclarativeChart::seriesAxisAttachHelper(QAbstractSeries *series, QAbstractAxis *axis,
419 Qt::Orientations orientation,
428 Qt::Orientations orientation,
420 Qt::Alignment alignment)
429 Qt::Alignment alignment)
421 {
430 {
422 if (!series->attachedAxes().contains(axis)) {
431 if (!series->attachedAxes().contains(axis)) {
423 // Remove & delete old axes that are not attached to any other series
432 // Remove & delete old axes that are not attached to any other series
424 foreach (QAbstractAxis* oldAxis, m_chart->axes(orientation, series)) {
433 foreach (QAbstractAxis* oldAxis, m_chart->axes(orientation, series)) {
425 bool otherAttachments = false;
434 bool otherAttachments = false;
426 if (oldAxis != axis) {
435 if (oldAxis != axis) {
427 foreach (QAbstractSeries *oldSeries, m_chart->series()) {
436 foreach (QAbstractSeries *oldSeries, m_chart->series()) {
428 if (oldSeries != series && oldSeries->attachedAxes().contains(oldAxis)) {
437 if (oldSeries != series && oldSeries->attachedAxes().contains(oldAxis)) {
429 otherAttachments = true;
438 otherAttachments = true;
430 break;
439 break;
431 }
440 }
432 }
441 }
433 if (!otherAttachments) {
442 if (!otherAttachments) {
434 m_chart->removeAxis(oldAxis);
443 m_chart->removeAxis(oldAxis);
435 delete oldAxis;
444 delete oldAxis;
436 }
445 }
437 }
446 }
438 }
447 }
439 if (!m_chart->axes(orientation).contains(axis))
448 if (!m_chart->axes(orientation).contains(axis))
440 m_chart->addAxis(axis, alignment);
449 m_chart->addAxis(axis, alignment);
441
450
442 series->attachAxis(axis);
451 series->attachAxis(axis);
443 }
452 }
444 }
453 }
445
454
446 void DeclarativeChart::handleAxisXSet(QAbstractAxis *axis)
455 void DeclarativeChart::handleAxisXSet(QAbstractAxis *axis)
447 {
456 {
448 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
457 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
449 if (axis && s) {
458 if (axis && s) {
450 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignBottom);
459 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignBottom);
451 } else {
460 } else {
452 qWarning() << "Trying to set axisX to null.";
461 qWarning() << "Trying to set axisX to null.";
453 }
462 }
454 }
463 }
455
464
456 void DeclarativeChart::handleAxisXTopSet(QAbstractAxis *axis)
465 void DeclarativeChart::handleAxisXTopSet(QAbstractAxis *axis)
457 {
466 {
458 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
467 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
459 if (axis && s) {
468 if (axis && s) {
460 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignTop);
469 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignTop);
461 } else {
470 } else {
462 qWarning() << "Trying to set axisXTop to null.";
471 qWarning() << "Trying to set axisXTop to null.";
463 }
472 }
464 }
473 }
465
474
466 void DeclarativeChart::handleAxisYSet(QAbstractAxis *axis)
475 void DeclarativeChart::handleAxisYSet(QAbstractAxis *axis)
467 {
476 {
468 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
477 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
469 if (axis && s) {
478 if (axis && s) {
470 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignLeft);
479 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignLeft);
471 } else {
480 } else {
472 qWarning() << "Trying to set axisY to null.";
481 qWarning() << "Trying to set axisY to null.";
473 }
482 }
474 }
483 }
475
484
476 void DeclarativeChart::handleAxisYRightSet(QAbstractAxis *axis)
485 void DeclarativeChart::handleAxisYRightSet(QAbstractAxis *axis)
477 {
486 {
478 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
487 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
479 if (axis && s) {
488 if (axis && s) {
480 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignRight);
489 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignRight);
481 } else {
490 } else {
482 qWarning() << "Trying to set axisYRight to null.";
491 qWarning() << "Trying to set axisYRight to null.";
483 }
492 }
484 }
493 }
485
494
486 void DeclarativeChart::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
495 void DeclarativeChart::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
487 {
496 {
488 if (newGeometry.isValid()) {
497 if (newGeometry.isValid()) {
489 if (newGeometry.width() > 0 && newGeometry.height() > 0) {
498 if (newGeometry.width() > 0 && newGeometry.height() > 0) {
490 m_chart->resize(newGeometry.width(), newGeometry.height());
499 m_chart->resize(newGeometry.width(), newGeometry.height());
491 }
500 }
492 }
501 }
493 QQuickItem::geometryChanged(newGeometry, oldGeometry);
502 QQuickItem::geometryChanged(newGeometry, oldGeometry);
494 }
503 }
495
504
496 void DeclarativeChart::sceneChanged(QList<QRectF> region)
505 QSGNode *DeclarativeChart::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
497 {
506 {
498 Q_UNUSED(region);
507 DeclarativeChartNode *node = static_cast<DeclarativeChartNode *>(oldNode);
499
508
500 if (m_guiThreadId == m_paintThreadId) {
509 if (!node) {
501 // Rendering in gui thread, no need for shenannigans, just update
510 node = new DeclarativeChartNode(window());
502 update();
511 connect(window(), &QQuickWindow::beforeRendering,
503 } else {
512 node->glRenderNode(), &DeclarativeRenderNode::render);
504 // Multi-threaded rendering, need to ensure scene is actually rendered in gui thread
513 }
505 if (!m_updatePending) {
514
515 const QRectF &bRect = boundingRect();
516
517 // Update GL data
518 if (m_glXYDataManager->dataMap().size() || m_glXYDataManager->mapDirty()) {
519 const QRectF &plotArea = m_chart->plotArea();
520 const QSizeF &chartAreaSize = m_chart->size();
521
522 // We can't use chart's plot area directly, as graphicscene has some internal minimum size
523 const qreal normalizedX = plotArea.x() / chartAreaSize.width();
524 const qreal normalizedY = plotArea.y() / chartAreaSize.height();
525 const qreal normalizedWidth = plotArea.width() / chartAreaSize.width();
526 const qreal normalizedHeight = plotArea.height() / chartAreaSize.height();
527
528 QRectF adjustedPlotArea(normalizedX * bRect.width(),
529 normalizedY * bRect.height(),
530 normalizedWidth * bRect.width(),
531 normalizedHeight * bRect.height());
532
533 const QSize &adjustedPlotSize = adjustedPlotArea.size().toSize();
534 if (adjustedPlotSize != node->glRenderNode()->textureSize())
535 node->glRenderNode()->setTextureSize(adjustedPlotSize);
536
537 node->glRenderNode()->setRect(adjustedPlotArea);
538 node->glRenderNode()->setSeriesData(m_glXYDataManager->mapDirty(),
539 m_glXYDataManager->dataMap());
540
541 // Clear dirty flags from original xy data
542 m_glXYDataManager->clearAllDirty();
543 }
544
545 // Copy chart (if dirty) to chart node
546 if (m_sceneImageDirty) {
547 node->createTextureFromImage(*m_sceneImage);
548 m_sceneImageDirty = false;
549 }
550
551 node->setRect(bRect);
552
553 return node;
554 }
555
556 void DeclarativeChart::sceneChanged(QList<QRectF> region)
557 {
558 const int count = region.size();
559 const qreal limitSize = 0.01;
560 if (count && !m_updatePending) {
561 qreal totalSize = 0.0;
562 for (int i = 0; i < count; i++) {
563 const QRectF &reg = region.at(i);
564 totalSize += (reg.height() * reg.width());
565 if (totalSize >= limitSize)
566 break;
567 }
568 // Ignore region updates that change less than small fraction of a pixel, as there is
569 // little point regenerating the image in these cases. These are typically cases
570 // where OpenGL series are drawn to otherwise static chart.
571 if (totalSize >= limitSize) {
506 m_updatePending = true;
572 m_updatePending = true;
507 // Do async render to avoid some unnecessary renders.
573 // Do async render to avoid some unnecessary renders.
508 QTimer::singleShot(0, this, SLOT(renderScene()));
574 emit needRender();
575 } else {
576 // We do want to call update to trigger possible gl series updates.
577 update();
509 }
578 }
510 }
579 }
511 }
580 }
512
581
513 void DeclarativeChart::renderScene()
582 void DeclarativeChart::renderScene()
514 {
583 {
515 m_updatePending = false;
584 m_updatePending = false;
516 m_sceneImageLock.lock();
585 m_sceneImageDirty = true;
517 delete m_currentSceneImage;
586 QSize chartSize = m_chart->size().toSize();
518 m_currentSceneImage = new QImage(m_chart->size().toSize(), QImage::Format_ARGB32);
587 if (!m_sceneImage || chartSize != m_sceneImage->size()) {
519 m_currentSceneImage->fill(Qt::transparent);
588 delete m_sceneImage;
520 QPainter painter(m_currentSceneImage);
589 m_sceneImage = new QImage(chartSize, QImage::Format_ARGB32);
521 if (antialiasing())
590 m_sceneImage->fill(Qt::transparent);
522 painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
523 QRect renderRect(QPoint(0, 0), m_chart->size().toSize());
524 m_scene->render(&painter, renderRect, renderRect);
525 m_sceneImageLock.unlock();
526
527 update();
528 }
529
530 void DeclarativeChart::paint(QPainter *painter)
531 {
532 if (!m_paintThreadId) {
533 m_paintThreadId = QThread::currentThreadId();
534 if (m_guiThreadId == m_paintThreadId) {
535 // No need for scene image in single threaded rendering, so delete
536 // the one that got made by default before the rendering type was
537 // detected.
538 delete m_currentSceneImage;
539 m_currentSceneImage = 0;
540 }
541 }
591 }
542
592
543 if (m_guiThreadId == m_paintThreadId) {
593 QPainter painter(m_sceneImage);
544 QRectF renderRect(QPointF(0, 0), m_chart->size());
594 if (antialiasing()) {
545 m_scene->render(painter, renderRect, renderRect);
595 painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing
546 } else {
596 | QPainter::SmoothPixmapTransform);
547 m_sceneImageLock.lock();
548 if (m_currentSceneImage) {
549 QRect imageRect(QPoint(0, 0), m_currentSceneImage->size());
550 QRect itemRect(QPoint(0, 0), QSize(width(), height()));
551 painter->drawImage(itemRect, *m_currentSceneImage, imageRect);
552 }
553 m_sceneImageLock.unlock();
554 }
597 }
598 QRect renderRect(QPoint(0, 0), chartSize);
599 m_scene->render(&painter, renderRect, renderRect);
600 update();
555 }
601 }
556
602
557 void DeclarativeChart::mousePressEvent(QMouseEvent *event)
603 void DeclarativeChart::mousePressEvent(QMouseEvent *event)
558 {
604 {
559 m_mousePressScenePoint = event->pos();
605 m_mousePressScenePoint = event->pos();
560 m_mousePressScreenPoint = event->globalPos();
606 m_mousePressScreenPoint = event->globalPos();
561 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
607 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
562 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
608 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
563 m_mousePressButton = event->button();
609 m_mousePressButton = event->button();
564 m_mousePressButtons = event->buttons();
610 m_mousePressButtons = event->buttons();
565
611
566 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
612 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
567 mouseEvent.setWidget(0);
613 mouseEvent.setWidget(0);
568 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
614 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
569 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
615 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
570 mouseEvent.setScenePos(m_mousePressScenePoint);
616 mouseEvent.setScenePos(m_mousePressScenePoint);
571 mouseEvent.setScreenPos(m_mousePressScreenPoint);
617 mouseEvent.setScreenPos(m_mousePressScreenPoint);
572 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
618 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
573 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
619 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
574 mouseEvent.setButtons(m_mousePressButtons);
620 mouseEvent.setButtons(m_mousePressButtons);
575 mouseEvent.setButton(m_mousePressButton);
621 mouseEvent.setButton(m_mousePressButton);
576 mouseEvent.setModifiers(event->modifiers());
622 mouseEvent.setModifiers(event->modifiers());
577 mouseEvent.setAccepted(false);
623 mouseEvent.setAccepted(false);
578
624
579 QApplication::sendEvent(m_scene, &mouseEvent);
625 QApplication::sendEvent(m_scene, &mouseEvent);
580 }
626 }
581
627
582 void DeclarativeChart::mouseReleaseEvent(QMouseEvent *event)
628 void DeclarativeChart::mouseReleaseEvent(QMouseEvent *event)
583 {
629 {
584 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
630 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
585 mouseEvent.setWidget(0);
631 mouseEvent.setWidget(0);
586 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
632 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
587 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
633 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
588 mouseEvent.setScenePos(event->pos());
634 mouseEvent.setScenePos(event->pos());
589 mouseEvent.setScreenPos(event->globalPos());
635 mouseEvent.setScreenPos(event->globalPos());
590 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
636 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
591 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
637 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
592 mouseEvent.setButtons(event->buttons());
638 mouseEvent.setButtons(event->buttons());
593 mouseEvent.setButton(event->button());
639 mouseEvent.setButton(event->button());
594 mouseEvent.setModifiers(event->modifiers());
640 mouseEvent.setModifiers(event->modifiers());
595 mouseEvent.setAccepted(false);
641 mouseEvent.setAccepted(false);
596
642
597 QApplication::sendEvent(m_scene, &mouseEvent);
643 QApplication::sendEvent(m_scene, &mouseEvent);
598
644
599 m_mousePressButtons = event->buttons();
645 m_mousePressButtons = event->buttons();
600 m_mousePressButton = Qt::NoButton;
646 m_mousePressButton = Qt::NoButton;
601 }
647 }
602
648
603 void DeclarativeChart::hoverMoveEvent(QHoverEvent *event)
649 void DeclarativeChart::hoverMoveEvent(QHoverEvent *event)
604 {
650 {
605 // Convert hover move to mouse move, since we don't seem to get actual mouse move events.
651 // Convert hover move to mouse move, since we don't seem to get actual mouse move events.
606 // QGraphicsScene generates hover events from mouse move events, so we don't need
652 // QGraphicsScene generates hover events from mouse move events, so we don't need
607 // to pass hover events there.
653 // to pass hover events there.
608 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
654 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
609 mouseEvent.setWidget(0);
655 mouseEvent.setWidget(0);
610 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
656 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
611 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
657 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
612 mouseEvent.setScenePos(event->pos());
658 mouseEvent.setScenePos(event->pos());
613 // Hover events do not have global pos in them, and the screen position doesn't seem to
659 // Hover events do not have global pos in them, and the screen position doesn't seem to
614 // matter anyway in this use case, so just pass event pos instead of trying to
660 // matter anyway in this use case, so just pass event pos instead of trying to
615 // calculate the real screen position.
661 // calculate the real screen position.
616 mouseEvent.setScreenPos(event->pos());
662 mouseEvent.setScreenPos(event->pos());
617 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
663 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
618 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
664 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
619 mouseEvent.setButtons(m_mousePressButtons);
665 mouseEvent.setButtons(m_mousePressButtons);
620 mouseEvent.setButton(m_mousePressButton);
666 mouseEvent.setButton(m_mousePressButton);
621 mouseEvent.setModifiers(event->modifiers());
667 mouseEvent.setModifiers(event->modifiers());
622 m_lastMouseMoveScenePoint = mouseEvent.scenePos();
668 m_lastMouseMoveScenePoint = mouseEvent.scenePos();
623 m_lastMouseMoveScreenPoint = mouseEvent.screenPos();
669 m_lastMouseMoveScreenPoint = mouseEvent.screenPos();
624 mouseEvent.setAccepted(false);
670 mouseEvent.setAccepted(false);
625
671
626 QApplication::sendEvent(m_scene, &mouseEvent);
672 QApplication::sendEvent(m_scene, &mouseEvent);
627 }
673 }
628
674
629 void DeclarativeChart::mouseDoubleClickEvent(QMouseEvent *event)
675 void DeclarativeChart::mouseDoubleClickEvent(QMouseEvent *event)
630 {
676 {
631 m_mousePressScenePoint = event->pos();
677 m_mousePressScenePoint = event->pos();
632 m_mousePressScreenPoint = event->globalPos();
678 m_mousePressScreenPoint = event->globalPos();
633 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
679 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
634 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
680 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
635 m_mousePressButton = event->button();
681 m_mousePressButton = event->button();
636 m_mousePressButtons = event->buttons();
682 m_mousePressButtons = event->buttons();
637
683
638 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseDoubleClick);
684 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseDoubleClick);
639 mouseEvent.setWidget(0);
685 mouseEvent.setWidget(0);
640 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
686 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
641 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
687 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
642 mouseEvent.setScenePos(m_mousePressScenePoint);
688 mouseEvent.setScenePos(m_mousePressScenePoint);
643 mouseEvent.setScreenPos(m_mousePressScreenPoint);
689 mouseEvent.setScreenPos(m_mousePressScreenPoint);
644 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
690 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
645 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
691 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
646 mouseEvent.setButtons(m_mousePressButtons);
692 mouseEvent.setButtons(m_mousePressButtons);
647 mouseEvent.setButton(m_mousePressButton);
693 mouseEvent.setButton(m_mousePressButton);
648 mouseEvent.setModifiers(event->modifiers());
694 mouseEvent.setModifiers(event->modifiers());
649 mouseEvent.setAccepted(false);
695 mouseEvent.setAccepted(false);
650
696
651 QApplication::sendEvent(m_scene, &mouseEvent);
697 QApplication::sendEvent(m_scene, &mouseEvent);
652 }
698 }
653
699
654 void DeclarativeChart::handleAntialiasingChanged(bool enable)
700 void DeclarativeChart::handleAntialiasingChanged(bool enable)
655 {
701 {
656 setAntialiasing(enable);
702 setAntialiasing(enable);
657 }
703 }
658
704
659 void DeclarativeChart::setTheme(DeclarativeChart::Theme theme)
705 void DeclarativeChart::setTheme(DeclarativeChart::Theme theme)
660 {
706 {
661 QChart::ChartTheme chartTheme = (QChart::ChartTheme) theme;
707 QChart::ChartTheme chartTheme = (QChart::ChartTheme) theme;
662 if (chartTheme != m_chart->theme())
708 if (chartTheme != m_chart->theme())
663 m_chart->setTheme(chartTheme);
709 m_chart->setTheme(chartTheme);
664 }
710 }
665
711
666 DeclarativeChart::Theme DeclarativeChart::theme()
712 DeclarativeChart::Theme DeclarativeChart::theme()
667 {
713 {
668 return (DeclarativeChart::Theme) m_chart->theme();
714 return (DeclarativeChart::Theme) m_chart->theme();
669 }
715 }
670
716
671 void DeclarativeChart::setAnimationOptions(DeclarativeChart::Animation animations)
717 void DeclarativeChart::setAnimationOptions(DeclarativeChart::Animation animations)
672 {
718 {
673 QChart::AnimationOption animationOptions = (QChart::AnimationOption) animations;
719 QChart::AnimationOption animationOptions = (QChart::AnimationOption) animations;
674 if (animationOptions != m_chart->animationOptions())
720 if (animationOptions != m_chart->animationOptions())
675 m_chart->setAnimationOptions(animationOptions);
721 m_chart->setAnimationOptions(animationOptions);
676 }
722 }
677
723
678 DeclarativeChart::Animation DeclarativeChart::animationOptions()
724 DeclarativeChart::Animation DeclarativeChart::animationOptions()
679 {
725 {
680 if (m_chart->animationOptions().testFlag(QChart::AllAnimations))
726 if (m_chart->animationOptions().testFlag(QChart::AllAnimations))
681 return DeclarativeChart::AllAnimations;
727 return DeclarativeChart::AllAnimations;
682 else if (m_chart->animationOptions().testFlag(QChart::GridAxisAnimations))
728 else if (m_chart->animationOptions().testFlag(QChart::GridAxisAnimations))
683 return DeclarativeChart::GridAxisAnimations;
729 return DeclarativeChart::GridAxisAnimations;
684 else if (m_chart->animationOptions().testFlag(QChart::SeriesAnimations))
730 else if (m_chart->animationOptions().testFlag(QChart::SeriesAnimations))
685 return DeclarativeChart::SeriesAnimations;
731 return DeclarativeChart::SeriesAnimations;
686 else
732 else
687 return DeclarativeChart::NoAnimation;
733 return DeclarativeChart::NoAnimation;
688 }
734 }
689
735
690 void DeclarativeChart::setAnimationDuration(int msecs)
736 void DeclarativeChart::setAnimationDuration(int msecs)
691 {
737 {
692 if (msecs != m_chart->animationDuration()) {
738 if (msecs != m_chart->animationDuration()) {
693 m_chart->setAnimationDuration(msecs);
739 m_chart->setAnimationDuration(msecs);
694 emit animationDurationChanged(msecs);
740 emit animationDurationChanged(msecs);
695 }
741 }
696 }
742 }
697
743
698 int DeclarativeChart::animationDuration() const
744 int DeclarativeChart::animationDuration() const
699 {
745 {
700 return m_chart->animationDuration();
746 return m_chart->animationDuration();
701 }
747 }
702
748
703 void DeclarativeChart::setAnimationEasingCurve(const QEasingCurve &curve)
749 void DeclarativeChart::setAnimationEasingCurve(const QEasingCurve &curve)
704 {
750 {
705 if (curve != m_chart->animationEasingCurve()) {
751 if (curve != m_chart->animationEasingCurve()) {
706 m_chart->setAnimationEasingCurve(curve);
752 m_chart->setAnimationEasingCurve(curve);
707 emit animationEasingCurveChanged(curve);
753 emit animationEasingCurveChanged(curve);
708 }
754 }
709 }
755 }
710
756
711 QEasingCurve DeclarativeChart::animationEasingCurve() const
757 QEasingCurve DeclarativeChart::animationEasingCurve() const
712 {
758 {
713 return m_chart->animationEasingCurve();
759 return m_chart->animationEasingCurve();
714 }
760 }
715
761
716 void DeclarativeChart::setTitle(QString title)
762 void DeclarativeChart::setTitle(QString title)
717 {
763 {
718 if (title != m_chart->title())
764 if (title != m_chart->title())
719 m_chart->setTitle(title);
765 m_chart->setTitle(title);
720 }
766 }
721 QString DeclarativeChart::title()
767 QString DeclarativeChart::title()
722 {
768 {
723 return m_chart->title();
769 return m_chart->title();
724 }
770 }
725
771
726 QAbstractAxis *DeclarativeChart::axisX(QAbstractSeries *series)
772 QAbstractAxis *DeclarativeChart::axisX(QAbstractSeries *series)
727 {
773 {
728 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Horizontal, series);
774 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Horizontal, series);
729 if (axes.count())
775 if (axes.count())
730 return axes[0];
776 return axes[0];
731 return 0;
777 return 0;
732 }
778 }
733
779
734 QAbstractAxis *DeclarativeChart::axisY(QAbstractSeries *series)
780 QAbstractAxis *DeclarativeChart::axisY(QAbstractSeries *series)
735 {
781 {
736 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Vertical, series);
782 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Vertical, series);
737 if (axes.count())
783 if (axes.count())
738 return axes[0];
784 return axes[0];
739 return 0;
785 return 0;
740 }
786 }
741
787
742 QLegend *DeclarativeChart::legend()
788 QLegend *DeclarativeChart::legend()
743 {
789 {
744 return m_chart->legend();
790 return m_chart->legend();
745 }
791 }
746
792
747 void DeclarativeChart::setTitleColor(QColor color)
793 void DeclarativeChart::setTitleColor(QColor color)
748 {
794 {
749 QBrush b = m_chart->titleBrush();
795 QBrush b = m_chart->titleBrush();
750 if (color != b.color()) {
796 if (color != b.color()) {
751 b.setColor(color);
797 b.setColor(color);
752 m_chart->setTitleBrush(b);
798 m_chart->setTitleBrush(b);
753 emit titleColorChanged(color);
799 emit titleColorChanged(color);
754 }
800 }
755 }
801 }
756
802
757 QFont DeclarativeChart::titleFont() const
803 QFont DeclarativeChart::titleFont() const
758 {
804 {
759 return m_chart->titleFont();
805 return m_chart->titleFont();
760 }
806 }
761
807
762 void DeclarativeChart::setTitleFont(const QFont &font)
808 void DeclarativeChart::setTitleFont(const QFont &font)
763 {
809 {
764 m_chart->setTitleFont(font);
810 m_chart->setTitleFont(font);
765 }
811 }
766
812
767 QColor DeclarativeChart::titleColor()
813 QColor DeclarativeChart::titleColor()
768 {
814 {
769 return m_chart->titleBrush().color();
815 return m_chart->titleBrush().color();
770 }
816 }
771
817
772 void DeclarativeChart::setBackgroundColor(QColor color)
818 void DeclarativeChart::setBackgroundColor(QColor color)
773 {
819 {
774 QBrush b = m_chart->backgroundBrush();
820 QBrush b = m_chart->backgroundBrush();
775 if (b.style() != Qt::SolidPattern || color != b.color()) {
821 if (b.style() != Qt::SolidPattern || color != b.color()) {
776 b.setStyle(Qt::SolidPattern);
822 b.setStyle(Qt::SolidPattern);
777 b.setColor(color);
823 b.setColor(color);
778 m_chart->setBackgroundBrush(b);
824 m_chart->setBackgroundBrush(b);
779 emit backgroundColorChanged();
825 emit backgroundColorChanged();
780 }
826 }
781 }
827 }
782
828
783 QColor DeclarativeChart::backgroundColor()
829 QColor DeclarativeChart::backgroundColor()
784 {
830 {
785 return m_chart->backgroundBrush().color();
831 return m_chart->backgroundBrush().color();
786 }
832 }
787
833
788 void QtCharts::DeclarativeChart::setPlotAreaColor(QColor color)
834 void QtCharts::DeclarativeChart::setPlotAreaColor(QColor color)
789 {
835 {
790 QBrush b = m_chart->plotAreaBackgroundBrush();
836 QBrush b = m_chart->plotAreaBackgroundBrush();
791 if (b.style() != Qt::SolidPattern || color != b.color()) {
837 if (b.style() != Qt::SolidPattern || color != b.color()) {
792 b.setStyle(Qt::SolidPattern);
838 b.setStyle(Qt::SolidPattern);
793 b.setColor(color);
839 b.setColor(color);
794 m_chart->setPlotAreaBackgroundBrush(b);
840 m_chart->setPlotAreaBackgroundBrush(b);
795 m_chart->setPlotAreaBackgroundVisible(true);
841 m_chart->setPlotAreaBackgroundVisible(true);
796 emit plotAreaColorChanged();
842 emit plotAreaColorChanged();
797 }
843 }
798 }
844 }
799
845
800 QColor QtCharts::DeclarativeChart::plotAreaColor()
846 QColor QtCharts::DeclarativeChart::plotAreaColor()
801 {
847 {
802 return m_chart->plotAreaBackgroundBrush().color();
848 return m_chart->plotAreaBackgroundBrush().color();
803 }
849 }
804
850
805 void DeclarativeChart::setLocalizeNumbers(bool localize)
851 void DeclarativeChart::setLocalizeNumbers(bool localize)
806 {
852 {
807 if (m_chart->localizeNumbers() != localize) {
853 if (m_chart->localizeNumbers() != localize) {
808 m_chart->setLocalizeNumbers(localize);
854 m_chart->setLocalizeNumbers(localize);
809 emit localizeNumbersChanged();
855 emit localizeNumbersChanged();
810 }
856 }
811 }
857 }
812
858
813 bool DeclarativeChart::localizeNumbers() const
859 bool DeclarativeChart::localizeNumbers() const
814 {
860 {
815 return m_chart->localizeNumbers();
861 return m_chart->localizeNumbers();
816 }
862 }
817
863
818 void QtCharts::DeclarativeChart::setLocale(const QLocale &locale)
864 void QtCharts::DeclarativeChart::setLocale(const QLocale &locale)
819 {
865 {
820 if (m_chart->locale() != locale) {
866 if (m_chart->locale() != locale) {
821 m_chart->setLocale(locale);
867 m_chart->setLocale(locale);
822 emit localeChanged();
868 emit localeChanged();
823 }
869 }
824 }
870 }
825
871
826 QLocale QtCharts::DeclarativeChart::locale() const
872 QLocale QtCharts::DeclarativeChart::locale() const
827 {
873 {
828 return m_chart->locale();
874 return m_chart->locale();
829 }
875 }
830
876
831 int DeclarativeChart::count()
877 int DeclarativeChart::count()
832 {
878 {
833 return m_chart->series().count();
879 return m_chart->series().count();
834 }
880 }
835
881
836 void DeclarativeChart::setDropShadowEnabled(bool enabled)
882 void DeclarativeChart::setDropShadowEnabled(bool enabled)
837 {
883 {
838 if (enabled != m_chart->isDropShadowEnabled()) {
884 if (enabled != m_chart->isDropShadowEnabled()) {
839 m_chart->setDropShadowEnabled(enabled);
885 m_chart->setDropShadowEnabled(enabled);
840 dropShadowEnabledChanged(enabled);
886 dropShadowEnabledChanged(enabled);
841 }
887 }
842 }
888 }
843
889
844 bool DeclarativeChart::dropShadowEnabled()
890 bool DeclarativeChart::dropShadowEnabled()
845 {
891 {
846 return m_chart->isDropShadowEnabled();
892 return m_chart->isDropShadowEnabled();
847 }
893 }
848
894
849 qreal DeclarativeChart::backgroundRoundness() const
895 qreal DeclarativeChart::backgroundRoundness() const
850 {
896 {
851 return m_chart->backgroundRoundness();
897 return m_chart->backgroundRoundness();
852 }
898 }
853
899
854 void DeclarativeChart::setBackgroundRoundness(qreal diameter)
900 void DeclarativeChart::setBackgroundRoundness(qreal diameter)
855 {
901 {
856 if (m_chart->backgroundRoundness() != diameter) {
902 if (m_chart->backgroundRoundness() != diameter) {
857 m_chart->setBackgroundRoundness(diameter);
903 m_chart->setBackgroundRoundness(diameter);
858 emit backgroundRoundnessChanged(diameter);
904 emit backgroundRoundnessChanged(diameter);
859 }
905 }
860 }
906 }
861
907
862 void DeclarativeChart::zoom(qreal factor)
908 void DeclarativeChart::zoom(qreal factor)
863 {
909 {
864 m_chart->zoom(factor);
910 m_chart->zoom(factor);
865 }
911 }
866
912
867 void DeclarativeChart::zoomIn()
913 void DeclarativeChart::zoomIn()
868 {
914 {
869 m_chart->zoomIn();
915 m_chart->zoomIn();
870 }
916 }
871
917
872 void DeclarativeChart::zoomIn(const QRectF &rectangle)
918 void DeclarativeChart::zoomIn(const QRectF &rectangle)
873 {
919 {
874 m_chart->zoomIn(rectangle);
920 m_chart->zoomIn(rectangle);
875 }
921 }
876
922
877 void DeclarativeChart::zoomOut()
923 void DeclarativeChart::zoomOut()
878 {
924 {
879 m_chart->zoomOut();
925 m_chart->zoomOut();
880 }
926 }
881
927
882 void DeclarativeChart::zoomReset()
928 void DeclarativeChart::zoomReset()
883 {
929 {
884 m_chart->zoomReset();
930 m_chart->zoomReset();
885 }
931 }
886
932
887 bool DeclarativeChart::isZoomed()
933 bool DeclarativeChart::isZoomed()
888 {
934 {
889 return m_chart->isZoomed();
935 return m_chart->isZoomed();
890 }
936 }
891
937
892 void DeclarativeChart::scrollLeft(qreal pixels)
938 void DeclarativeChart::scrollLeft(qreal pixels)
893 {
939 {
894 m_chart->scroll(-pixels, 0);
940 m_chart->scroll(-pixels, 0);
895 }
941 }
896
942
897 void DeclarativeChart::scrollRight(qreal pixels)
943 void DeclarativeChart::scrollRight(qreal pixels)
898 {
944 {
899 m_chart->scroll(pixels, 0);
945 m_chart->scroll(pixels, 0);
900 }
946 }
901
947
902 void DeclarativeChart::scrollUp(qreal pixels)
948 void DeclarativeChart::scrollUp(qreal pixels)
903 {
949 {
904 m_chart->scroll(0, pixels);
950 m_chart->scroll(0, pixels);
905 }
951 }
906
952
907 void DeclarativeChart::scrollDown(qreal pixels)
953 void DeclarativeChart::scrollDown(qreal pixels)
908 {
954 {
909 m_chart->scroll(0, -pixels);
955 m_chart->scroll(0, -pixels);
910 }
956 }
911
957
912 QQmlListProperty<QAbstractAxis> DeclarativeChart::axes()
958 QQmlListProperty<QAbstractAxis> DeclarativeChart::axes()
913 {
959 {
914 return QQmlListProperty<QAbstractAxis>(this, 0,
960 return QQmlListProperty<QAbstractAxis>(this, 0,
915 &DeclarativeChart::axesAppendFunc,
961 &DeclarativeChart::axesAppendFunc,
916 &DeclarativeChart::axesCountFunc,
962 &DeclarativeChart::axesCountFunc,
917 &DeclarativeChart::axesAtFunc,
963 &DeclarativeChart::axesAtFunc,
918 &DeclarativeChart::axesClearFunc);
964 &DeclarativeChart::axesClearFunc);
919 }
965 }
920
966
921 void DeclarativeChart::axesAppendFunc(QQmlListProperty<QAbstractAxis> *list, QAbstractAxis *element)
967 void DeclarativeChart::axesAppendFunc(QQmlListProperty<QAbstractAxis> *list, QAbstractAxis *element)
922 {
968 {
923 // Empty implementation
969 // Empty implementation
924 Q_UNUSED(list);
970 Q_UNUSED(list);
925 Q_UNUSED(element);
971 Q_UNUSED(element);
926 }
972 }
927
973
928 int DeclarativeChart::axesCountFunc(QQmlListProperty<QAbstractAxis> *list)
974 int DeclarativeChart::axesCountFunc(QQmlListProperty<QAbstractAxis> *list)
929 {
975 {
930 if (qobject_cast<DeclarativeChart *>(list->object)) {
976 if (qobject_cast<DeclarativeChart *>(list->object)) {
931 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
977 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
932 return chart->m_chart->axes(Qt::Horizontal | Qt::Vertical).count();
978 return chart->m_chart->axes(Qt::Horizontal | Qt::Vertical).count();
933 }
979 }
934 return 0;
980 return 0;
935 }
981 }
936
982
937 QAbstractAxis *DeclarativeChart::axesAtFunc(QQmlListProperty<QAbstractAxis> *list, int index)
983 QAbstractAxis *DeclarativeChart::axesAtFunc(QQmlListProperty<QAbstractAxis> *list, int index)
938 {
984 {
939 if (qobject_cast<DeclarativeChart *>(list->object)) {
985 if (qobject_cast<DeclarativeChart *>(list->object)) {
940 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
986 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
941 QList<QAbstractAxis *> axes = chart->m_chart->axes(Qt::Horizontal | Qt::Vertical, chart->m_chart->series()[0]);
987 QList<QAbstractAxis *> axes = chart->m_chart->axes(Qt::Horizontal | Qt::Vertical, chart->m_chart->series()[0]);
942 return axes.at(index);
988 return axes.at(index);
943 }
989 }
944 return 0;
990 return 0;
945 }
991 }
946
992
947 void DeclarativeChart::axesClearFunc(QQmlListProperty<QAbstractAxis> *list)
993 void DeclarativeChart::axesClearFunc(QQmlListProperty<QAbstractAxis> *list)
948 {
994 {
949 // Empty implementation
995 // Empty implementation
950 Q_UNUSED(list);
996 Q_UNUSED(list);
951 }
997 }
952
998
953
999
954 QAbstractSeries *DeclarativeChart::series(int index)
1000 QAbstractSeries *DeclarativeChart::series(int index)
955 {
1001 {
956 if (index < m_chart->series().count()) {
1002 if (index < m_chart->series().count()) {
957 return m_chart->series().at(index);
1003 return m_chart->series().at(index);
958 }
1004 }
959 return 0;
1005 return 0;
960 }
1006 }
961
1007
962 QAbstractSeries *DeclarativeChart::series(QString seriesName)
1008 QAbstractSeries *DeclarativeChart::series(QString seriesName)
963 {
1009 {
964 foreach (QAbstractSeries *series, m_chart->series()) {
1010 foreach (QAbstractSeries *series, m_chart->series()) {
965 if (series->name() == seriesName)
1011 if (series->name() == seriesName)
966 return series;
1012 return series;
967 }
1013 }
968 return 0;
1014 return 0;
969 }
1015 }
970
1016
971 QAbstractSeries *DeclarativeChart::createSeries(int type, QString name, QAbstractAxis *axisX, QAbstractAxis *axisY)
1017 QAbstractSeries *DeclarativeChart::createSeries(int type, QString name, QAbstractAxis *axisX, QAbstractAxis *axisY)
972 {
1018 {
973 QAbstractSeries *series = 0;
1019 QAbstractSeries *series = 0;
974
1020
975 switch (type) {
1021 switch (type) {
976 case DeclarativeChart::SeriesTypeLine:
1022 case DeclarativeChart::SeriesTypeLine:
977 series = new DeclarativeLineSeries();
1023 series = new DeclarativeLineSeries();
978 break;
1024 break;
979 case DeclarativeChart::SeriesTypeArea: {
1025 case DeclarativeChart::SeriesTypeArea: {
980 DeclarativeAreaSeries *area = new DeclarativeAreaSeries();
1026 DeclarativeAreaSeries *area = new DeclarativeAreaSeries();
981 DeclarativeLineSeries *line = new DeclarativeLineSeries();
1027 DeclarativeLineSeries *line = new DeclarativeLineSeries();
982 line->setParent(area);
1028 line->setParent(area);
983 area->setUpperSeries(line);
1029 area->setUpperSeries(line);
984 series = area;
1030 series = area;
985 break;
1031 break;
986 }
1032 }
987 case DeclarativeChart::SeriesTypeStackedBar:
1033 case DeclarativeChart::SeriesTypeStackedBar:
988 series = new DeclarativeStackedBarSeries();
1034 series = new DeclarativeStackedBarSeries();
989 break;
1035 break;
990 case DeclarativeChart::SeriesTypePercentBar:
1036 case DeclarativeChart::SeriesTypePercentBar:
991 series = new DeclarativePercentBarSeries();
1037 series = new DeclarativePercentBarSeries();
992 break;
1038 break;
993 case DeclarativeChart::SeriesTypeBar:
1039 case DeclarativeChart::SeriesTypeBar:
994 series = new DeclarativeBarSeries();
1040 series = new DeclarativeBarSeries();
995 break;
1041 break;
996 case DeclarativeChart::SeriesTypeHorizontalBar:
1042 case DeclarativeChart::SeriesTypeHorizontalBar:
997 series = new DeclarativeHorizontalBarSeries();
1043 series = new DeclarativeHorizontalBarSeries();
998 break;
1044 break;
999 case DeclarativeChart::SeriesTypeHorizontalPercentBar:
1045 case DeclarativeChart::SeriesTypeHorizontalPercentBar:
1000 series = new DeclarativeHorizontalPercentBarSeries();
1046 series = new DeclarativeHorizontalPercentBarSeries();
1001 break;
1047 break;
1002 case DeclarativeChart::SeriesTypeHorizontalStackedBar:
1048 case DeclarativeChart::SeriesTypeHorizontalStackedBar:
1003 series = new DeclarativeHorizontalStackedBarSeries();
1049 series = new DeclarativeHorizontalStackedBarSeries();
1004 break;
1050 break;
1005 case DeclarativeChart::SeriesTypeBoxPlot:
1051 case DeclarativeChart::SeriesTypeBoxPlot:
1006 series = new DeclarativeBoxPlotSeries();
1052 series = new DeclarativeBoxPlotSeries();
1007 break;
1053 break;
1008 case DeclarativeChart::SeriesTypePie:
1054 case DeclarativeChart::SeriesTypePie:
1009 series = new DeclarativePieSeries();
1055 series = new DeclarativePieSeries();
1010 break;
1056 break;
1011 case DeclarativeChart::SeriesTypeScatter:
1057 case DeclarativeChart::SeriesTypeScatter:
1012 series = new DeclarativeScatterSeries();
1058 series = new DeclarativeScatterSeries();
1013 break;
1059 break;
1014 case DeclarativeChart::SeriesTypeSpline:
1060 case DeclarativeChart::SeriesTypeSpline:
1015 series = new DeclarativeSplineSeries();
1061 series = new DeclarativeSplineSeries();
1016 break;
1062 break;
1017 default:
1063 default:
1018 qWarning() << "Illegal series type";
1064 qWarning() << "Illegal series type";
1019 }
1065 }
1020
1066
1021 if (series) {
1067 if (series) {
1022 // Connect to axis changed signals (unless this is a pie series)
1068 // Connect to axis changed signals (unless this is a pie series)
1023 if (!qobject_cast<DeclarativePieSeries *>(series)) {
1069 if (!qobject_cast<DeclarativePieSeries *>(series)) {
1024 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1070 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1025 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1071 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1026 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
1072 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
1027 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
1073 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
1028 }
1074 }
1029
1075
1030 series->setName(name);
1076 series->setName(name);
1031 m_chart->addSeries(series);
1077 m_chart->addSeries(series);
1032
1078
1033 if (!axisX || !axisY)
1079 if (!axisX || !axisY)
1034 initializeAxes(series);
1080 initializeAxes(series);
1035
1081
1036 if (axisX)
1082 if (axisX)
1037 setAxisX(axisX, series);
1083 setAxisX(axisX, series);
1038 if (axisY)
1084 if (axisY)
1039 setAxisY(axisY, series);
1085 setAxisY(axisY, series);
1040 }
1086 }
1041
1087
1042 return series;
1088 return series;
1043 }
1089 }
1044
1090
1045 void DeclarativeChart::removeSeries(QAbstractSeries *series)
1091 void DeclarativeChart::removeSeries(QAbstractSeries *series)
1046 {
1092 {
1047 if (series)
1093 if (series)
1048 m_chart->removeSeries(series);
1094 m_chart->removeSeries(series);
1049 else
1095 else
1050 qWarning("removeSeries: cannot remove null");
1096 qWarning("removeSeries: cannot remove null");
1051 }
1097 }
1052
1098
1053 void DeclarativeChart::setAxisX(QAbstractAxis *axis, QAbstractSeries *series)
1099 void DeclarativeChart::setAxisX(QAbstractAxis *axis, QAbstractSeries *series)
1054 {
1100 {
1055 if (axis && series)
1101 if (axis && series)
1056 seriesAxisAttachHelper(series, axis, Qt::Horizontal, Qt::AlignBottom);
1102 seriesAxisAttachHelper(series, axis, Qt::Horizontal, Qt::AlignBottom);
1057 }
1103 }
1058
1104
1059 void DeclarativeChart::setAxisY(QAbstractAxis *axis, QAbstractSeries *series)
1105 void DeclarativeChart::setAxisY(QAbstractAxis *axis, QAbstractSeries *series)
1060 {
1106 {
1061 if (axis && series)
1107 if (axis && series)
1062 seriesAxisAttachHelper(series, axis, Qt::Vertical, Qt::AlignLeft);
1108 seriesAxisAttachHelper(series, axis, Qt::Vertical, Qt::AlignLeft);
1063 }
1109 }
1064
1110
1065 QAbstractAxis *DeclarativeChart::defaultAxis(Qt::Orientation orientation, QAbstractSeries *series)
1111 QAbstractAxis *DeclarativeChart::defaultAxis(Qt::Orientation orientation, QAbstractSeries *series)
1066 {
1112 {
1067 if (!series) {
1113 if (!series) {
1068 qWarning() << "No axis type defined for null series";
1114 qWarning() << "No axis type defined for null series";
1069 return 0;
1115 return 0;
1070 }
1116 }
1071
1117
1072 foreach (QAbstractAxis *existingAxis, m_chart->axes(orientation)) {
1118 foreach (QAbstractAxis *existingAxis, m_chart->axes(orientation)) {
1073 if (existingAxis->type() == series->d_ptr->defaultAxisType(orientation))
1119 if (existingAxis->type() == series->d_ptr->defaultAxisType(orientation))
1074 return existingAxis;
1120 return existingAxis;
1075 }
1121 }
1076
1122
1077 switch (series->d_ptr->defaultAxisType(orientation)) {
1123 switch (series->d_ptr->defaultAxisType(orientation)) {
1078 case QAbstractAxis::AxisTypeValue:
1124 case QAbstractAxis::AxisTypeValue:
1079 return new QValueAxis(this);
1125 return new QValueAxis(this);
1080 case QAbstractAxis::AxisTypeBarCategory:
1126 case QAbstractAxis::AxisTypeBarCategory:
1081 return new QBarCategoryAxis(this);
1127 return new QBarCategoryAxis(this);
1082 case QAbstractAxis::AxisTypeCategory:
1128 case QAbstractAxis::AxisTypeCategory:
1083 return new QCategoryAxis(this);
1129 return new QCategoryAxis(this);
1084 #ifndef QT_ON_ARM
1130 #ifndef QT_ON_ARM
1085 case QAbstractAxis::AxisTypeDateTime:
1131 case QAbstractAxis::AxisTypeDateTime:
1086 return new QDateTimeAxis(this);
1132 return new QDateTimeAxis(this);
1087 #endif
1133 #endif
1088 case QAbstractAxis::AxisTypeLogValue:
1134 case QAbstractAxis::AxisTypeLogValue:
1089 return new QLogValueAxis(this);
1135 return new QLogValueAxis(this);
1090 default:
1136 default:
1091 // assume AxisTypeNoAxis
1137 // assume AxisTypeNoAxis
1092 return 0;
1138 return 0;
1093 }
1139 }
1094 }
1140 }
1095
1141
1096 void DeclarativeChart::initializeAxes(QAbstractSeries *series)
1142 void DeclarativeChart::initializeAxes(QAbstractSeries *series)
1097 {
1143 {
1098 if (qobject_cast<DeclarativeLineSeries *>(series))
1144 if (qobject_cast<DeclarativeLineSeries *>(series))
1099 doInitializeAxes(series, qobject_cast<DeclarativeLineSeries *>(series)->m_axes);
1145 doInitializeAxes(series, qobject_cast<DeclarativeLineSeries *>(series)->m_axes);
1100 else if (qobject_cast<DeclarativeScatterSeries *>(series))
1146 else if (qobject_cast<DeclarativeScatterSeries *>(series))
1101 doInitializeAxes(series, qobject_cast<DeclarativeScatterSeries *>(series)->m_axes);
1147 doInitializeAxes(series, qobject_cast<DeclarativeScatterSeries *>(series)->m_axes);
1102 else if (qobject_cast<DeclarativeSplineSeries *>(series))
1148 else if (qobject_cast<DeclarativeSplineSeries *>(series))
1103 doInitializeAxes(series, qobject_cast<DeclarativeSplineSeries *>(series)->m_axes);
1149 doInitializeAxes(series, qobject_cast<DeclarativeSplineSeries *>(series)->m_axes);
1104 else if (qobject_cast<DeclarativeAreaSeries *>(series))
1150 else if (qobject_cast<DeclarativeAreaSeries *>(series))
1105 doInitializeAxes(series, qobject_cast<DeclarativeAreaSeries *>(series)->m_axes);
1151 doInitializeAxes(series, qobject_cast<DeclarativeAreaSeries *>(series)->m_axes);
1106 else if (qobject_cast<DeclarativeBarSeries *>(series))
1152 else if (qobject_cast<DeclarativeBarSeries *>(series))
1107 doInitializeAxes(series, qobject_cast<DeclarativeBarSeries *>(series)->m_axes);
1153 doInitializeAxes(series, qobject_cast<DeclarativeBarSeries *>(series)->m_axes);
1108 else if (qobject_cast<DeclarativeStackedBarSeries *>(series))
1154 else if (qobject_cast<DeclarativeStackedBarSeries *>(series))
1109 doInitializeAxes(series, qobject_cast<DeclarativeStackedBarSeries *>(series)->m_axes);
1155 doInitializeAxes(series, qobject_cast<DeclarativeStackedBarSeries *>(series)->m_axes);
1110 else if (qobject_cast<DeclarativePercentBarSeries *>(series))
1156 else if (qobject_cast<DeclarativePercentBarSeries *>(series))
1111 doInitializeAxes(series, qobject_cast<DeclarativePercentBarSeries *>(series)->m_axes);
1157 doInitializeAxes(series, qobject_cast<DeclarativePercentBarSeries *>(series)->m_axes);
1112 else if (qobject_cast<DeclarativeHorizontalBarSeries *>(series))
1158 else if (qobject_cast<DeclarativeHorizontalBarSeries *>(series))
1113 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalBarSeries *>(series)->m_axes);
1159 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalBarSeries *>(series)->m_axes);
1114 else if (qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series))
1160 else if (qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series))
1115 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series)->m_axes);
1161 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series)->m_axes);
1116 else if (qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series))
1162 else if (qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series))
1117 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series)->m_axes);
1163 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series)->m_axes);
1118 else if (qobject_cast<DeclarativeBoxPlotSeries *>(series))
1164 else if (qobject_cast<DeclarativeBoxPlotSeries *>(series))
1119 doInitializeAxes(series, qobject_cast<DeclarativeBoxPlotSeries *>(series)->m_axes);
1165 doInitializeAxes(series, qobject_cast<DeclarativeBoxPlotSeries *>(series)->m_axes);
1120 // else: do nothing
1166 // else: do nothing
1121 }
1167 }
1122
1168
1123 void DeclarativeChart::doInitializeAxes(QAbstractSeries *series, DeclarativeAxes *axes)
1169 void DeclarativeChart::doInitializeAxes(QAbstractSeries *series, DeclarativeAxes *axes)
1124 {
1170 {
1125 qreal min;
1171 qreal min;
1126 qreal max;
1172 qreal max;
1127 // Initialize axis X
1173 // Initialize axis X
1128 if (axes->axisX()) {
1174 if (axes->axisX()) {
1129 axes->emitAxisXChanged();
1175 axes->emitAxisXChanged();
1130 } else if (axes->axisXTop()) {
1176 } else if (axes->axisXTop()) {
1131 axes->emitAxisXTopChanged();
1177 axes->emitAxisXTopChanged();
1132 } else {
1178 } else {
1133 axes->setAxisX(defaultAxis(Qt::Horizontal, series));
1179 axes->setAxisX(defaultAxis(Qt::Horizontal, series));
1134 findMinMaxForSeries(series, Qt::Horizontal, min, max);
1180 findMinMaxForSeries(series, Qt::Horizontal, min, max);
1135 axes->axisX()->setRange(min, max);
1181 axes->axisX()->setRange(min, max);
1136 }
1182 }
1137
1183
1138 // Initialize axis Y
1184 // Initialize axis Y
1139 if (axes->axisY()) {
1185 if (axes->axisY()) {
1140 axes->emitAxisYChanged();
1186 axes->emitAxisYChanged();
1141 } else if (axes->axisYRight()) {
1187 } else if (axes->axisYRight()) {
1142 axes->emitAxisYRightChanged();
1188 axes->emitAxisYRightChanged();
1143 } else {
1189 } else {
1144 axes->setAxisY(defaultAxis(Qt::Vertical, series));
1190 axes->setAxisY(defaultAxis(Qt::Vertical, series));
1145 findMinMaxForSeries(series, Qt::Vertical, min, max);
1191 findMinMaxForSeries(series, Qt::Vertical, min, max);
1146 axes->axisY()->setRange(min, max);
1192 axes->axisY()->setRange(min, max);
1147 }
1193 }
1148 }
1194 }
1149
1195
1150 void DeclarativeChart::findMinMaxForSeries(QAbstractSeries *series, Qt::Orientations orientation,
1196 void DeclarativeChart::findMinMaxForSeries(QAbstractSeries *series, Qt::Orientations orientation,
1151 qreal &min, qreal &max)
1197 qreal &min, qreal &max)
1152 {
1198 {
1153 if (!series) {
1199 if (!series) {
1154 min = 0.5;
1200 min = 0.5;
1155 max = 0.5;
1201 max = 0.5;
1156 } else {
1202 } else {
1157 AbstractDomain *domain = series->d_ptr->domain();
1203 AbstractDomain *domain = series->d_ptr->domain();
1158 min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
1204 min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
1159 max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
1205 max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
1160
1206
1161 if (min == max) {
1207 if (min == max) {
1162 min -= 0.5;
1208 min -= 0.5;
1163 max += 0.5;
1209 max += 0.5;
1164 }
1210 }
1165 }
1211 }
1166 }
1212 }
1167
1213
1168 QPointF DeclarativeChart::mapToValue(const QPointF &position, QAbstractSeries *series)
1214 QPointF DeclarativeChart::mapToValue(const QPointF &position, QAbstractSeries *series)
1169 {
1215 {
1170 return m_chart->mapToValue(position, series);
1216 return m_chart->mapToValue(position, series);
1171 }
1217 }
1172
1218
1173 QPointF DeclarativeChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
1219 QPointF DeclarativeChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
1174 {
1220 {
1175 return m_chart->mapToPosition(value, series);
1221 return m_chart->mapToPosition(value, series);
1176 }
1222 }
1177
1223
1178 #include "moc_declarativechart.cpp"
1224 #include "moc_declarativechart.cpp"
1179
1225
1180 QT_CHARTS_END_NAMESPACE
1226 QT_CHARTS_END_NAMESPACE
@@ -1,240 +1,242
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #ifndef DECLARATIVECHART_H
19 #ifndef DECLARATIVECHART_H
20 #define DECLARATIVECHART_H
20 #define DECLARATIVECHART_H
21
21
22 #include <private/glxyseriesdata_p.h>
23
22 #include <QtCore/QtGlobal>
24 #include <QtCore/QtGlobal>
23 #include <QtQuick/QQuickItem>
25 #include <QtQuick/QQuickItem>
24 #include <QtQuick/QQuickPaintedItem>
25 #include <QtWidgets/QGraphicsScene>
26 #include <QtWidgets/QGraphicsScene>
26 #include <QtCore/QMutex>
27
27
28 #include <QtCharts/QChart>
28 #include <QtCharts/QChart>
29 #include <QtCore/QLocale>
29 #include <QtCore/QLocale>
30
30
31 QT_CHARTS_BEGIN_NAMESPACE
31 QT_CHARTS_BEGIN_NAMESPACE
32
32
33 class DeclarativeMargins;
33 class DeclarativeMargins;
34 class Domain;
34 class Domain;
35 class DeclarativeAxes;
35 class DeclarativeAxes;
36
36
37 class DeclarativeChart : public QQuickPaintedItem
37 class DeclarativeChart : public QQuickItem
38 {
38 {
39 Q_OBJECT
39 Q_OBJECT
40 Q_PROPERTY(Theme theme READ theme WRITE setTheme)
40 Q_PROPERTY(Theme theme READ theme WRITE setTheme)
41 Q_PROPERTY(Animation animationOptions READ animationOptions WRITE setAnimationOptions)
41 Q_PROPERTY(Animation animationOptions READ animationOptions WRITE setAnimationOptions)
42 Q_PROPERTY(int animationDuration READ animationDuration WRITE setAnimationDuration NOTIFY animationDurationChanged REVISION 5)
42 Q_PROPERTY(int animationDuration READ animationDuration WRITE setAnimationDuration NOTIFY animationDurationChanged REVISION 5)
43 Q_PROPERTY(QEasingCurve animationEasingCurve READ animationEasingCurve WRITE setAnimationEasingCurve NOTIFY animationEasingCurveChanged REVISION 5)
43 Q_PROPERTY(QEasingCurve animationEasingCurve READ animationEasingCurve WRITE setAnimationEasingCurve NOTIFY animationEasingCurveChanged REVISION 5)
44 Q_PROPERTY(QString title READ title WRITE setTitle)
44 Q_PROPERTY(QString title READ title WRITE setTitle)
45 Q_PROPERTY(QFont titleFont READ titleFont WRITE setTitleFont)
45 Q_PROPERTY(QFont titleFont READ titleFont WRITE setTitleFont)
46 Q_PROPERTY(QColor titleColor READ titleColor WRITE setTitleColor NOTIFY titleColorChanged)
46 Q_PROPERTY(QColor titleColor READ titleColor WRITE setTitleColor NOTIFY titleColorChanged)
47 Q_PROPERTY(QLegend *legend READ legend CONSTANT)
47 Q_PROPERTY(QLegend *legend READ legend CONSTANT)
48 Q_PROPERTY(int count READ count)
48 Q_PROPERTY(int count READ count)
49 Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged)
49 Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged)
50 Q_PROPERTY(bool dropShadowEnabled READ dropShadowEnabled WRITE setDropShadowEnabled NOTIFY dropShadowEnabledChanged)
50 Q_PROPERTY(bool dropShadowEnabled READ dropShadowEnabled WRITE setDropShadowEnabled NOTIFY dropShadowEnabledChanged)
51 Q_PROPERTY(qreal backgroundRoundness READ backgroundRoundness WRITE setBackgroundRoundness NOTIFY backgroundRoundnessChanged REVISION 3)
51 Q_PROPERTY(qreal backgroundRoundness READ backgroundRoundness WRITE setBackgroundRoundness NOTIFY backgroundRoundnessChanged REVISION 3)
52 Q_PROPERTY(DeclarativeMargins *margins READ margins NOTIFY marginsChanged REVISION 2)
52 Q_PROPERTY(DeclarativeMargins *margins READ margins NOTIFY marginsChanged REVISION 2)
53 Q_PROPERTY(QRectF plotArea READ plotArea NOTIFY plotAreaChanged REVISION 1)
53 Q_PROPERTY(QRectF plotArea READ plotArea NOTIFY plotAreaChanged REVISION 1)
54 Q_PROPERTY(QColor plotAreaColor READ plotAreaColor WRITE setPlotAreaColor NOTIFY plotAreaColorChanged REVISION 3)
54 Q_PROPERTY(QColor plotAreaColor READ plotAreaColor WRITE setPlotAreaColor NOTIFY plotAreaColorChanged REVISION 3)
55 Q_PROPERTY(QQmlListProperty<QAbstractAxis> axes READ axes REVISION 2)
55 Q_PROPERTY(QQmlListProperty<QAbstractAxis> axes READ axes REVISION 2)
56 Q_PROPERTY(bool localizeNumbers READ localizeNumbers WRITE setLocalizeNumbers NOTIFY localizeNumbersChanged REVISION 4)
56 Q_PROPERTY(bool localizeNumbers READ localizeNumbers WRITE setLocalizeNumbers NOTIFY localizeNumbersChanged REVISION 4)
57 Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged REVISION 4)
57 Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged REVISION 4)
58 Q_ENUMS(Animation)
58 Q_ENUMS(Animation)
59 Q_ENUMS(Theme)
59 Q_ENUMS(Theme)
60 Q_ENUMS(SeriesType)
60 Q_ENUMS(SeriesType)
61
61
62 public:
62 public:
63 // duplicating enums from QChart to make the QML api namings 1-to-1 with the C++ api
63 // duplicating enums from QChart to make the QML api namings 1-to-1 with the C++ api
64 enum Theme {
64 enum Theme {
65 ChartThemeLight = 0,
65 ChartThemeLight = 0,
66 ChartThemeBlueCerulean,
66 ChartThemeBlueCerulean,
67 ChartThemeDark,
67 ChartThemeDark,
68 ChartThemeBrownSand,
68 ChartThemeBrownSand,
69 ChartThemeBlueNcs,
69 ChartThemeBlueNcs,
70 ChartThemeHighContrast,
70 ChartThemeHighContrast,
71 ChartThemeBlueIcy,
71 ChartThemeBlueIcy,
72 ChartThemeQt
72 ChartThemeQt
73 };
73 };
74
74
75 enum Animation {
75 enum Animation {
76 NoAnimation = 0x0,
76 NoAnimation = 0x0,
77 GridAxisAnimations = 0x1,
77 GridAxisAnimations = 0x1,
78 SeriesAnimations = 0x2,
78 SeriesAnimations = 0x2,
79 AllAnimations = 0x3
79 AllAnimations = 0x3
80 };
80 };
81
81
82 enum SeriesType {
82 enum SeriesType {
83 SeriesTypeLine,
83 SeriesTypeLine,
84 SeriesTypeArea,
84 SeriesTypeArea,
85 SeriesTypeBar,
85 SeriesTypeBar,
86 SeriesTypeStackedBar,
86 SeriesTypeStackedBar,
87 SeriesTypePercentBar,
87 SeriesTypePercentBar,
88 SeriesTypeBoxPlot,
88 SeriesTypeBoxPlot,
89 SeriesTypePie,
89 SeriesTypePie,
90 SeriesTypeScatter,
90 SeriesTypeScatter,
91 SeriesTypeSpline,
91 SeriesTypeSpline,
92 SeriesTypeHorizontalBar,
92 SeriesTypeHorizontalBar,
93 SeriesTypeHorizontalStackedBar,
93 SeriesTypeHorizontalStackedBar,
94 SeriesTypeHorizontalPercentBar
94 SeriesTypeHorizontalPercentBar
95 };
95 };
96
96
97 public:
97 public:
98 DeclarativeChart(QQuickItem *parent = 0);
98 DeclarativeChart(QQuickItem *parent = 0);
99 ~DeclarativeChart();
99 ~DeclarativeChart();
100
100
101 public: // From parent classes
101 public: // From parent classes
102 void childEvent(QChildEvent *event);
102 void childEvent(QChildEvent *event);
103 void componentComplete();
103 void componentComplete();
104 void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
104 void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
105 void paint(QPainter *painter);
105 QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
106 protected:
106 protected:
107 void mousePressEvent(QMouseEvent *event);
107 void mousePressEvent(QMouseEvent *event);
108 void mouseReleaseEvent(QMouseEvent *event);
108 void mouseReleaseEvent(QMouseEvent *event);
109 void hoverMoveEvent(QHoverEvent *event);
109 void hoverMoveEvent(QHoverEvent *event);
110 void mouseDoubleClickEvent(QMouseEvent *event);
110 void mouseDoubleClickEvent(QMouseEvent *event);
111 private Q_SLOTS:
111 private Q_SLOTS:
112 void handleAntialiasingChanged(bool enable);
112 void handleAntialiasingChanged(bool enable);
113 void sceneChanged(QList<QRectF> region);
113 void sceneChanged(QList<QRectF> region);
114 void renderScene();
114 void renderScene();
115
115
116 public:
116 public:
117 void setTheme(DeclarativeChart::Theme theme);
117 void setTheme(DeclarativeChart::Theme theme);
118 DeclarativeChart::Theme theme();
118 DeclarativeChart::Theme theme();
119 void setAnimationOptions(DeclarativeChart::Animation animations);
119 void setAnimationOptions(DeclarativeChart::Animation animations);
120 DeclarativeChart::Animation animationOptions();
120 DeclarativeChart::Animation animationOptions();
121 void setAnimationDuration(int msecs);
121 void setAnimationDuration(int msecs);
122 int animationDuration() const;
122 int animationDuration() const;
123 void setAnimationEasingCurve(const QEasingCurve &curve);
123 void setAnimationEasingCurve(const QEasingCurve &curve);
124 QEasingCurve animationEasingCurve() const;
124 QEasingCurve animationEasingCurve() const;
125 void setTitle(QString title);
125 void setTitle(QString title);
126 QString title();
126 QString title();
127 QLegend *legend();
127 QLegend *legend();
128 QFont titleFont() const;
128 QFont titleFont() const;
129 void setTitleFont(const QFont &font);
129 void setTitleFont(const QFont &font);
130 void setTitleColor(QColor color);
130 void setTitleColor(QColor color);
131 QColor titleColor();
131 QColor titleColor();
132 void setBackgroundColor(QColor color);
132 void setBackgroundColor(QColor color);
133 QColor backgroundColor();
133 QColor backgroundColor();
134 void setPlotAreaColor(QColor color);
134 void setPlotAreaColor(QColor color);
135 QColor plotAreaColor();
135 QColor plotAreaColor();
136 void setLocalizeNumbers(bool localize);
136 void setLocalizeNumbers(bool localize);
137 bool localizeNumbers() const;
137 bool localizeNumbers() const;
138 void setLocale(const QLocale &locale);
138 void setLocale(const QLocale &locale);
139 QLocale locale() const;
139 QLocale locale() const;
140
140
141 int count();
141 int count();
142 void setDropShadowEnabled(bool enabled);
142 void setDropShadowEnabled(bool enabled);
143 bool dropShadowEnabled();
143 bool dropShadowEnabled();
144 qreal backgroundRoundness() const;
144 qreal backgroundRoundness() const;
145 void setBackgroundRoundness(qreal diameter);
145 void setBackgroundRoundness(qreal diameter);
146
146
147 // Margins & plotArea
147 // Margins & plotArea
148 DeclarativeMargins *margins() { return m_margins; }
148 DeclarativeMargins *margins() { return m_margins; }
149 QRectF plotArea() { return m_chart->plotArea(); }
149 QRectF plotArea() { return m_chart->plotArea(); }
150
150
151 // Axis handling
151 // Axis handling
152 QAbstractAxis *defaultAxis(Qt::Orientation orientation, QAbstractSeries *series);
152 QAbstractAxis *defaultAxis(Qt::Orientation orientation, QAbstractSeries *series);
153 void initializeAxes(QAbstractSeries *series);
153 void initializeAxes(QAbstractSeries *series);
154 void doInitializeAxes(QAbstractSeries *series, DeclarativeAxes *axes);
154 void doInitializeAxes(QAbstractSeries *series, DeclarativeAxes *axes);
155 QQmlListProperty<QAbstractAxis> axes();
155 QQmlListProperty<QAbstractAxis> axes();
156 static void axesAppendFunc(QQmlListProperty<QAbstractAxis> *list, QAbstractAxis *element);
156 static void axesAppendFunc(QQmlListProperty<QAbstractAxis> *list, QAbstractAxis *element);
157 static int axesCountFunc(QQmlListProperty<QAbstractAxis> *list);
157 static int axesCountFunc(QQmlListProperty<QAbstractAxis> *list);
158 static QAbstractAxis *axesAtFunc(QQmlListProperty<QAbstractAxis> *list, int index);
158 static QAbstractAxis *axesAtFunc(QQmlListProperty<QAbstractAxis> *list, int index);
159 static void axesClearFunc(QQmlListProperty<QAbstractAxis> *list);
159 static void axesClearFunc(QQmlListProperty<QAbstractAxis> *list);
160
160
161 public:
161 public:
162 Q_INVOKABLE QAbstractSeries *series(int index);
162 Q_INVOKABLE QAbstractSeries *series(int index);
163 Q_INVOKABLE QAbstractSeries *series(QString seriesName);
163 Q_INVOKABLE QAbstractSeries *series(QString seriesName);
164 Q_INVOKABLE QAbstractSeries *createSeries(int type, QString name = "", QAbstractAxis *axisX = 0, QAbstractAxis *axisY = 0);
164 Q_INVOKABLE QAbstractSeries *createSeries(int type, QString name = "", QAbstractAxis *axisX = 0, QAbstractAxis *axisY = 0);
165 Q_INVOKABLE void removeSeries(QAbstractSeries *series);
165 Q_INVOKABLE void removeSeries(QAbstractSeries *series);
166 Q_INVOKABLE void removeAllSeries() { m_chart->removeAllSeries(); }
166 Q_INVOKABLE void removeAllSeries() { m_chart->removeAllSeries(); }
167 Q_INVOKABLE void setAxisX(QAbstractAxis *axis, QAbstractSeries *series = 0);
167 Q_INVOKABLE void setAxisX(QAbstractAxis *axis, QAbstractSeries *series = 0);
168 Q_INVOKABLE void setAxisY(QAbstractAxis *axis, QAbstractSeries *series = 0);
168 Q_INVOKABLE void setAxisY(QAbstractAxis *axis, QAbstractSeries *series = 0);
169 Q_INVOKABLE QAbstractAxis *axisX(QAbstractSeries *series = 0);
169 Q_INVOKABLE QAbstractAxis *axisX(QAbstractSeries *series = 0);
170 Q_INVOKABLE QAbstractAxis *axisY(QAbstractSeries *series = 0);
170 Q_INVOKABLE QAbstractAxis *axisY(QAbstractSeries *series = 0);
171 Q_INVOKABLE void zoom(qreal factor);
171 Q_INVOKABLE void zoom(qreal factor);
172 Q_REVISION(5) Q_INVOKABLE void zoomIn();
172 Q_REVISION(5) Q_INVOKABLE void zoomIn();
173 Q_REVISION(5) Q_INVOKABLE void zoomIn(const QRectF &rectangle);
173 Q_REVISION(5) Q_INVOKABLE void zoomIn(const QRectF &rectangle);
174 Q_REVISION(5) Q_INVOKABLE void zoomOut();
174 Q_REVISION(5) Q_INVOKABLE void zoomOut();
175 Q_REVISION(5) Q_INVOKABLE void zoomReset();
175 Q_REVISION(5) Q_INVOKABLE void zoomReset();
176 Q_REVISION(5) Q_INVOKABLE bool isZoomed();
176 Q_REVISION(5) Q_INVOKABLE bool isZoomed();
177 Q_INVOKABLE void scrollLeft(qreal pixels);
177 Q_INVOKABLE void scrollLeft(qreal pixels);
178 Q_INVOKABLE void scrollRight(qreal pixels);
178 Q_INVOKABLE void scrollRight(qreal pixels);
179 Q_INVOKABLE void scrollUp(qreal pixels);
179 Q_INVOKABLE void scrollUp(qreal pixels);
180 Q_INVOKABLE void scrollDown(qreal pixels);
180 Q_INVOKABLE void scrollDown(qreal pixels);
181 Q_REVISION(5) Q_INVOKABLE QPointF mapToValue(const QPointF &position,
181 Q_REVISION(5) Q_INVOKABLE QPointF mapToValue(const QPointF &position,
182 QAbstractSeries *series = 0);
182 QAbstractSeries *series = 0);
183 Q_REVISION(5) Q_INVOKABLE QPointF mapToPosition(const QPointF &value,
183 Q_REVISION(5) Q_INVOKABLE QPointF mapToPosition(const QPointF &value,
184 QAbstractSeries *series = 0);
184 QAbstractSeries *series = 0);
185
185
186
186
187 Q_SIGNALS:
187 Q_SIGNALS:
188 void axisLabelsChanged();
188 void axisLabelsChanged();
189 void titleColorChanged(QColor color);
189 void titleColorChanged(QColor color);
190 void backgroundColorChanged();
190 void backgroundColorChanged();
191 void dropShadowEnabledChanged(bool enabled);
191 void dropShadowEnabledChanged(bool enabled);
192 Q_REVISION(2) void marginsChanged();
192 Q_REVISION(2) void marginsChanged();
193 void plotAreaChanged(QRectF plotArea);
193 void plotAreaChanged(QRectF plotArea);
194 void seriesAdded(QAbstractSeries *series);
194 void seriesAdded(QAbstractSeries *series);
195 void seriesRemoved(QAbstractSeries *series);
195 void seriesRemoved(QAbstractSeries *series);
196 Q_REVISION(3) void plotAreaColorChanged();
196 Q_REVISION(3) void plotAreaColorChanged();
197 Q_REVISION(3) void backgroundRoundnessChanged(qreal diameter);
197 Q_REVISION(3) void backgroundRoundnessChanged(qreal diameter);
198 Q_REVISION(4) void localizeNumbersChanged();
198 Q_REVISION(4) void localizeNumbersChanged();
199 Q_REVISION(4) void localeChanged();
199 Q_REVISION(4) void localeChanged();
200 Q_REVISION(5) void animationDurationChanged(int msecs);
200 Q_REVISION(5) void animationDurationChanged(int msecs);
201 Q_REVISION(5) void animationEasingCurveChanged(QEasingCurve curve);
201 Q_REVISION(5) void animationEasingCurveChanged(QEasingCurve curve);
202 void needRender();
202
203
203 private Q_SLOTS:
204 private Q_SLOTS:
204 void changeMargins(int top, int bottom, int left, int right);
205 void changeMargins(int top, int bottom, int left, int right);
205 void handleAxisXSet(QAbstractAxis *axis);
206 void handleAxisXSet(QAbstractAxis *axis);
206 void handleAxisYSet(QAbstractAxis *axis);
207 void handleAxisYSet(QAbstractAxis *axis);
207 void handleAxisXTopSet(QAbstractAxis *axis);
208 void handleAxisXTopSet(QAbstractAxis *axis);
208 void handleAxisYRightSet(QAbstractAxis *axis);
209 void handleAxisYRightSet(QAbstractAxis *axis);
209 void handleSeriesAdded(QAbstractSeries *series);
210 void handleSeriesAdded(QAbstractSeries *series);
210
211
211 protected:
212 protected:
212 explicit DeclarativeChart(QChart::ChartType type, QQuickItem *parent);
213 explicit DeclarativeChart(QChart::ChartType type, QQuickItem *parent);
213
214
214 private:
215 private:
215 void initChart(QChart::ChartType type);
216 void initChart(QChart::ChartType type);
216 void seriesAxisAttachHelper(QAbstractSeries *series, QAbstractAxis *axis,
217 void seriesAxisAttachHelper(QAbstractSeries *series, QAbstractAxis *axis,
217 Qt::Orientations orientation, Qt::Alignment alignment);
218 Qt::Orientations orientation, Qt::Alignment alignment);
218 void findMinMaxForSeries(QAbstractSeries *series,Qt::Orientations orientation,
219 void findMinMaxForSeries(QAbstractSeries *series,Qt::Orientations orientation,
219 qreal &min, qreal &max);
220 qreal &min, qreal &max);
220 // Extending QChart with DeclarativeChart is not possible because QObject does not support
221 // Extending QChart with DeclarativeChart is not possible because QObject does not support
221 // multi inheritance, so we now have a QChart as a member instead
222 // multi inheritance, so we now have a QChart as a member instead
222 QChart *m_chart;
223 QChart *m_chart;
223 QGraphicsScene *m_scene;
224 QGraphicsScene *m_scene;
224 QPointF m_mousePressScenePoint;
225 QPointF m_mousePressScenePoint;
225 QPoint m_mousePressScreenPoint;
226 QPoint m_mousePressScreenPoint;
226 QPointF m_lastMouseMoveScenePoint;
227 QPointF m_lastMouseMoveScenePoint;
227 QPoint m_lastMouseMoveScreenPoint;
228 QPoint m_lastMouseMoveScreenPoint;
228 Qt::MouseButton m_mousePressButton;
229 Qt::MouseButton m_mousePressButton;
229 Qt::MouseButtons m_mousePressButtons;
230 Qt::MouseButtons m_mousePressButtons;
230 QMutex m_sceneImageLock;
231 QImage *m_sceneImage;
231 QImage *m_currentSceneImage;
232 bool m_sceneImageDirty;
232 bool m_updatePending;
233 bool m_updatePending;
233 Qt::HANDLE m_paintThreadId;
234 Qt::HANDLE m_paintThreadId;
234 Qt::HANDLE m_guiThreadId;
235 Qt::HANDLE m_guiThreadId;
235 DeclarativeMargins *m_margins;
236 DeclarativeMargins *m_margins;
237 GLXYSeriesDataManager *m_glXYDataManager;
236 };
238 };
237
239
238 QT_CHARTS_END_NAMESPACE
240 QT_CHARTS_END_NAMESPACE
239
241
240 #endif // DECLARATIVECHART_H
242 #endif // DECLARATIVECHART_H
@@ -1,228 +1,229
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include "../qxyseries/tst_qxyseries.h"
19 #include "../qxyseries/tst_qxyseries.h"
20 #include <QtCharts/QLineSeries>
20 #include <QtCharts/QLineSeries>
21
21
22
23 Q_DECLARE_METATYPE(QList<QPointF>)
22 Q_DECLARE_METATYPE(QList<QPointF>)
23 Q_DECLARE_METATYPE(QVector<QPointF>)
24
24
25 class tst_QLineSeries : public tst_QXYSeries
25 class tst_QLineSeries : public tst_QXYSeries
26 {
26 {
27 Q_OBJECT
27 Q_OBJECT
28
28
29 public slots:
29 public slots:
30 void initTestCase();
30 void initTestCase();
31 void cleanupTestCase();
31 void cleanupTestCase();
32 void init();
32 void init();
33 void cleanup();
33 void cleanup();
34 private slots:
34 private slots:
35 void qlineseries_data();
35 void qlineseries_data();
36 void qlineseries();
36 void qlineseries();
37 void pressedSignal();
37 void pressedSignal();
38 void releasedSignal();
38 void releasedSignal();
39 void doubleClickedSignal();
39 void doubleClickedSignal();
40 void insert();
40 void insert();
41 protected:
41 protected:
42 void pointsVisible_data();
42 void pointsVisible_data();
43 };
43 };
44
44
45 void tst_QLineSeries::initTestCase()
45 void tst_QLineSeries::initTestCase()
46 {
46 {
47 }
47 }
48
48
49 void tst_QLineSeries::cleanupTestCase()
49 void tst_QLineSeries::cleanupTestCase()
50 {
50 {
51 QTest::qWait(1); // Allow final deleteLaters to run
51 QTest::qWait(1); // Allow final deleteLaters to run
52 }
52 }
53
53
54 void tst_QLineSeries::init()
54 void tst_QLineSeries::init()
55 {
55 {
56 tst_QXYSeries::init();
56 tst_QXYSeries::init();
57 m_series = new QLineSeries();
57 m_series = new QLineSeries();
58 }
58 }
59
59
60 void tst_QLineSeries::cleanup()
60 void tst_QLineSeries::cleanup()
61 {
61 {
62 delete m_series;
62 delete m_series;
63 m_series=0;
63 m_series=0;
64 tst_QXYSeries::cleanup();
64 tst_QXYSeries::cleanup();
65 }
65 }
66
66
67 void tst_QLineSeries::qlineseries_data()
67 void tst_QLineSeries::qlineseries_data()
68 {
68 {
69
69
70 }
70 }
71
71
72 void tst_QLineSeries::qlineseries()
72 void tst_QLineSeries::qlineseries()
73 {
73 {
74 QLineSeries series;
74 QLineSeries series;
75
75
76 QCOMPARE(series.count(),0);
76 QCOMPARE(series.count(),0);
77 QCOMPARE(series.brush(), QBrush());
77 QCOMPARE(series.brush(), QBrush());
78 QCOMPARE(series.points(), QList<QPointF>());
78 QCOMPARE(series.points(), QList<QPointF>());
79 QCOMPARE(series.pointsVector(), QVector<QPointF>());
79 QCOMPARE(series.pen(), QPen());
80 QCOMPARE(series.pen(), QPen());
80 QCOMPARE(series.pointsVisible(), false);
81 QCOMPARE(series.pointsVisible(), false);
81 QCOMPARE(series.pointLabelsVisible(), false);
82 QCOMPARE(series.pointLabelsVisible(), false);
82 QCOMPARE(series.pointLabelsFormat(), QLatin1String("@xPoint, @yPoint"));
83 QCOMPARE(series.pointLabelsFormat(), QLatin1String("@xPoint, @yPoint"));
83 QCOMPARE(series.pointLabelsClipping(), true);
84 QCOMPARE(series.pointLabelsClipping(), true);
84
85
85 series.append(QList<QPointF>());
86 series.append(QList<QPointF>());
86 series.append(0.0,0.0);
87 series.append(0.0,0.0);
87 series.append(QPointF());
88 series.append(QPointF());
88
89
89 series.remove(0.0,0.0);
90 series.remove(0.0,0.0);
90 series.remove(QPointF());
91 series.remove(QPointF());
91 series.clear();
92 series.clear();
92
93
93 series.replace(QPointF(),QPointF());
94 series.replace(QPointF(),QPointF());
94 series.replace(0,0,0,0);
95 series.replace(0,0,0,0);
95 series.setBrush(QBrush());
96 series.setBrush(QBrush());
96
97
97 series.setPen(QPen());
98 series.setPen(QPen());
98 series.setPointsVisible(false);
99 series.setPointsVisible(false);
99
100
100 series.setPointLabelsVisible(false);
101 series.setPointLabelsVisible(false);
101 series.setPointLabelsFormat(QString());
102 series.setPointLabelsFormat(QString());
102
103
103 m_chart->addSeries(&series);
104 m_chart->addSeries(&series);
104 m_view->show();
105 m_view->show();
105 QTest::qWaitForWindowShown(m_view);
106 QTest::qWaitForWindowShown(m_view);
106 }
107 }
107
108
108 void tst_QLineSeries::pressedSignal()
109 void tst_QLineSeries::pressedSignal()
109 {
110 {
110 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
111 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
111
112
112 QPointF linePoint(4, 12);
113 QPointF linePoint(4, 12);
113 QLineSeries *lineSeries = new QLineSeries();
114 QLineSeries *lineSeries = new QLineSeries();
114 lineSeries->append(QPointF(2, 1));
115 lineSeries->append(QPointF(2, 1));
115 lineSeries->append(linePoint);
116 lineSeries->append(linePoint);
116 lineSeries->append(QPointF(6, 12));
117 lineSeries->append(QPointF(6, 12));
117
118
118 QChartView view;
119 QChartView view;
119 view.chart()->legend()->setVisible(false);
120 view.chart()->legend()->setVisible(false);
120 view.chart()->addSeries(lineSeries);
121 view.chart()->addSeries(lineSeries);
121 view.show();
122 view.show();
122 QTest::qWaitForWindowShown(&view);
123 QTest::qWaitForWindowShown(&view);
123
124
124 QSignalSpy seriesSpy(lineSeries, SIGNAL(pressed(QPointF)));
125 QSignalSpy seriesSpy(lineSeries, SIGNAL(pressed(QPointF)));
125
126
126 QPointF checkPoint = view.chart()->mapToPosition(linePoint);
127 QPointF checkPoint = view.chart()->mapToPosition(linePoint);
127 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
128 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
128 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
129 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
129
130
130 QCOMPARE(seriesSpy.count(), 1);
131 QCOMPARE(seriesSpy.count(), 1);
131 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
132 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
132 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
133 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
133 // this causes small distinction in decimals so we round it before comparing
134 // this causes small distinction in decimals so we round it before comparing
134 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
135 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
135 QCOMPARE(qRound(signalPoint.x()), qRound(linePoint.x()));
136 QCOMPARE(qRound(signalPoint.x()), qRound(linePoint.x()));
136 QCOMPARE(qRound(signalPoint.y()), qRound(linePoint.y()));
137 QCOMPARE(qRound(signalPoint.y()), qRound(linePoint.y()));
137 }
138 }
138
139
139 void tst_QLineSeries::releasedSignal()
140 void tst_QLineSeries::releasedSignal()
140 {
141 {
141 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
142 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
142
143
143 QPointF linePoint(4, 12);
144 QPointF linePoint(4, 12);
144 QLineSeries *lineSeries = new QLineSeries();
145 QLineSeries *lineSeries = new QLineSeries();
145 lineSeries->append(QPointF(2, 20));
146 lineSeries->append(QPointF(2, 20));
146 lineSeries->append(linePoint);
147 lineSeries->append(linePoint);
147 lineSeries->append(QPointF(6, 12));
148 lineSeries->append(QPointF(6, 12));
148
149
149 QChartView view;
150 QChartView view;
150 view.chart()->legend()->setVisible(false);
151 view.chart()->legend()->setVisible(false);
151 view.chart()->addSeries(lineSeries);
152 view.chart()->addSeries(lineSeries);
152 view.show();
153 view.show();
153 QTest::qWaitForWindowShown(&view);
154 QTest::qWaitForWindowShown(&view);
154
155
155 QSignalSpy seriesSpy(lineSeries, SIGNAL(released(QPointF)));
156 QSignalSpy seriesSpy(lineSeries, SIGNAL(released(QPointF)));
156
157
157 QPointF checkPoint = view.chart()->mapToPosition(linePoint);
158 QPointF checkPoint = view.chart()->mapToPosition(linePoint);
158 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
159 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
159 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
160 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
160
161
161 QCOMPARE(seriesSpy.count(), 1);
162 QCOMPARE(seriesSpy.count(), 1);
162 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
163 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
163 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
164 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
164 // this causes small distinction in decimals so we round it before comparing
165 // this causes small distinction in decimals so we round it before comparing
165 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
166 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
166 QCOMPARE(qRound(signalPoint.x()), qRound(linePoint.x()));
167 QCOMPARE(qRound(signalPoint.x()), qRound(linePoint.x()));
167 QCOMPARE(qRound(signalPoint.y()), qRound(linePoint.y()));
168 QCOMPARE(qRound(signalPoint.y()), qRound(linePoint.y()));
168 }
169 }
169
170
170 void tst_QLineSeries::insert()
171 void tst_QLineSeries::insert()
171 {
172 {
172 QLineSeries lineSeries;
173 QLineSeries lineSeries;
173 QSignalSpy insertSpy(&lineSeries, &QXYSeries::pointAdded);
174 QSignalSpy insertSpy(&lineSeries, &QXYSeries::pointAdded);
174 lineSeries.insert(0, QPoint(3, 3));
175 lineSeries.insert(0, QPoint(3, 3));
175 QCOMPARE(insertSpy.count(), 1);
176 QCOMPARE(insertSpy.count(), 1);
176 QVariantList arguments = insertSpy.takeFirst();
177 QVariantList arguments = insertSpy.takeFirst();
177 QCOMPARE(arguments.first().toInt(), 0);
178 QCOMPARE(arguments.first().toInt(), 0);
178 lineSeries.insert(0, QPoint(1, 1));
179 lineSeries.insert(0, QPoint(1, 1));
179 arguments = insertSpy.takeFirst();
180 arguments = insertSpy.takeFirst();
180 QCOMPARE(arguments.first().toInt(), 0);
181 QCOMPARE(arguments.first().toInt(), 0);
181 lineSeries.insert(1, QPoint(2, 2));
182 lineSeries.insert(1, QPoint(2, 2));
182 arguments = insertSpy.takeFirst();
183 arguments = insertSpy.takeFirst();
183 QCOMPARE(arguments.first().toInt(), 1);
184 QCOMPARE(arguments.first().toInt(), 1);
184 lineSeries.insert(42, QPoint(0, 0));
185 lineSeries.insert(42, QPoint(0, 0));
185 arguments = insertSpy.takeFirst();
186 arguments = insertSpy.takeFirst();
186 QCOMPARE(arguments.first().toInt(), 3);
187 QCOMPARE(arguments.first().toInt(), 3);
187 lineSeries.insert(-42, QPoint(0, 0));
188 lineSeries.insert(-42, QPoint(0, 0));
188 arguments = insertSpy.takeFirst();
189 arguments = insertSpy.takeFirst();
189 QCOMPARE(arguments.first().toInt(), 0);
190 QCOMPARE(arguments.first().toInt(), 0);
190 }
191 }
191
192
192 void tst_QLineSeries::doubleClickedSignal()
193 void tst_QLineSeries::doubleClickedSignal()
193 {
194 {
194 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
195 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
195
196
196 QPointF linePoint(4, 12);
197 QPointF linePoint(4, 12);
197 QLineSeries *lineSeries = new QLineSeries();
198 QLineSeries *lineSeries = new QLineSeries();
198 lineSeries->append(QPointF(2, 20));
199 lineSeries->append(QPointF(2, 20));
199 lineSeries->append(linePoint);
200 lineSeries->append(linePoint);
200 lineSeries->append(QPointF(6, 12));
201 lineSeries->append(QPointF(6, 12));
201
202
202 QChartView view;
203 QChartView view;
203 view.chart()->legend()->setVisible(false);
204 view.chart()->legend()->setVisible(false);
204 view.chart()->addSeries(lineSeries);
205 view.chart()->addSeries(lineSeries);
205 view.show();
206 view.show();
206 QTest::qWaitForWindowShown(&view);
207 QTest::qWaitForWindowShown(&view);
207
208
208 QSignalSpy seriesSpy(lineSeries, SIGNAL(doubleClicked(QPointF)));
209 QSignalSpy seriesSpy(lineSeries, SIGNAL(doubleClicked(QPointF)));
209
210
210 QPointF checkPoint = view.chart()->mapToPosition(linePoint);
211 QPointF checkPoint = view.chart()->mapToPosition(linePoint);
211 // mouseClick needed first to save the position
212 // mouseClick needed first to save the position
212 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
213 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
213 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
214 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
214 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
215 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
215
216
216 QCOMPARE(seriesSpy.count(), 1);
217 QCOMPARE(seriesSpy.count(), 1);
217 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
218 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
218 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
219 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
219 // this causes small distinction in decimals so we round it before comparing
220 // this causes small distinction in decimals so we round it before comparing
220 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
221 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
221 QCOMPARE(qRound(signalPoint.x()), qRound(linePoint.x()));
222 QCOMPARE(qRound(signalPoint.x()), qRound(linePoint.x()));
222 QCOMPARE(qRound(signalPoint.y()), qRound(linePoint.y()));
223 QCOMPARE(qRound(signalPoint.y()), qRound(linePoint.y()));
223 }
224 }
224
225
225 QTEST_MAIN(tst_QLineSeries)
226 QTEST_MAIN(tst_QLineSeries)
226
227
227 #include "tst_qlineseries.moc"
228 #include "tst_qlineseries.moc"
228
229
@@ -1,226 +1,228
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include "../qxyseries/tst_qxyseries.h"
19 #include "../qxyseries/tst_qxyseries.h"
20 #include <QtCharts/QScatterSeries>
20 #include <QtCharts/QScatterSeries>
21
21
22 Q_DECLARE_METATYPE(QList<QPointF>)
22 Q_DECLARE_METATYPE(QList<QPointF>)
23 Q_DECLARE_METATYPE(QVector<QPointF>)
23
24
24 class tst_QScatterSeries : public tst_QXYSeries
25 class tst_QScatterSeries : public tst_QXYSeries
25 {
26 {
26 Q_OBJECT
27 Q_OBJECT
27
28
28 public slots:
29 public slots:
29 void initTestCase();
30 void initTestCase();
30 void cleanupTestCase();
31 void cleanupTestCase();
31 void init();
32 void init();
32 void cleanup();
33 void cleanup();
33 private slots:
34 private slots:
34 void qscatterseries_data();
35 void qscatterseries_data();
35 void qscatterseries();
36 void qscatterseries();
36 void scatterChangedSignals();
37 void scatterChangedSignals();
37 void pressedSignal();
38 void pressedSignal();
38 void releasedSignal();
39 void releasedSignal();
39 void doubleClickedSignal();
40 void doubleClickedSignal();
40
41
41 protected:
42 protected:
42 void pointsVisible_data();
43 void pointsVisible_data();
43 };
44 };
44
45
45 void tst_QScatterSeries::initTestCase()
46 void tst_QScatterSeries::initTestCase()
46 {
47 {
47 }
48 }
48
49
49 void tst_QScatterSeries::cleanupTestCase()
50 void tst_QScatterSeries::cleanupTestCase()
50 {
51 {
51 QTest::qWait(1); // Allow final deleteLaters to run
52 QTest::qWait(1); // Allow final deleteLaters to run
52 }
53 }
53
54
54 void tst_QScatterSeries::init()
55 void tst_QScatterSeries::init()
55 {
56 {
56 tst_QXYSeries::init();
57 tst_QXYSeries::init();
57 m_series = new QScatterSeries();
58 m_series = new QScatterSeries();
58 }
59 }
59
60
60 void tst_QScatterSeries::cleanup()
61 void tst_QScatterSeries::cleanup()
61 {
62 {
62 delete m_series;
63 delete m_series;
63 tst_QXYSeries::cleanup();
64 tst_QXYSeries::cleanup();
64 }
65 }
65
66
66 void tst_QScatterSeries::qscatterseries_data()
67 void tst_QScatterSeries::qscatterseries_data()
67 {
68 {
68
69
69 }
70 }
70
71
71 void tst_QScatterSeries::qscatterseries()
72 void tst_QScatterSeries::qscatterseries()
72 {
73 {
73 QScatterSeries series;
74 QScatterSeries series;
74
75
75 QCOMPARE(series.count(),0);
76 QCOMPARE(series.count(),0);
76 QCOMPARE(series.brush(), QBrush());
77 QCOMPARE(series.brush(), QBrush());
77 QCOMPARE(series.points(), QList<QPointF>());
78 QCOMPARE(series.points(), QList<QPointF>());
79 QCOMPARE(series.pointsVector(), QVector<QPointF>());
78 QCOMPARE(series.pen(), QPen());
80 QCOMPARE(series.pen(), QPen());
79 QCOMPARE(series.pointsVisible(), false);
81 QCOMPARE(series.pointsVisible(), false);
80
82
81 series.append(QList<QPointF>());
83 series.append(QList<QPointF>());
82 series.append(0.0,0.0);
84 series.append(0.0,0.0);
83 series.append(QPointF());
85 series.append(QPointF());
84
86
85 series.remove(0.0,0.0);
87 series.remove(0.0,0.0);
86 series.remove(QPointF());
88 series.remove(QPointF());
87 series.clear();
89 series.clear();
88
90
89 series.replace(QPointF(),QPointF());
91 series.replace(QPointF(),QPointF());
90 series.replace(0,0,0,0);
92 series.replace(0,0,0,0);
91 series.setBrush(QBrush());
93 series.setBrush(QBrush());
92
94
93 series.setPen(QPen());
95 series.setPen(QPen());
94 series.setPointsVisible(false);
96 series.setPointsVisible(false);
95
97
96 m_chart->addSeries(&series);
98 m_chart->addSeries(&series);
97 m_view->show();
99 m_view->show();
98 QTest::qWaitForWindowShown(m_view);
100 QTest::qWaitForWindowShown(m_view);
99 }
101 }
100
102
101 void tst_QScatterSeries::scatterChangedSignals()
103 void tst_QScatterSeries::scatterChangedSignals()
102 {
104 {
103 QScatterSeries *series = qobject_cast<QScatterSeries *>(m_series);
105 QScatterSeries *series = qobject_cast<QScatterSeries *>(m_series);
104 QVERIFY(series);
106 QVERIFY(series);
105
107
106 QSignalSpy colorSpy(series, SIGNAL(colorChanged(QColor)));
108 QSignalSpy colorSpy(series, SIGNAL(colorChanged(QColor)));
107 QSignalSpy borderColorSpy(series, SIGNAL(borderColorChanged(QColor)));
109 QSignalSpy borderColorSpy(series, SIGNAL(borderColorChanged(QColor)));
108
110
109 // Color
111 // Color
110 series->setColor(QColor("blueviolet"));
112 series->setColor(QColor("blueviolet"));
111 TRY_COMPARE(colorSpy.count(), 1);
113 TRY_COMPARE(colorSpy.count(), 1);
112
114
113 // Border color
115 // Border color
114 series->setBorderColor(QColor("burlywood"));
116 series->setBorderColor(QColor("burlywood"));
115 TRY_COMPARE(borderColorSpy.count(), 1);
117 TRY_COMPARE(borderColorSpy.count(), 1);
116
118
117 // Pen
119 // Pen
118 QPen p = series->pen();
120 QPen p = series->pen();
119 p.setColor("lightpink");
121 p.setColor("lightpink");
120 series->setPen(p);
122 series->setPen(p);
121 TRY_COMPARE(borderColorSpy.count(), 2);
123 TRY_COMPARE(borderColorSpy.count(), 2);
122
124
123 // Brush
125 // Brush
124 QBrush b = series->brush();
126 QBrush b = series->brush();
125 b.setColor("lime");
127 b.setColor("lime");
126 series->setBrush(b);
128 series->setBrush(b);
127 TRY_COMPARE(colorSpy.count(), 2);
129 TRY_COMPARE(colorSpy.count(), 2);
128 }
130 }
129
131
130 void tst_QScatterSeries::pressedSignal()
132 void tst_QScatterSeries::pressedSignal()
131 {
133 {
132 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
134 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
133
135
134 QPointF scatterPoint(4, 12);
136 QPointF scatterPoint(4, 12);
135 QScatterSeries *scatterSeries = new QScatterSeries();
137 QScatterSeries *scatterSeries = new QScatterSeries();
136 scatterSeries->append(QPointF(2, 1));
138 scatterSeries->append(QPointF(2, 1));
137 scatterSeries->append(scatterPoint);
139 scatterSeries->append(scatterPoint);
138 scatterSeries->append(QPointF(6, 12));
140 scatterSeries->append(QPointF(6, 12));
139
141
140 QChartView view;
142 QChartView view;
141 view.chart()->legend()->setVisible(false);
143 view.chart()->legend()->setVisible(false);
142 view.chart()->addSeries(scatterSeries);
144 view.chart()->addSeries(scatterSeries);
143 view.show();
145 view.show();
144 QTest::qWaitForWindowShown(&view);
146 QTest::qWaitForWindowShown(&view);
145
147
146 QSignalSpy seriesSpy(scatterSeries, SIGNAL(pressed(QPointF)));
148 QSignalSpy seriesSpy(scatterSeries, SIGNAL(pressed(QPointF)));
147
149
148 QPointF checkPoint = view.chart()->mapToPosition(scatterPoint);
150 QPointF checkPoint = view.chart()->mapToPosition(scatterPoint);
149 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
151 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
150 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
152 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
151
153
152 QCOMPARE(seriesSpy.count(), 1);
154 QCOMPARE(seriesSpy.count(), 1);
153 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
155 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
154 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
156 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
155 // this causes small distinction in decimals so we round it before comparing
157 // this causes small distinction in decimals so we round it before comparing
156 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
158 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
157 QCOMPARE(qRound(signalPoint.x()), qRound(scatterPoint.x()));
159 QCOMPARE(qRound(signalPoint.x()), qRound(scatterPoint.x()));
158 QCOMPARE(qRound(signalPoint.y()), qRound(scatterPoint.y()));
160 QCOMPARE(qRound(signalPoint.y()), qRound(scatterPoint.y()));
159 }
161 }
160
162
161 void tst_QScatterSeries::releasedSignal()
163 void tst_QScatterSeries::releasedSignal()
162 {
164 {
163 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
165 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
164
166
165 QPointF scatterPoint(4, 12);
167 QPointF scatterPoint(4, 12);
166 QScatterSeries *scatterSeries = new QScatterSeries();
168 QScatterSeries *scatterSeries = new QScatterSeries();
167 scatterSeries->append(QPointF(2, 1));
169 scatterSeries->append(QPointF(2, 1));
168 scatterSeries->append(scatterPoint);
170 scatterSeries->append(scatterPoint);
169 scatterSeries->append(QPointF(6, 12));
171 scatterSeries->append(QPointF(6, 12));
170
172
171 QChartView view;
173 QChartView view;
172 view.chart()->legend()->setVisible(false);
174 view.chart()->legend()->setVisible(false);
173 view.chart()->addSeries(scatterSeries);
175 view.chart()->addSeries(scatterSeries);
174 view.show();
176 view.show();
175 QTest::qWaitForWindowShown(&view);
177 QTest::qWaitForWindowShown(&view);
176
178
177 QSignalSpy seriesSpy(scatterSeries, SIGNAL(released(QPointF)));
179 QSignalSpy seriesSpy(scatterSeries, SIGNAL(released(QPointF)));
178
180
179 QPointF checkPoint = view.chart()->mapToPosition(scatterPoint);
181 QPointF checkPoint = view.chart()->mapToPosition(scatterPoint);
180 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
182 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
181 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
183 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
182
184
183 QCOMPARE(seriesSpy.count(), 1);
185 QCOMPARE(seriesSpy.count(), 1);
184 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
186 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
185 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
187 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
186 // this causes small distinction in decimals so we round it before comparing
188 // this causes small distinction in decimals so we round it before comparing
187 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
189 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
188 QCOMPARE(qRound(signalPoint.x()), qRound(scatterPoint.x()));
190 QCOMPARE(qRound(signalPoint.x()), qRound(scatterPoint.x()));
189 QCOMPARE(qRound(signalPoint.y()), qRound(scatterPoint.y()));
191 QCOMPARE(qRound(signalPoint.y()), qRound(scatterPoint.y()));
190 }
192 }
191
193
192 void tst_QScatterSeries::doubleClickedSignal()
194 void tst_QScatterSeries::doubleClickedSignal()
193 {
195 {
194 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
196 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
195
197
196 QPointF scatterPoint(4, 12);
198 QPointF scatterPoint(4, 12);
197 QScatterSeries *scatterSeries = new QScatterSeries();
199 QScatterSeries *scatterSeries = new QScatterSeries();
198 scatterSeries->append(QPointF(2, 1));
200 scatterSeries->append(QPointF(2, 1));
199 scatterSeries->append(scatterPoint);
201 scatterSeries->append(scatterPoint);
200 scatterSeries->append(QPointF(6, 12));
202 scatterSeries->append(QPointF(6, 12));
201
203
202 QChartView view;
204 QChartView view;
203 view.chart()->legend()->setVisible(false);
205 view.chart()->legend()->setVisible(false);
204 view.chart()->addSeries(scatterSeries);
206 view.chart()->addSeries(scatterSeries);
205 view.show();
207 view.show();
206 QTest::qWaitForWindowShown(&view);
208 QTest::qWaitForWindowShown(&view);
207
209
208 QSignalSpy seriesSpy(scatterSeries, SIGNAL(doubleClicked(QPointF)));
210 QSignalSpy seriesSpy(scatterSeries, SIGNAL(doubleClicked(QPointF)));
209
211
210 QPointF checkPoint = view.chart()->mapToPosition(scatterPoint);
212 QPointF checkPoint = view.chart()->mapToPosition(scatterPoint);
211 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
213 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
212 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
214 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
213
215
214 QCOMPARE(seriesSpy.count(), 1);
216 QCOMPARE(seriesSpy.count(), 1);
215 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
217 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
216 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
218 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
217 // this causes small distinction in decimals so we round it before comparing
219 // this causes small distinction in decimals so we round it before comparing
218 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
220 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
219 QCOMPARE(qRound(signalPoint.x()), qRound(scatterPoint.x()));
221 QCOMPARE(qRound(signalPoint.x()), qRound(scatterPoint.x()));
220 QCOMPARE(qRound(signalPoint.y()), qRound(scatterPoint.y()));
222 QCOMPARE(qRound(signalPoint.y()), qRound(scatterPoint.y()));
221 }
223 }
222
224
223 QTEST_MAIN(tst_QScatterSeries)
225 QTEST_MAIN(tst_QScatterSeries)
224
226
225 #include "tst_qscatterseries.moc"
227 #include "tst_qscatterseries.moc"
226
228
@@ -1,196 +1,198
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include "../qxyseries/tst_qxyseries.h"
19 #include "../qxyseries/tst_qxyseries.h"
20 #include <QtCharts/QSplineSeries>
20 #include <QtCharts/QSplineSeries>
21
21
22 Q_DECLARE_METATYPE(QList<QPointF>)
22 Q_DECLARE_METATYPE(QList<QPointF>)
23 Q_DECLARE_METATYPE(QVector<QPointF>)
23
24
24 class tst_QSplineSeries : public tst_QXYSeries
25 class tst_QSplineSeries : public tst_QXYSeries
25 {
26 {
26 Q_OBJECT
27 Q_OBJECT
27
28
28 public slots:
29 public slots:
29 void initTestCase();
30 void initTestCase();
30 void cleanupTestCase();
31 void cleanupTestCase();
31 void init();
32 void init();
32 void cleanup();
33 void cleanup();
33 private slots:
34 private slots:
34 void qsplineseries_data();
35 void qsplineseries_data();
35 void qsplineseries();
36 void qsplineseries();
36 void pressedSignal();
37 void pressedSignal();
37 void releasedSignal();
38 void releasedSignal();
38 void doubleClickedSignal();
39 void doubleClickedSignal();
39 protected:
40 protected:
40 void pointsVisible_data();
41 void pointsVisible_data();
41 };
42 };
42
43
43 void tst_QSplineSeries::initTestCase()
44 void tst_QSplineSeries::initTestCase()
44 {
45 {
45 }
46 }
46
47
47 void tst_QSplineSeries::cleanupTestCase()
48 void tst_QSplineSeries::cleanupTestCase()
48 {
49 {
49 QTest::qWait(1); // Allow final deleteLaters to run
50 QTest::qWait(1); // Allow final deleteLaters to run
50 }
51 }
51
52
52 void tst_QSplineSeries::init()
53 void tst_QSplineSeries::init()
53 {
54 {
54 tst_QXYSeries::init();
55 tst_QXYSeries::init();
55 m_series = new QSplineSeries();
56 m_series = new QSplineSeries();
56 }
57 }
57
58
58 void tst_QSplineSeries::cleanup()
59 void tst_QSplineSeries::cleanup()
59 {
60 {
60 delete m_series;
61 delete m_series;
61 tst_QXYSeries::cleanup();
62 tst_QXYSeries::cleanup();
62 }
63 }
63
64
64 void tst_QSplineSeries::qsplineseries_data()
65 void tst_QSplineSeries::qsplineseries_data()
65 {
66 {
66
67
67 }
68 }
68
69
69 void tst_QSplineSeries::qsplineseries()
70 void tst_QSplineSeries::qsplineseries()
70 {
71 {
71 QSplineSeries series;
72 QSplineSeries series;
72
73
73 QCOMPARE(series.count(),0);
74 QCOMPARE(series.count(),0);
74 QCOMPARE(series.brush(), QBrush());
75 QCOMPARE(series.brush(), QBrush());
75 QCOMPARE(series.points(), QList<QPointF>());
76 QCOMPARE(series.points(), QList<QPointF>());
77 QCOMPARE(series.pointsVector(), QVector<QPointF>());
76 QCOMPARE(series.pen(), QPen());
78 QCOMPARE(series.pen(), QPen());
77 QCOMPARE(series.pointsVisible(), false);
79 QCOMPARE(series.pointsVisible(), false);
78
80
79 series.append(QList<QPointF>());
81 series.append(QList<QPointF>());
80 series.append(0.0,0.0);
82 series.append(0.0,0.0);
81 series.append(QPointF());
83 series.append(QPointF());
82
84
83 series.remove(0.0,0.0);
85 series.remove(0.0,0.0);
84 series.remove(QPointF());
86 series.remove(QPointF());
85 series.clear();
87 series.clear();
86
88
87 series.replace(QPointF(),QPointF());
89 series.replace(QPointF(),QPointF());
88 series.replace(0,0,0,0);
90 series.replace(0,0,0,0);
89 series.setBrush(QBrush());
91 series.setBrush(QBrush());
90
92
91 series.setPen(QPen());
93 series.setPen(QPen());
92 series.setPointsVisible(false);
94 series.setPointsVisible(false);
93
95
94 m_chart->addSeries(&series);
96 m_chart->addSeries(&series);
95 m_view->show();
97 m_view->show();
96 QTest::qWaitForWindowShown(m_view);
98 QTest::qWaitForWindowShown(m_view);
97 }
99 }
98
100
99 void tst_QSplineSeries::pressedSignal()
101 void tst_QSplineSeries::pressedSignal()
100 {
102 {
101 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
103 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
102
104
103 QPointF splinePoint(4, 12);
105 QPointF splinePoint(4, 12);
104 QSplineSeries *splineSeries = new QSplineSeries();
106 QSplineSeries *splineSeries = new QSplineSeries();
105 splineSeries->append(QPointF(2, 1));
107 splineSeries->append(QPointF(2, 1));
106 splineSeries->append(splinePoint);
108 splineSeries->append(splinePoint);
107 splineSeries->append(QPointF(6, 12));
109 splineSeries->append(QPointF(6, 12));
108
110
109 QChartView view;
111 QChartView view;
110 view.chart()->legend()->setVisible(false);
112 view.chart()->legend()->setVisible(false);
111 view.chart()->addSeries(splineSeries);
113 view.chart()->addSeries(splineSeries);
112 view.show();
114 view.show();
113 QTest::qWaitForWindowShown(&view);
115 QTest::qWaitForWindowShown(&view);
114
116
115 QSignalSpy seriesSpy(splineSeries, SIGNAL(pressed(QPointF)));
117 QSignalSpy seriesSpy(splineSeries, SIGNAL(pressed(QPointF)));
116
118
117 QPointF checkPoint = view.chart()->mapToPosition(splinePoint);
119 QPointF checkPoint = view.chart()->mapToPosition(splinePoint);
118 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
120 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
119 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
121 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
120
122
121 QCOMPARE(seriesSpy.count(), 1);
123 QCOMPARE(seriesSpy.count(), 1);
122 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
124 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
123 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
125 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
124 // this causes small distinction in decimals so we round it before comparing
126 // this causes small distinction in decimals so we round it before comparing
125 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
127 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
126 QCOMPARE(qRound(signalPoint.x()), qRound(splinePoint.x()));
128 QCOMPARE(qRound(signalPoint.x()), qRound(splinePoint.x()));
127 QCOMPARE(qRound(signalPoint.y()), qRound(splinePoint.y()));
129 QCOMPARE(qRound(signalPoint.y()), qRound(splinePoint.y()));
128 }
130 }
129
131
130 void tst_QSplineSeries::releasedSignal()
132 void tst_QSplineSeries::releasedSignal()
131 {
133 {
132 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
134 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
133
135
134 QPointF splinePoint(4, 12);
136 QPointF splinePoint(4, 12);
135 QSplineSeries *splineSeries = new QSplineSeries();
137 QSplineSeries *splineSeries = new QSplineSeries();
136 splineSeries->append(QPointF(2, 20));
138 splineSeries->append(QPointF(2, 20));
137 splineSeries->append(splinePoint);
139 splineSeries->append(splinePoint);
138 splineSeries->append(QPointF(6, 12));
140 splineSeries->append(QPointF(6, 12));
139
141
140 QChartView view;
142 QChartView view;
141 view.chart()->legend()->setVisible(false);
143 view.chart()->legend()->setVisible(false);
142 view.chart()->addSeries(splineSeries);
144 view.chart()->addSeries(splineSeries);
143 view.show();
145 view.show();
144 QTest::qWaitForWindowShown(&view);
146 QTest::qWaitForWindowShown(&view);
145
147
146 QSignalSpy seriesSpy(splineSeries, SIGNAL(released(QPointF)));
148 QSignalSpy seriesSpy(splineSeries, SIGNAL(released(QPointF)));
147
149
148 QPointF checkPoint = view.chart()->mapToPosition(splinePoint);
150 QPointF checkPoint = view.chart()->mapToPosition(splinePoint);
149 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
151 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
150 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
152 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
151
153
152 QCOMPARE(seriesSpy.count(), 1);
154 QCOMPARE(seriesSpy.count(), 1);
153 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
155 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
154 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
156 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
155 // this causes small distinction in decimals so we round it before comparing
157 // this causes small distinction in decimals so we round it before comparing
156 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
158 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
157 QCOMPARE(qRound(signalPoint.x()), qRound(splinePoint.x()));
159 QCOMPARE(qRound(signalPoint.x()), qRound(splinePoint.x()));
158 QCOMPARE(qRound(signalPoint.y()), qRound(splinePoint.y()));
160 QCOMPARE(qRound(signalPoint.y()), qRound(splinePoint.y()));
159 }
161 }
160
162
161 void tst_QSplineSeries::doubleClickedSignal()
163 void tst_QSplineSeries::doubleClickedSignal()
162 {
164 {
163 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
165 SKIP_IF_CANNOT_TEST_MOUSE_EVENTS();
164
166
165 QPointF splinePoint(4, 12);
167 QPointF splinePoint(4, 12);
166 QSplineSeries *splineSeries = new QSplineSeries();
168 QSplineSeries *splineSeries = new QSplineSeries();
167 splineSeries->append(QPointF(2, 20));
169 splineSeries->append(QPointF(2, 20));
168 splineSeries->append(splinePoint);
170 splineSeries->append(splinePoint);
169 splineSeries->append(QPointF(6, 12));
171 splineSeries->append(QPointF(6, 12));
170
172
171 QChartView view;
173 QChartView view;
172 view.chart()->legend()->setVisible(false);
174 view.chart()->legend()->setVisible(false);
173 view.chart()->addSeries(splineSeries);
175 view.chart()->addSeries(splineSeries);
174 view.show();
176 view.show();
175 QTest::qWaitForWindowShown(&view);
177 QTest::qWaitForWindowShown(&view);
176
178
177 QSignalSpy seriesSpy(splineSeries, SIGNAL(doubleClicked(QPointF)));
179 QSignalSpy seriesSpy(splineSeries, SIGNAL(doubleClicked(QPointF)));
178
180
179 QPointF checkPoint = view.chart()->mapToPosition(splinePoint);
181 QPointF checkPoint = view.chart()->mapToPosition(splinePoint);
180 // mouseClick needed first to save the position
182 // mouseClick needed first to save the position
181 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
183 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
182 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
184 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, checkPoint.toPoint());
183 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
185 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
184
186
185 QCOMPARE(seriesSpy.count(), 1);
187 QCOMPARE(seriesSpy.count(), 1);
186 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
188 QList<QVariant> seriesSpyArg = seriesSpy.takeFirst();
187 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
189 // checkPoint is QPointF and for the mouseClick it it's changed to QPoint
188 // this causes small distinction in decimals so we round it before comparing
190 // this causes small distinction in decimals so we round it before comparing
189 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
191 QPointF signalPoint = qvariant_cast<QPointF>(seriesSpyArg.at(0));
190 QCOMPARE(qRound(signalPoint.x()), qRound(splinePoint.x()));
192 QCOMPARE(qRound(signalPoint.x()), qRound(splinePoint.x()));
191 QCOMPARE(qRound(signalPoint.y()), qRound(splinePoint.y()));
193 QCOMPARE(qRound(signalPoint.y()), qRound(splinePoint.y()));
192 }
194 }
193 QTEST_MAIN(tst_QSplineSeries)
195 QTEST_MAIN(tst_QSplineSeries)
194
196
195 #include "tst_qsplineseries.moc"
197 #include "tst_qsplineseries.moc"
196
198
@@ -1,642 +1,643
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd
3 ** Copyright (C) 2015 The Qt Company Ltd
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
5 ** For any questions to The Qt Company, please use contact form at http://qt.io
6 **
6 **
7 ** This file is part of the Qt Charts module.
7 ** This file is part of the Qt Charts module.
8 **
8 **
9 ** Licensees holding valid commercial license for Qt may use this file in
9 ** Licensees holding valid commercial license for Qt may use this file in
10 ** accordance with the Qt License Agreement provided with the Software
10 ** accordance with the Qt License Agreement provided with the Software
11 ** or, alternatively, in accordance with the terms contained in a written
11 ** or, alternatively, in accordance with the terms contained in a written
12 ** agreement between you and The Qt Company.
12 ** agreement between you and The Qt Company.
13 **
13 **
14 ** If you have questions regarding the use of this file, please use
14 ** If you have questions regarding the use of this file, please use
15 ** contact form at http://qt.io
15 ** contact form at http://qt.io
16 **
16 **
17 ****************************************************************************/
17 ****************************************************************************/
18
18
19 #include "tst_qxyseries.h"
19 #include "tst_qxyseries.h"
20
20
21 Q_DECLARE_METATYPE(QList<QPointF>)
21 Q_DECLARE_METATYPE(QList<QPointF>)
22
22
23 void tst_QXYSeries::initTestCase()
23 void tst_QXYSeries::initTestCase()
24 {
24 {
25 }
25 }
26
26
27 void tst_QXYSeries::cleanupTestCase()
27 void tst_QXYSeries::cleanupTestCase()
28 {
28 {
29 QTest::qWait(1); // Allow final deleteLaters to run
29 QTest::qWait(1); // Allow final deleteLaters to run
30 }
30 }
31
31
32 void tst_QXYSeries::init()
32 void tst_QXYSeries::init()
33 {
33 {
34 m_view = new QChartView(newQChartOrQPolarChart());
34 m_view = new QChartView(newQChartOrQPolarChart());
35 m_chart = m_view->chart();
35 m_chart = m_view->chart();
36 }
36 }
37
37
38 void tst_QXYSeries::cleanup()
38 void tst_QXYSeries::cleanup()
39 {
39 {
40 delete m_view;
40 delete m_view;
41 m_view = 0;
41 m_view = 0;
42 m_chart = 0;
42 m_chart = 0;
43 m_series = 0;
43 m_series = 0;
44 }
44 }
45
45
46 void tst_QXYSeries::seriesName()
46 void tst_QXYSeries::seriesName()
47 {
47 {
48 QSignalSpy nameSpy(m_series, SIGNAL(nameChanged()));
48 QSignalSpy nameSpy(m_series, SIGNAL(nameChanged()));
49 QCOMPARE(m_series->name(), QString());
49 QCOMPARE(m_series->name(), QString());
50 m_series->setName("seriesname");
50 m_series->setName("seriesname");
51 QCOMPARE(m_series->name(), QString("seriesname"));
51 QCOMPARE(m_series->name(), QString("seriesname"));
52 TRY_COMPARE(nameSpy.count(), 1);
52 TRY_COMPARE(nameSpy.count(), 1);
53 }
53 }
54
54
55 void tst_QXYSeries::seriesVisible()
55 void tst_QXYSeries::seriesVisible()
56 {
56 {
57 QSignalSpy visibleSpy(m_series, SIGNAL(visibleChanged()));
57 QSignalSpy visibleSpy(m_series, SIGNAL(visibleChanged()));
58 QCOMPARE(m_series->isVisible(), true);
58 QCOMPARE(m_series->isVisible(), true);
59 m_series->setVisible(false);
59 m_series->setVisible(false);
60 QCOMPARE(m_series->isVisible(), false);
60 QCOMPARE(m_series->isVisible(), false);
61 m_series->setVisible(true);
61 m_series->setVisible(true);
62 TRY_COMPARE(visibleSpy.count(), 2);
62 TRY_COMPARE(visibleSpy.count(), 2);
63 }
63 }
64
64
65 void tst_QXYSeries::seriesOpacity()
65 void tst_QXYSeries::seriesOpacity()
66 {
66 {
67 QSignalSpy opacitySpy(m_series, SIGNAL(opacityChanged()));
67 QSignalSpy opacitySpy(m_series, SIGNAL(opacityChanged()));
68 QCOMPARE(m_series->opacity(), 1.0);
68 QCOMPARE(m_series->opacity(), 1.0);
69
69
70 m_series->setOpacity(0.5);
70 m_series->setOpacity(0.5);
71 QCOMPARE(m_series->opacity(), 0.5);
71 QCOMPARE(m_series->opacity(), 0.5);
72 QCOMPARE(opacitySpy.count(), 1);
72 QCOMPARE(opacitySpy.count(), 1);
73
73
74 m_series->setOpacity(0.0);
74 m_series->setOpacity(0.0);
75 QCOMPARE(m_series->opacity(), 0.0);
75 QCOMPARE(m_series->opacity(), 0.0);
76 QCOMPARE(opacitySpy.count(), 2);
76 QCOMPARE(opacitySpy.count(), 2);
77
77
78 m_series->setOpacity(1.0);
78 m_series->setOpacity(1.0);
79 QCOMPARE(m_series->opacity(), 1.0);
79 QCOMPARE(m_series->opacity(), 1.0);
80 QCOMPARE(opacitySpy.count(), 3);
80 QCOMPARE(opacitySpy.count(), 3);
81 }
81 }
82
82
83 void tst_QXYSeries::pointLabelsFormat()
83 void tst_QXYSeries::pointLabelsFormat()
84 {
84 {
85 QSignalSpy labelsFormatSpy(m_series, SIGNAL(pointLabelsFormatChanged(QString)));
85 QSignalSpy labelsFormatSpy(m_series, SIGNAL(pointLabelsFormatChanged(QString)));
86 QCOMPARE(m_series->pointLabelsFormat(), QLatin1String("@xPoint, @yPoint"));
86 QCOMPARE(m_series->pointLabelsFormat(), QLatin1String("@xPoint, @yPoint"));
87
87
88 QString format("@yPoint");
88 QString format("@yPoint");
89 m_series->setPointLabelsFormat(format);
89 m_series->setPointLabelsFormat(format);
90 TRY_COMPARE(labelsFormatSpy.count(), 1);
90 TRY_COMPARE(labelsFormatSpy.count(), 1);
91 QList<QVariant> arguments = labelsFormatSpy.takeFirst();
91 QList<QVariant> arguments = labelsFormatSpy.takeFirst();
92 QVERIFY(arguments.at(0).toString() == format);
92 QVERIFY(arguments.at(0).toString() == format);
93
93
94 m_series->setPointLabelsFormat(QString());
94 m_series->setPointLabelsFormat(QString());
95 TRY_COMPARE(labelsFormatSpy.count(), 1);
95 TRY_COMPARE(labelsFormatSpy.count(), 1);
96 arguments = labelsFormatSpy.takeFirst();
96 arguments = labelsFormatSpy.takeFirst();
97 QVERIFY(arguments.at(0).toString() == QString());
97 QVERIFY(arguments.at(0).toString() == QString());
98
98
99 }
99 }
100
100
101 void tst_QXYSeries::pointLabelsVisible()
101 void tst_QXYSeries::pointLabelsVisible()
102 {
102 {
103 QSignalSpy labelsVisibleSpy(m_series, SIGNAL(pointLabelsVisibilityChanged(bool)));
103 QSignalSpy labelsVisibleSpy(m_series, SIGNAL(pointLabelsVisibilityChanged(bool)));
104 QCOMPARE(m_series->pointLabelsVisible(), false);
104 QCOMPARE(m_series->pointLabelsVisible(), false);
105
105
106 m_series->setPointLabelsVisible();
106 m_series->setPointLabelsVisible();
107 QCOMPARE(m_series->pointLabelsVisible(), true);
107 QCOMPARE(m_series->pointLabelsVisible(), true);
108 TRY_COMPARE(labelsVisibleSpy.count(), 1);
108 TRY_COMPARE(labelsVisibleSpy.count(), 1);
109 QList<QVariant> arguments = labelsVisibleSpy.takeFirst();
109 QList<QVariant> arguments = labelsVisibleSpy.takeFirst();
110 QVERIFY(arguments.at(0).toBool() == true);
110 QVERIFY(arguments.at(0).toBool() == true);
111
111
112 m_series->setPointLabelsVisible(false);
112 m_series->setPointLabelsVisible(false);
113 QCOMPARE(m_series->pointLabelsVisible(), false);
113 QCOMPARE(m_series->pointLabelsVisible(), false);
114 TRY_COMPARE(labelsVisibleSpy.count(), 1);
114 TRY_COMPARE(labelsVisibleSpy.count(), 1);
115 arguments = labelsVisibleSpy.takeFirst();
115 arguments = labelsVisibleSpy.takeFirst();
116 QVERIFY(arguments.at(0).toBool() == false);
116 QVERIFY(arguments.at(0).toBool() == false);
117 }
117 }
118
118
119 void tst_QXYSeries::pointLabelsFont()
119 void tst_QXYSeries::pointLabelsFont()
120 {
120 {
121 QFont defaultFont(m_series->pointLabelsFont());
121 QFont defaultFont(m_series->pointLabelsFont());
122 QSignalSpy labelsFontSpy(m_series, SIGNAL(pointLabelsFontChanged(QFont)));
122 QSignalSpy labelsFontSpy(m_series, SIGNAL(pointLabelsFontChanged(QFont)));
123
123
124 QFont font("Times", 10);
124 QFont font("Times", 10);
125 m_series->setPointLabelsFont(font);
125 m_series->setPointLabelsFont(font);
126 TRY_COMPARE(labelsFontSpy.count(), 1);
126 TRY_COMPARE(labelsFontSpy.count(), 1);
127 QList<QVariant> arguments = labelsFontSpy.takeFirst();
127 QList<QVariant> arguments = labelsFontSpy.takeFirst();
128 QVERIFY(arguments.at(0).value<QFont>() == font);
128 QVERIFY(arguments.at(0).value<QFont>() == font);
129
129
130 m_series->setPointLabelsFont(defaultFont);
130 m_series->setPointLabelsFont(defaultFont);
131 TRY_COMPARE(labelsFontSpy.count(), 1);
131 TRY_COMPARE(labelsFontSpy.count(), 1);
132 arguments = labelsFontSpy.takeFirst();
132 arguments = labelsFontSpy.takeFirst();
133 QVERIFY(arguments.at(0).value<QFont>() == defaultFont);
133 QVERIFY(arguments.at(0).value<QFont>() == defaultFont);
134
134
135 }
135 }
136
136
137 void tst_QXYSeries::pointLabelsColor()
137 void tst_QXYSeries::pointLabelsColor()
138 {
138 {
139 QColor defaultColor(QPen().color());
139 QColor defaultColor(QPen().color());
140 QSignalSpy labelsColorSpy(m_series, SIGNAL(pointLabelsColorChanged(QColor)));
140 QSignalSpy labelsColorSpy(m_series, SIGNAL(pointLabelsColorChanged(QColor)));
141 QCOMPARE(m_series->pointLabelsColor(), defaultColor);
141 QCOMPARE(m_series->pointLabelsColor(), defaultColor);
142
142
143 QColor color(Qt::blue);
143 QColor color(Qt::blue);
144 m_series->setPointLabelsColor(color);
144 m_series->setPointLabelsColor(color);
145 TRY_COMPARE(labelsColorSpy.count(), 1);
145 TRY_COMPARE(labelsColorSpy.count(), 1);
146 QList<QVariant> arguments = labelsColorSpy.takeFirst();
146 QList<QVariant> arguments = labelsColorSpy.takeFirst();
147 QVERIFY(arguments.at(0).value<QColor>() == color);
147 QVERIFY(arguments.at(0).value<QColor>() == color);
148
148
149 m_series->setPointLabelsColor(defaultColor);
149 m_series->setPointLabelsColor(defaultColor);
150 TRY_COMPARE(labelsColorSpy.count(), 1);
150 TRY_COMPARE(labelsColorSpy.count(), 1);
151 arguments = labelsColorSpy.takeFirst();
151 arguments = labelsColorSpy.takeFirst();
152 QVERIFY(arguments.at(0).value<QColor>() == defaultColor);
152 QVERIFY(arguments.at(0).value<QColor>() == defaultColor);
153 }
153 }
154
154
155 void tst_QXYSeries::pointLabelsClipping()
155 void tst_QXYSeries::pointLabelsClipping()
156 {
156 {
157 QSignalSpy labelsClippingSpy(m_series, SIGNAL(pointLabelsClippingChanged(bool)));
157 QSignalSpy labelsClippingSpy(m_series, SIGNAL(pointLabelsClippingChanged(bool)));
158 QCOMPARE(m_series->pointLabelsClipping(), true);
158 QCOMPARE(m_series->pointLabelsClipping(), true);
159
159
160 m_series->setPointLabelsClipping(false);
160 m_series->setPointLabelsClipping(false);
161 QCOMPARE(m_series->pointLabelsClipping(), false);
161 QCOMPARE(m_series->pointLabelsClipping(), false);
162 TRY_COMPARE(labelsClippingSpy.count(), 1);
162 TRY_COMPARE(labelsClippingSpy.count(), 1);
163 QList<QVariant> arguments = labelsClippingSpy.takeFirst();
163 QList<QVariant> arguments = labelsClippingSpy.takeFirst();
164 QVERIFY(arguments.at(0).toBool() == false);
164 QVERIFY(arguments.at(0).toBool() == false);
165
165
166 m_series->setPointLabelsClipping();
166 m_series->setPointLabelsClipping();
167 QCOMPARE(m_series->pointLabelsClipping(), true);
167 QCOMPARE(m_series->pointLabelsClipping(), true);
168 TRY_COMPARE(labelsClippingSpy.count(), 1);
168 TRY_COMPARE(labelsClippingSpy.count(), 1);
169 arguments = labelsClippingSpy.takeFirst();
169 arguments = labelsClippingSpy.takeFirst();
170 QVERIFY(arguments.at(0).toBool() == true);
170 QVERIFY(arguments.at(0).toBool() == true);
171 }
171 }
172
172
173 void tst_QXYSeries::append_data()
173 void tst_QXYSeries::append_data()
174 {
174 {
175 QTest::addColumn< QList<QPointF> >("points");
175 QTest::addColumn< QList<QPointF> >("points");
176 QTest::addColumn< QList<QPointF> >("otherPoints");
176 QTest::addColumn< QList<QPointF> >("otherPoints");
177 QTest::newRow("0,0 1,1 2,2 3,3")
177 QTest::newRow("0,0 1,1 2,2 3,3")
178 << (QList<QPointF>() << QPointF(0,0) << QPointF(1,1) << QPointF(2,2) << QPointF(3,3))
178 << (QList<QPointF>() << QPointF(0,0) << QPointF(1,1) << QPointF(2,2) << QPointF(3,3))
179 << (QList<QPointF>() << QPointF(4,4) << QPointF(5,5) << QPointF(6,6) << QPointF(7,7));
179 << (QList<QPointF>() << QPointF(4,4) << QPointF(5,5) << QPointF(6,6) << QPointF(7,7));
180 QTest::newRow("0,0 -1,-1 -2,-2 -3,-3")
180 QTest::newRow("0,0 -1,-1 -2,-2 -3,-3")
181 << (QList<QPointF>() << QPointF(0,0) << QPointF(-1,-1) << QPointF(-2,-2) << QPointF(-3,-3))
181 << (QList<QPointF>() << QPointF(0,0) << QPointF(-1,-1) << QPointF(-2,-2) << QPointF(-3,-3))
182 << (QList<QPointF>() << QPointF(-4,-4) << QPointF(-5,-5) << QPointF(-6,-6) << QPointF(-7,-7));
182 << (QList<QPointF>() << QPointF(-4,-4) << QPointF(-5,-5) << QPointF(-6,-6) << QPointF(-7,-7));
183 }
183 }
184
184
185
185
186 void tst_QXYSeries::append_raw_data()
186 void tst_QXYSeries::append_raw_data()
187 {
187 {
188 append_data();
188 append_data();
189 }
189 }
190
190
191 void tst_QXYSeries::append_raw()
191 void tst_QXYSeries::append_raw()
192 {
192 {
193 QFETCH(QList<QPointF>, points);
193 QFETCH(QList<QPointF>, points);
194 QFETCH(QList<QPointF>, otherPoints);
194 QFETCH(QList<QPointF>, otherPoints);
195 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
195 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
196 QSignalSpy addedSpy(m_series, SIGNAL(pointAdded(int)));
196 QSignalSpy addedSpy(m_series, SIGNAL(pointAdded(int)));
197 m_series->append(points);
197 m_series->append(points);
198 TRY_COMPARE(spy0.count(), 0);
198 TRY_COMPARE(spy0.count(), 0);
199 TRY_COMPARE(addedSpy.count(), points.count());
199 TRY_COMPARE(addedSpy.count(), points.count());
200 QCOMPARE(m_series->points(), points);
200 QCOMPARE(m_series->points(), points);
201 QCOMPARE(m_series->pointsVector(), points.toVector());
201
202
202 // Process events between appends
203 // Process events between appends
203 foreach (const QPointF &point, otherPoints) {
204 foreach (const QPointF &point, otherPoints) {
204 m_series->append(point);
205 m_series->append(point);
205 QApplication::processEvents();
206 QApplication::processEvents();
206 }
207 }
207 }
208 }
208
209
209 void tst_QXYSeries::chart_append_data()
210 void tst_QXYSeries::chart_append_data()
210 {
211 {
211 append_data();
212 append_data();
212 }
213 }
213
214
214 void tst_QXYSeries::chart_append()
215 void tst_QXYSeries::chart_append()
215 {
216 {
216 append_raw();
217 append_raw();
217 m_chart->addSeries(m_series);
218 m_chart->addSeries(m_series);
218 m_view->show();
219 m_view->show();
219 QTest::qWaitForWindowShown(m_view);
220 QTest::qWaitForWindowShown(m_view);
220 }
221 }
221
222
222 void tst_QXYSeries::append_chart_data()
223 void tst_QXYSeries::append_chart_data()
223 {
224 {
224 append_data();
225 append_data();
225 }
226 }
226
227
227 void tst_QXYSeries::append_chart()
228 void tst_QXYSeries::append_chart()
228 {
229 {
229 m_view->show();
230 m_view->show();
230 m_chart->addSeries(m_series);
231 m_chart->addSeries(m_series);
231 QTest::qWaitForWindowShown(m_view);
232 QTest::qWaitForWindowShown(m_view);
232 append_raw();
233 append_raw();
233
234
234 }
235 }
235
236
236 void tst_QXYSeries::append_chart_animation_data()
237 void tst_QXYSeries::append_chart_animation_data()
237 {
238 {
238 append_data();
239 append_data();
239 }
240 }
240
241
241 void tst_QXYSeries::append_chart_animation()
242 void tst_QXYSeries::append_chart_animation()
242 {
243 {
243 m_chart->setAnimationOptions(QChart::AllAnimations);
244 m_chart->setAnimationOptions(QChart::AllAnimations);
244 append_chart();
245 append_chart();
245 }
246 }
246
247
247 void tst_QXYSeries::count_data()
248 void tst_QXYSeries::count_data()
248 {
249 {
249 QTest::addColumn<int>("count");
250 QTest::addColumn<int>("count");
250 QTest::newRow("0") << 0;
251 QTest::newRow("0") << 0;
251 QTest::newRow("5") << 5;
252 QTest::newRow("5") << 5;
252 QTest::newRow("10") << 5;
253 QTest::newRow("10") << 5;
253 }
254 }
254
255
255 void tst_QXYSeries::count_raw_data()
256 void tst_QXYSeries::count_raw_data()
256 {
257 {
257 count_data();
258 count_data();
258 }
259 }
259
260
260 void tst_QXYSeries::count_raw()
261 void tst_QXYSeries::count_raw()
261 {
262 {
262 QFETCH(int, count);
263 QFETCH(int, count);
263
264
264 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
265 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
265
266
266 for(int i=0 ; i< count; ++i)
267 for(int i=0 ; i< count; ++i)
267 m_series->append(i,i);
268 m_series->append(i,i);
268
269
269 TRY_COMPARE(spy0.count(), 0);
270 TRY_COMPARE(spy0.count(), 0);
270 QCOMPARE(m_series->count(), count);
271 QCOMPARE(m_series->count(), count);
271 }
272 }
272
273
273 void tst_QXYSeries::remove_raw_data()
274 void tst_QXYSeries::remove_raw_data()
274 {
275 {
275 append_data();
276 append_data();
276 }
277 }
277
278
278 void tst_QXYSeries::remove_raw()
279 void tst_QXYSeries::remove_raw()
279 {
280 {
280 QFETCH(QList<QPointF>, points);
281 QFETCH(QList<QPointF>, points);
281 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
282 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
282 m_series->append(points);
283 m_series->append(points);
283 TRY_COMPARE(spy0.count(), 0);
284 TRY_COMPARE(spy0.count(), 0);
284 QCOMPARE(m_series->points(), points);
285 QCOMPARE(m_series->points(), points);
285
286
286 foreach (const QPointF& point,points)
287 foreach (const QPointF& point,points)
287 m_series->remove(point);
288 m_series->remove(point);
288
289
289 QCOMPARE(m_series->points().count(), 0);
290 QCOMPARE(m_series->points().count(), 0);
290 TRY_COMPARE(spy0.count(), 0);
291 TRY_COMPARE(spy0.count(), 0);
291
292
292 m_series->append(points);
293 m_series->append(points);
293 QCOMPARE(m_series->points(), points);
294 QCOMPARE(m_series->points(), points);
294
295
295 //reverse order
296 //reverse order
296 for(int i = points.count()-1 ; i>=0; i--){
297 for(int i = points.count()-1 ; i>=0; i--){
297 m_series->remove(points[i]);
298 m_series->remove(points[i]);
298 }
299 }
299 QCOMPARE(m_series->points().count(), 0);
300 QCOMPARE(m_series->points().count(), 0);
300
301
301 QApplication::processEvents();
302 QApplication::processEvents();
302
303
303 // Process events between removes
304 // Process events between removes
304 m_series->append(points);
305 m_series->append(points);
305 QCOMPARE(m_series->points(), points);
306 QCOMPARE(m_series->points(), points);
306 foreach (const QPointF &point, points) {
307 foreach (const QPointF &point, points) {
307 m_series->remove(point);
308 m_series->remove(point);
308 QApplication::processEvents();
309 QApplication::processEvents();
309 }
310 }
310
311
311 // Actual meaningful delay between removes, but still shorter than animation duration
312 // Actual meaningful delay between removes, but still shorter than animation duration
312 // (simulate e.g. spamming a hypothetical "remove last point"-button)
313 // (simulate e.g. spamming a hypothetical "remove last point"-button)
313 QList<QPointF> bunchOfPoints;
314 QList<QPointF> bunchOfPoints;
314 for (int i = 0; i < 10; i++)
315 for (int i = 0; i < 10; i++)
315 bunchOfPoints.append(QPointF(i, (qreal) rand() / (qreal) RAND_MAX));
316 bunchOfPoints.append(QPointF(i, (qreal) rand() / (qreal) RAND_MAX));
316 m_series->replace(bunchOfPoints);
317 m_series->replace(bunchOfPoints);
317 QCOMPARE(m_series->points(), bunchOfPoints);
318 QCOMPARE(m_series->points(), bunchOfPoints);
318 QTest::qWait(1500); // Wait for append animations to be over
319 QTest::qWait(1500); // Wait for append animations to be over
319 for (int i = bunchOfPoints.count() - 1; i >= 0; i--) {
320 for (int i = bunchOfPoints.count() - 1; i >= 0; i--) {
320 m_series->remove(bunchOfPoints.at(i));
321 m_series->remove(bunchOfPoints.at(i));
321 QTest::qWait(50);
322 QTest::qWait(50);
322 }
323 }
323 QCOMPARE(m_series->points().count(), 0);
324 QCOMPARE(m_series->points().count(), 0);
324
325
325 // Removal using index
326 // Removal using index
326 for (int i = 0; i < 10; i++)
327 for (int i = 0; i < 10; i++)
327 bunchOfPoints.append(QPointF(i, (qreal) rand() / (qreal) RAND_MAX));
328 bunchOfPoints.append(QPointF(i, (qreal) rand() / (qreal) RAND_MAX));
328 m_series->replace(bunchOfPoints);
329 m_series->replace(bunchOfPoints);
329 m_series->remove(5);
330 m_series->remove(5);
330 m_series->remove(0);
331 m_series->remove(0);
331 QCOMPARE(m_series->points().count(), (bunchOfPoints.count() - 2));
332 QCOMPARE(m_series->points().count(), (bunchOfPoints.count() - 2));
332 for (int i = bunchOfPoints.count() - 3; i >= 0; i--) {
333 for (int i = bunchOfPoints.count() - 3; i >= 0; i--) {
333 m_series->remove(i);
334 m_series->remove(i);
334 QCOMPARE(m_series->points().count(), i);
335 QCOMPARE(m_series->points().count(), i);
335 }
336 }
336 QCOMPARE(m_series->points().count(), 0);
337 QCOMPARE(m_series->points().count(), 0);
337
338
338 // Multiple removal using index
339 // Multiple removal using index
339 for (int i = 0; i < 10; i++)
340 for (int i = 0; i < 10; i++)
340 bunchOfPoints.append(QPointF(i, (qreal) rand() / (qreal) RAND_MAX));
341 bunchOfPoints.append(QPointF(i, (qreal) rand() / (qreal) RAND_MAX));
341 m_series->replace(bunchOfPoints);
342 m_series->replace(bunchOfPoints);
342 m_series->removePoints(5, 2);
343 m_series->removePoints(5, 2);
343 m_series->removePoints(0, 3);
344 m_series->removePoints(0, 3);
344 QCOMPARE(m_series->points().count(), (bunchOfPoints.count() - 5));
345 QCOMPARE(m_series->points().count(), (bunchOfPoints.count() - 5));
345 m_series->removePoints(0, (bunchOfPoints.count() - 5));
346 m_series->removePoints(0, (bunchOfPoints.count() - 5));
346 QCOMPARE(m_series->points().count(), 0);
347 QCOMPARE(m_series->points().count(), 0);
347 }
348 }
348
349
349 void tst_QXYSeries::remove_chart_data()
350 void tst_QXYSeries::remove_chart_data()
350 {
351 {
351 append_data();
352 append_data();
352 }
353 }
353
354
354 void tst_QXYSeries::remove_chart()
355 void tst_QXYSeries::remove_chart()
355 {
356 {
356 m_view->show();
357 m_view->show();
357 m_chart->addSeries(m_series);
358 m_chart->addSeries(m_series);
358 QTest::qWaitForWindowShown(m_view);
359 QTest::qWaitForWindowShown(m_view);
359 remove_raw();
360 remove_raw();
360 }
361 }
361
362
362 void tst_QXYSeries::remove_chart_animation_data()
363 void tst_QXYSeries::remove_chart_animation_data()
363 {
364 {
364 append_data();
365 append_data();
365 }
366 }
366
367
367 void tst_QXYSeries::remove_chart_animation()
368 void tst_QXYSeries::remove_chart_animation()
368 {
369 {
369 m_chart->setAnimationOptions(QChart::AllAnimations);
370 m_chart->setAnimationOptions(QChart::AllAnimations);
370 remove_chart();
371 remove_chart();
371 }
372 }
372
373
373
374
374 void tst_QXYSeries::clear_raw_data()
375 void tst_QXYSeries::clear_raw_data()
375 {
376 {
376 append_data();
377 append_data();
377 }
378 }
378
379
379 void tst_QXYSeries::clear_raw()
380 void tst_QXYSeries::clear_raw()
380 {
381 {
381 QFETCH(QList<QPointF>, points);
382 QFETCH(QList<QPointF>, points);
382 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
383 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
383 m_series->append(points);
384 m_series->append(points);
384 TRY_COMPARE(spy0.count(), 0);
385 TRY_COMPARE(spy0.count(), 0);
385 QCOMPARE(m_series->points(), points);
386 QCOMPARE(m_series->points(), points);
386 m_series->clear();
387 m_series->clear();
387 TRY_COMPARE(spy0.count(), 0);
388 TRY_COMPARE(spy0.count(), 0);
388 QCOMPARE(m_series->points().count(), 0);
389 QCOMPARE(m_series->points().count(), 0);
389
390
390 QApplication::processEvents();
391 QApplication::processEvents();
391 }
392 }
392
393
393 void tst_QXYSeries::clear_chart_data()
394 void tst_QXYSeries::clear_chart_data()
394 {
395 {
395 append_data();
396 append_data();
396 }
397 }
397
398
398 void tst_QXYSeries::clear_chart()
399 void tst_QXYSeries::clear_chart()
399 {
400 {
400 m_view->show();
401 m_view->show();
401 m_chart->addSeries(m_series);
402 m_chart->addSeries(m_series);
402 QTest::qWaitForWindowShown(m_view);
403 QTest::qWaitForWindowShown(m_view);
403 clear_raw();
404 clear_raw();
404 }
405 }
405
406
406 void tst_QXYSeries::clear_chart_animation_data()
407 void tst_QXYSeries::clear_chart_animation_data()
407 {
408 {
408 append_data();
409 append_data();
409 }
410 }
410
411
411 void tst_QXYSeries::clear_chart_animation()
412 void tst_QXYSeries::clear_chart_animation()
412 {
413 {
413 m_chart->setAnimationOptions(QChart::AllAnimations);
414 m_chart->setAnimationOptions(QChart::AllAnimations);
414 clear_chart();
415 clear_chart();
415 }
416 }
416
417
417 void tst_QXYSeries::replace_raw_data()
418 void tst_QXYSeries::replace_raw_data()
418 {
419 {
419 append_data();
420 append_data();
420 }
421 }
421
422
422 void tst_QXYSeries::replace_raw()
423 void tst_QXYSeries::replace_raw()
423 {
424 {
424 QFETCH(QList<QPointF>, points);
425 QFETCH(QList<QPointF>, points);
425 QFETCH(QList<QPointF>, otherPoints);
426 QFETCH(QList<QPointF>, otherPoints);
426 QSignalSpy pointReplacedSpy(m_series, SIGNAL(pointReplaced(int)));
427 QSignalSpy pointReplacedSpy(m_series, SIGNAL(pointReplaced(int)));
427 QSignalSpy pointsReplacedSpy(m_series, SIGNAL(pointsReplaced()));
428 QSignalSpy pointsReplacedSpy(m_series, SIGNAL(pointsReplaced()));
428 m_series->append(points);
429 m_series->append(points);
429 TRY_COMPARE(pointReplacedSpy.count(), 0);
430 TRY_COMPARE(pointReplacedSpy.count(), 0);
430 TRY_COMPARE(pointsReplacedSpy.count(), 0);
431 TRY_COMPARE(pointsReplacedSpy.count(), 0);
431 QCOMPARE(m_series->points(), points);
432 QCOMPARE(m_series->points(), points);
432
433
433 foreach (const QPointF& point, points)
434 foreach (const QPointF& point, points)
434 m_series->replace(point.x(),point.y(),point.x(),0);
435 m_series->replace(point.x(),point.y(),point.x(),0);
435 TRY_COMPARE(pointReplacedSpy.count(), points.count());
436 TRY_COMPARE(pointReplacedSpy.count(), points.count());
436 TRY_COMPARE(pointsReplacedSpy.count(), 0);
437 TRY_COMPARE(pointsReplacedSpy.count(), 0);
437
438
438 // Replace a point that does not exist
439 // Replace a point that does not exist
439 m_series->replace(-123, 999, 0, 0);
440 m_series->replace(-123, 999, 0, 0);
440 TRY_COMPARE(pointReplacedSpy.count(), points.count());
441 TRY_COMPARE(pointReplacedSpy.count(), points.count());
441 TRY_COMPARE(pointsReplacedSpy.count(), 0);
442 TRY_COMPARE(pointsReplacedSpy.count(), 0);
442
443
443 QList<QPointF> newPoints = m_series->points();
444 QList<QPointF> newPoints = m_series->points();
444 QCOMPARE(newPoints.count(), points.count());
445 QCOMPARE(newPoints.count(), points.count());
445 for(int i =0 ; i<points.count() ; ++i) {
446 for(int i =0 ; i<points.count() ; ++i) {
446 QCOMPARE(points[i].x(), newPoints[i].x());
447 QCOMPARE(points[i].x(), newPoints[i].x());
447 QCOMPARE(newPoints[i].y(), 0.0);
448 QCOMPARE(newPoints[i].y(), 0.0);
448 }
449 }
449
450
450 // Replace all points
451 // Replace all points
451 QList<QPointF> allPoints;
452 QList<QPointF> allPoints;
452 for (int i = 0; i < 10; i++)
453 for (int i = 0; i < 10; i++)
453 allPoints.append(QPointF(i, (qreal) rand() / (qreal) RAND_MAX));
454 allPoints.append(QPointF(i, (qreal) rand() / (qreal) RAND_MAX));
454 m_series->replace(allPoints);
455 m_series->replace(allPoints);
455 TRY_COMPARE(pointReplacedSpy.count(), points.count());
456 TRY_COMPARE(pointReplacedSpy.count(), points.count());
456 TRY_COMPARE(pointsReplacedSpy.count(), 1);
457 TRY_COMPARE(pointsReplacedSpy.count(), 1);
457
458
458 m_series->replace(points);
459 m_series->replace(points);
459 QApplication::processEvents();
460 QApplication::processEvents();
460
461
461 // Process events between replaces
462 // Process events between replaces
462 for (int i = 0; i < points.count(); ++i) {
463 for (int i = 0; i < points.count(); ++i) {
463 m_series->replace(points.at(i), otherPoints.at(i));
464 m_series->replace(points.at(i), otherPoints.at(i));
464 QApplication::processEvents();
465 QApplication::processEvents();
465 }
466 }
466
467
467 newPoints = m_series->points();
468 newPoints = m_series->points();
468 QCOMPARE(newPoints.count(), points.count());
469 QCOMPARE(newPoints.count(), points.count());
469 for (int i = 0; i < points.count(); ++i) {
470 for (int i = 0; i < points.count(); ++i) {
470 QCOMPARE(otherPoints.at(i).x(), newPoints.at(i).x());
471 QCOMPARE(otherPoints.at(i).x(), newPoints.at(i).x());
471 QCOMPARE(otherPoints.at(i).y(), newPoints.at(i).y());
472 QCOMPARE(otherPoints.at(i).y(), newPoints.at(i).y());
472 }
473 }
473
474
474 // Append followed by a replace shouldn't crash
475 // Append followed by a replace shouldn't crash
475 m_series->clear();
476 m_series->clear();
476 m_series->append(QPointF(22,22));
477 m_series->append(QPointF(22,22));
477 m_series->append(QPointF(23,23));
478 m_series->append(QPointF(23,23));
478 QApplication::processEvents();
479 QApplication::processEvents();
479 m_series->replace(QPointF(23,23), otherPoints.at(1));
480 m_series->replace(QPointF(23,23), otherPoints.at(1));
480 QCOMPARE(m_series->points().at(1).x(), otherPoints.at(1).x());
481 QCOMPARE(m_series->points().at(1).x(), otherPoints.at(1).x());
481 QCOMPARE(m_series->points().at(1).y(), otherPoints.at(1).y());
482 QCOMPARE(m_series->points().at(1).y(), otherPoints.at(1).y());
482
483
483 // Replace using index
484 // Replace using index
484 m_series->append(otherPoints);
485 m_series->append(otherPoints);
485 m_series->replace(0, QPointF(333, 333));
486 m_series->replace(0, QPointF(333, 333));
486 m_series->replace(3, 444, 444);
487 m_series->replace(3, 444, 444);
487 m_series->replace(m_series->count() - 1, QPointF(555, 555));
488 m_series->replace(m_series->count() - 1, QPointF(555, 555));
488 QCOMPARE(m_series->points().at(0), QPointF(333, 333));
489 QCOMPARE(m_series->points().at(0), QPointF(333, 333));
489 QCOMPARE(m_series->points().at(3), QPointF(444, 444));
490 QCOMPARE(m_series->points().at(3), QPointF(444, 444));
490 QCOMPARE(m_series->points().at(m_series->count() - 1), QPointF(555, 555));
491 QCOMPARE(m_series->points().at(m_series->count() - 1), QPointF(555, 555));
491 }
492 }
492
493
493
494
494 void tst_QXYSeries::replace_chart_data()
495 void tst_QXYSeries::replace_chart_data()
495 {
496 {
496 append_data();
497 append_data();
497 }
498 }
498
499
499 void tst_QXYSeries::replace_chart()
500 void tst_QXYSeries::replace_chart()
500 {
501 {
501 m_view->show();
502 m_view->show();
502 m_chart->addSeries(m_series);
503 m_chart->addSeries(m_series);
503 QTest::qWaitForWindowShown(m_view);
504 QTest::qWaitForWindowShown(m_view);
504 replace_raw();
505 replace_raw();
505 }
506 }
506
507
507 void tst_QXYSeries::replace_chart_animation_data()
508 void tst_QXYSeries::replace_chart_animation_data()
508 {
509 {
509 append_data();
510 append_data();
510 }
511 }
511
512
512 void tst_QXYSeries::replace_chart_animation()
513 void tst_QXYSeries::replace_chart_animation()
513 {
514 {
514 m_chart->setAnimationOptions(QChart::AllAnimations);
515 m_chart->setAnimationOptions(QChart::AllAnimations);
515 replace_chart();
516 replace_chart();
516 }
517 }
517
518
518 void tst_QXYSeries::insert_data()
519 void tst_QXYSeries::insert_data()
519 {
520 {
520 append_data();
521 append_data();
521 }
522 }
522
523
523 void tst_QXYSeries::insert()
524 void tst_QXYSeries::insert()
524 {
525 {
525 QFETCH(QList<QPointF>, points);
526 QFETCH(QList<QPointF>, points);
526 m_series->append(points);
527 m_series->append(points);
527
528
528 QSignalSpy addedSpy(m_series, SIGNAL(pointAdded(int)));
529 QSignalSpy addedSpy(m_series, SIGNAL(pointAdded(int)));
529
530
530 m_series->insert(0, QPointF(5, 5));
531 m_series->insert(0, QPointF(5, 5));
531 TRY_COMPARE(addedSpy.count(), 1);
532 TRY_COMPARE(addedSpy.count(), 1);
532 QCOMPARE(m_series->points().count(), points.count() + 1);
533 QCOMPARE(m_series->points().count(), points.count() + 1);
533
534
534 m_series->insert(m_series->count(), QPointF(6, 6));
535 m_series->insert(m_series->count(), QPointF(6, 6));
535 TRY_COMPARE(addedSpy.count(), 2);
536 TRY_COMPARE(addedSpy.count(), 2);
536 QCOMPARE(m_series->points().count(), points.count() + 2);
537 QCOMPARE(m_series->points().count(), points.count() + 2);
537 }
538 }
538
539
539 void tst_QXYSeries::oper_data()
540 void tst_QXYSeries::oper_data()
540 {
541 {
541 append_data();
542 append_data();
542 }
543 }
543
544
544 void tst_QXYSeries::oper()
545 void tst_QXYSeries::oper()
545 {
546 {
546 QFETCH(QList<QPointF>, points);
547 QFETCH(QList<QPointF>, points);
547
548
548 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
549 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
549
550
550 foreach (const QPointF& point,points)
551 foreach (const QPointF& point,points)
551 {
552 {
552 *m_series<<point;
553 *m_series<<point;
553 }
554 }
554
555
555 QCOMPARE(m_series->points(), points);
556 QCOMPARE(m_series->points(), points);
556 TRY_COMPARE(spy0.count(), 0);
557 TRY_COMPARE(spy0.count(), 0);
557 }
558 }
558
559
559
560
560 void tst_QXYSeries::pen_data()
561 void tst_QXYSeries::pen_data()
561 {
562 {
562 QTest::addColumn<QPen>("pen");
563 QTest::addColumn<QPen>("pen");
563 QTest::newRow("null") << QPen();
564 QTest::newRow("null") << QPen();
564 QTest::newRow("blue") << QPen(Qt::blue);
565 QTest::newRow("blue") << QPen(Qt::blue);
565 QTest::newRow("black") << QPen(Qt::black);
566 QTest::newRow("black") << QPen(Qt::black);
566 QTest::newRow("red") << QPen(Qt::red);
567 QTest::newRow("red") << QPen(Qt::red);
567 }
568 }
568
569
569 void tst_QXYSeries::pen()
570 void tst_QXYSeries::pen()
570 {
571 {
571 QFETCH(QPen, pen);
572 QFETCH(QPen, pen);
572
573
573 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
574 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
574 m_series->setPen(pen);
575 m_series->setPen(pen);
575
576
576 TRY_COMPARE(spy0.count(), 0);
577 TRY_COMPARE(spy0.count(), 0);
577 QCOMPARE(m_series->pen(), pen);
578 QCOMPARE(m_series->pen(), pen);
578
579
579 m_chart->addSeries(m_series);
580 m_chart->addSeries(m_series);
580
581
581 if (pen != QPen())
582 if (pen != QPen())
582 QCOMPARE(m_series->pen(), pen);
583 QCOMPARE(m_series->pen(), pen);
583
584
584 m_chart->setTheme(QChart::ChartThemeDark);
585 m_chart->setTheme(QChart::ChartThemeDark);
585
586
586 // setting a theme will overwrite all customizations
587 // setting a theme will overwrite all customizations
587 if (pen != QPen())
588 if (pen != QPen())
588 QVERIFY(m_series->pen() != pen);
589 QVERIFY(m_series->pen() != pen);
589 }
590 }
590
591
591 void tst_QXYSeries::pointsVisible_data()
592 void tst_QXYSeries::pointsVisible_data()
592 {
593 {
593 QTest::addColumn<bool>("pointsVisible");
594 QTest::addColumn<bool>("pointsVisible");
594 QTest::newRow("true") << true;
595 QTest::newRow("true") << true;
595 QTest::newRow("false") << false;
596 QTest::newRow("false") << false;
596 }
597 }
597
598
598 void tst_QXYSeries::pointsVisible_raw_data()
599 void tst_QXYSeries::pointsVisible_raw_data()
599 {
600 {
600 pointsVisible_data();
601 pointsVisible_data();
601 }
602 }
602
603
603 void tst_QXYSeries::pointsVisible_raw()
604 void tst_QXYSeries::pointsVisible_raw()
604 {
605 {
605 QFETCH(bool, pointsVisible);
606 QFETCH(bool, pointsVisible);
606 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
607 QSignalSpy spy0(m_series, SIGNAL(clicked(QPointF)));
607 m_series->setPointsVisible(pointsVisible);
608 m_series->setPointsVisible(pointsVisible);
608 TRY_COMPARE(spy0.count(), 0);
609 TRY_COMPARE(spy0.count(), 0);
609 QCOMPARE(m_series->pointsVisible(), pointsVisible);
610 QCOMPARE(m_series->pointsVisible(), pointsVisible);
610 }
611 }
611
612
612 void tst_QXYSeries::changedSignals()
613 void tst_QXYSeries::changedSignals()
613 {
614 {
614 QSignalSpy visibleSpy(m_series, SIGNAL(visibleChanged()));
615 QSignalSpy visibleSpy(m_series, SIGNAL(visibleChanged()));
615 QSignalSpy nameSpy(m_series, SIGNAL(nameChanged()));
616 QSignalSpy nameSpy(m_series, SIGNAL(nameChanged()));
616 QSignalSpy colorSpy(m_series, SIGNAL(colorChanged(QColor)));
617 QSignalSpy colorSpy(m_series, SIGNAL(colorChanged(QColor)));
617
618
618 // Visibility
619 // Visibility
619 m_series->setVisible(false);
620 m_series->setVisible(false);
620 m_series->setVisible(false);
621 m_series->setVisible(false);
621 TRY_COMPARE(visibleSpy.count(), 1);
622 TRY_COMPARE(visibleSpy.count(), 1);
622 m_series->setVisible(true);
623 m_series->setVisible(true);
623 TRY_COMPARE(visibleSpy.count(), 2);
624 TRY_COMPARE(visibleSpy.count(), 2);
624
625
625 // Color
626 // Color
626 m_series->setColor(QColor("aliceblue"));
627 m_series->setColor(QColor("aliceblue"));
627 TRY_COMPARE(colorSpy.count(), 1);
628 TRY_COMPARE(colorSpy.count(), 1);
628
629
629 // Pen and Brush
630 // Pen and Brush
630 QPen p = m_series->pen();
631 QPen p = m_series->pen();
631 p.setColor("aquamarine");
632 p.setColor("aquamarine");
632 m_series->setPen(p);
633 m_series->setPen(p);
633 QBrush b = m_series->brush();
634 QBrush b = m_series->brush();
634 b.setColor("beige");
635 b.setColor("beige");
635 m_series->setBrush(b);
636 m_series->setBrush(b);
636 TRY_COMPARE(colorSpy.count(), 2);
637 TRY_COMPARE(colorSpy.count(), 2);
637
638
638 // Verify all the signals again, to make sure no extra signals were emitted
639 // Verify all the signals again, to make sure no extra signals were emitted
639 TRY_COMPARE(visibleSpy.count(), 2);
640 TRY_COMPARE(visibleSpy.count(), 2);
640 TRY_COMPARE(nameSpy.count(), 0);
641 TRY_COMPARE(nameSpy.count(), 0);
641 TRY_COMPARE(colorSpy.count(), 2);
642 TRY_COMPARE(colorSpy.count(), 2);
642 }
643 }
General Comments 0
You need to be logged in to leave comments. Login now