##// END OF EJS Templates
Merge remote-tracking branch 'origin/5.6' into 5.7...
Liang Qi -
r2866:bbf52870f4e3 merge
parent child
Show More
@@ -1,582 +1,585
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
4 ** Contact: https://www.qt.io/licensing/
5 **
5 **
6 ** This file is part of the Qt Charts module of the Qt Toolkit.
6 ** This file is part of the Qt Charts module of the Qt Toolkit.
7 **
7 **
8 ** $QT_BEGIN_LICENSE:GPL$
8 ** $QT_BEGIN_LICENSE:GPL$
9 ** Commercial License Usage
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
16 **
17 ** GNU General Public License Usage
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 or (at your option) any later version
19 ** General Public License version 3 or (at your option) any later version
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
22 ** included in the packaging of this file. Please review the following
22 ** included in the packaging of this file. Please review the following
23 ** information to ensure the GNU General Public License requirements will
23 ** information to ensure the GNU General Public License requirements will
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25 **
25 **
26 ** $QT_END_LICENSE$
26 ** $QT_END_LICENSE$
27 **
27 **
28 ****************************************************************************/
28 ****************************************************************************/
29 #include <private/chartpresenter_p.h>
29 #include <private/chartpresenter_p.h>
30 #include <QtCharts/QChart>
30 #include <QtCharts/QChart>
31 #include <private/chartitem_p.h>
31 #include <private/chartitem_p.h>
32 #include <private/qchart_p.h>
32 #include <private/qchart_p.h>
33 #include <QtCharts/QAbstractAxis>
33 #include <QtCharts/QAbstractAxis>
34 #include <private/qabstractaxis_p.h>
34 #include <private/qabstractaxis_p.h>
35 #include <private/chartdataset_p.h>
35 #include <private/chartdataset_p.h>
36 #include <private/chartanimation_p.h>
36 #include <private/chartanimation_p.h>
37 #include <private/qabstractseries_p.h>
37 #include <private/qabstractseries_p.h>
38 #include <QtCharts/QAreaSeries>
38 #include <QtCharts/QAreaSeries>
39 #include <private/chartaxiselement_p.h>
39 #include <private/chartaxiselement_p.h>
40 #include <private/chartbackground_p.h>
40 #include <private/chartbackground_p.h>
41 #include <private/cartesianchartlayout_p.h>
41 #include <private/cartesianchartlayout_p.h>
42 #include <private/polarchartlayout_p.h>
42 #include <private/polarchartlayout_p.h>
43 #include <private/charttitle_p.h>
43 #include <private/charttitle_p.h>
44 #include <QtCore/QTimer>
44 #include <QtCore/QTimer>
45 #include <QtGui/QTextDocument>
45 #include <QtGui/QTextDocument>
46 #include <QtWidgets/QGraphicsScene>
46 #include <QtWidgets/QGraphicsScene>
47 #include <QtWidgets/QGraphicsView>
47 #include <QtWidgets/QGraphicsView>
48
48
49 QT_CHARTS_BEGIN_NAMESPACE
49 QT_CHARTS_BEGIN_NAMESPACE
50
50
51 ChartPresenter::ChartPresenter(QChart *chart, QChart::ChartType type)
51 ChartPresenter::ChartPresenter(QChart *chart, QChart::ChartType type)
52 : QObject(chart),
52 : QObject(chart),
53 m_chart(chart),
53 m_chart(chart),
54 m_options(QChart::NoAnimation),
54 m_options(QChart::NoAnimation),
55 m_animationDuration(ChartAnimationDuration),
55 m_animationDuration(ChartAnimationDuration),
56 m_animationCurve(QEasingCurve::OutQuart),
56 m_animationCurve(QEasingCurve::OutQuart),
57 m_state(ShowState),
57 m_state(ShowState),
58 m_background(0),
58 m_background(0),
59 m_plotAreaBackground(0),
59 m_plotAreaBackground(0),
60 m_title(0),
60 m_title(0),
61 m_localizeNumbers(false)
61 m_localizeNumbers(false)
62 #ifndef QT_NO_OPENGL
62 #ifndef QT_NO_OPENGL
63 , m_glWidget(0)
63 , m_glWidget(0)
64 , m_glUseWidget(true)
64 , m_glUseWidget(true)
65 #endif
65 #endif
66 {
66 {
67 if (type == QChart::ChartTypeCartesian)
67 if (type == QChart::ChartTypeCartesian)
68 m_layout = new CartesianChartLayout(this);
68 m_layout = new CartesianChartLayout(this);
69 else if (type == QChart::ChartTypePolar)
69 else if (type == QChart::ChartTypePolar)
70 m_layout = new PolarChartLayout(this);
70 m_layout = new PolarChartLayout(this);
71 Q_ASSERT(m_layout);
71 Q_ASSERT(m_layout);
72 }
72 }
73
73
74 ChartPresenter::~ChartPresenter()
74 ChartPresenter::~ChartPresenter()
75 {
75 {
76 #ifndef QT_NO_OPENGL
76 #ifndef QT_NO_OPENGL
77 delete m_glWidget.data();
77 delete m_glWidget.data();
78 #endif
78 #endif
79 }
79 }
80
80
81 void ChartPresenter::setGeometry(const QRectF rect)
81 void ChartPresenter::setGeometry(const QRectF rect)
82 {
82 {
83 if (m_rect != rect) {
83 if (m_rect != rect) {
84 m_rect = rect;
84 m_rect = rect;
85 foreach (ChartItem *chart, m_chartItems) {
85 foreach (ChartItem *chart, m_chartItems) {
86 chart->domain()->setSize(rect.size());
86 chart->domain()->setSize(rect.size());
87 chart->setPos(rect.topLeft());
87 chart->setPos(rect.topLeft());
88 }
88 }
89 #ifndef QT_NO_OPENGL
89 #ifndef QT_NO_OPENGL
90 if (!m_glWidget.isNull())
90 if (!m_glWidget.isNull())
91 m_glWidget->setGeometry(m_rect.toRect());
91 m_glWidget->setGeometry(m_rect.toRect());
92 #endif
92 #endif
93 emit plotAreaChanged(m_rect);
93 emit plotAreaChanged(m_rect);
94 }
94 }
95 }
95 }
96
96
97 QRectF ChartPresenter::geometry() const
97 QRectF ChartPresenter::geometry() const
98 {
98 {
99 return m_rect;
99 return m_rect;
100 }
100 }
101
101
102 void ChartPresenter::handleAxisAdded(QAbstractAxis *axis)
102 void ChartPresenter::handleAxisAdded(QAbstractAxis *axis)
103 {
103 {
104 axis->d_ptr->initializeGraphics(rootItem());
104 axis->d_ptr->initializeGraphics(rootItem());
105 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
105 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
106 ChartAxisElement *item = axis->d_ptr->axisItem();
106 ChartAxisElement *item = axis->d_ptr->axisItem();
107 item->setPresenter(this);
107 item->setPresenter(this);
108 item->setThemeManager(m_chart->d_ptr->m_themeManager);
108 item->setThemeManager(m_chart->d_ptr->m_themeManager);
109 m_axisItems<<item;
109 m_axisItems<<item;
110 m_axes<<axis;
110 m_axes<<axis;
111 m_layout->invalidate();
111 m_layout->invalidate();
112 }
112 }
113
113
114 void ChartPresenter::handleAxisRemoved(QAbstractAxis *axis)
114 void ChartPresenter::handleAxisRemoved(QAbstractAxis *axis)
115 {
115 {
116 ChartAxisElement *item = axis->d_ptr->m_item.take();
116 ChartAxisElement *item = axis->d_ptr->m_item.take();
117 if (item->animation())
117 if (item->animation())
118 item->animation()->stopAndDestroyLater();
118 item->animation()->stopAndDestroyLater();
119 item->hide();
119 item->hide();
120 item->disconnect();
120 item->disconnect();
121 item->deleteLater();
121 item->deleteLater();
122 m_axisItems.removeAll(item);
122 m_axisItems.removeAll(item);
123 m_axes.removeAll(axis);
123 m_axes.removeAll(axis);
124 m_layout->invalidate();
124 m_layout->invalidate();
125 }
125 }
126
126
127
127
128 void ChartPresenter::handleSeriesAdded(QAbstractSeries *series)
128 void ChartPresenter::handleSeriesAdded(QAbstractSeries *series)
129 {
129 {
130 series->d_ptr->initializeGraphics(rootItem());
130 series->d_ptr->initializeGraphics(rootItem());
131 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
131 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
132 series->d_ptr->setPresenter(this);
132 series->d_ptr->setPresenter(this);
133 ChartItem *chart = series->d_ptr->chartItem();
133 ChartItem *chart = series->d_ptr->chartItem();
134 chart->setPresenter(this);
134 chart->setPresenter(this);
135 chart->setThemeManager(m_chart->d_ptr->m_themeManager);
135 chart->setThemeManager(m_chart->d_ptr->m_themeManager);
136 chart->setDataSet(m_chart->d_ptr->m_dataset);
136 chart->setDataSet(m_chart->d_ptr->m_dataset);
137 chart->domain()->setSize(m_rect.size());
137 chart->domain()->setSize(m_rect.size());
138 chart->setPos(m_rect.topLeft());
138 chart->setPos(m_rect.topLeft());
139 chart->handleDomainUpdated(); //this could be moved to intializeGraphics when animator is refactored
139 chart->handleDomainUpdated(); //this could be moved to intializeGraphics when animator is refactored
140 m_chartItems<<chart;
140 m_chartItems<<chart;
141 m_series<<series;
141 m_series<<series;
142 m_layout->invalidate();
142 m_layout->invalidate();
143 }
143 }
144
144
145 void ChartPresenter::handleSeriesRemoved(QAbstractSeries *series)
145 void ChartPresenter::handleSeriesRemoved(QAbstractSeries *series)
146 {
146 {
147 ChartItem *chart = series->d_ptr->m_item.take();
147 ChartItem *chart = series->d_ptr->m_item.take();
148 chart->hide();
148 chart->hide();
149 chart->disconnect();
149 chart->disconnect();
150 chart->deleteLater();
150 chart->deleteLater();
151 if (chart->animation())
151 if (chart->animation())
152 chart->animation()->stopAndDestroyLater();
152 chart->animation()->stopAndDestroyLater();
153 m_chartItems.removeAll(chart);
153 m_chartItems.removeAll(chart);
154 m_series.removeAll(series);
154 m_series.removeAll(series);
155 m_layout->invalidate();
155 m_layout->invalidate();
156 }
156 }
157
157
158 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
158 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
159 {
159 {
160 if (m_options != options) {
160 if (m_options != options) {
161 QChart::AnimationOptions oldOptions = m_options;
161 QChart::AnimationOptions oldOptions = m_options;
162 m_options = options;
162 m_options = options;
163 if (options.testFlag(QChart::SeriesAnimations) != oldOptions.testFlag(QChart::SeriesAnimations)) {
163 if (options.testFlag(QChart::SeriesAnimations) != oldOptions.testFlag(QChart::SeriesAnimations)) {
164 foreach (QAbstractSeries *series, m_series)
164 foreach (QAbstractSeries *series, m_series)
165 series->d_ptr->initializeAnimations(m_options, m_animationDuration,
165 series->d_ptr->initializeAnimations(m_options, m_animationDuration,
166 m_animationCurve);
166 m_animationCurve);
167 }
167 }
168 if (options.testFlag(QChart::GridAxisAnimations) != oldOptions.testFlag(QChart::GridAxisAnimations)) {
168 if (options.testFlag(QChart::GridAxisAnimations) != oldOptions.testFlag(QChart::GridAxisAnimations)) {
169 foreach (QAbstractAxis *axis, m_axes)
169 foreach (QAbstractAxis *axis, m_axes)
170 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
170 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
171 }
171 }
172 m_layout->invalidate(); // So that existing animations don't just stop halfway
172 m_layout->invalidate(); // So that existing animations don't just stop halfway
173 }
173 }
174 }
174 }
175
175
176 void ChartPresenter::setAnimationDuration(int msecs)
176 void ChartPresenter::setAnimationDuration(int msecs)
177 {
177 {
178 if (m_animationDuration != msecs) {
178 if (m_animationDuration != msecs) {
179 m_animationDuration = msecs;
179 m_animationDuration = msecs;
180 foreach (QAbstractSeries *series, m_series)
180 foreach (QAbstractSeries *series, m_series)
181 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
181 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
182 foreach (QAbstractAxis *axis, m_axes)
182 foreach (QAbstractAxis *axis, m_axes)
183 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
183 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
184 m_layout->invalidate(); // So that existing animations don't just stop halfway
184 m_layout->invalidate(); // So that existing animations don't just stop halfway
185 }
185 }
186 }
186 }
187
187
188 void ChartPresenter::setAnimationEasingCurve(const QEasingCurve &curve)
188 void ChartPresenter::setAnimationEasingCurve(const QEasingCurve &curve)
189 {
189 {
190 if (m_animationCurve != curve) {
190 if (m_animationCurve != curve) {
191 m_animationCurve = curve;
191 m_animationCurve = curve;
192 foreach (QAbstractSeries *series, m_series)
192 foreach (QAbstractSeries *series, m_series)
193 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
193 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
194 foreach (QAbstractAxis *axis, m_axes)
194 foreach (QAbstractAxis *axis, m_axes)
195 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
195 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
196 m_layout->invalidate(); // So that existing animations don't just stop halfway
196 m_layout->invalidate(); // So that existing animations don't just stop halfway
197 }
197 }
198 }
198 }
199
199
200 void ChartPresenter::setState(State state,QPointF point)
200 void ChartPresenter::setState(State state,QPointF point)
201 {
201 {
202 m_state=state;
202 m_state=state;
203 m_statePoint=point;
203 m_statePoint=point;
204 }
204 }
205
205
206 QChart::AnimationOptions ChartPresenter::animationOptions() const
206 QChart::AnimationOptions ChartPresenter::animationOptions() const
207 {
207 {
208 return m_options;
208 return m_options;
209 }
209 }
210
210
211 void ChartPresenter::createBackgroundItem()
211 void ChartPresenter::createBackgroundItem()
212 {
212 {
213 if (!m_background) {
213 if (!m_background) {
214 m_background = new ChartBackground(rootItem());
214 m_background = new ChartBackground(rootItem());
215 m_background->setPen(Qt::NoPen); // Theme doesn't touch pen so don't use default
215 m_background->setPen(Qt::NoPen); // Theme doesn't touch pen so don't use default
216 m_background->setBrush(QChartPrivate::defaultBrush());
216 m_background->setBrush(QChartPrivate::defaultBrush());
217 m_background->setZValue(ChartPresenter::BackgroundZValue);
217 m_background->setZValue(ChartPresenter::BackgroundZValue);
218 }
218 }
219 }
219 }
220
220
221 void ChartPresenter::createPlotAreaBackgroundItem()
221 void ChartPresenter::createPlotAreaBackgroundItem()
222 {
222 {
223 if (!m_plotAreaBackground) {
223 if (!m_plotAreaBackground) {
224 if (m_chart->chartType() == QChart::ChartTypeCartesian)
224 if (m_chart->chartType() == QChart::ChartTypeCartesian)
225 m_plotAreaBackground = new QGraphicsRectItem(rootItem());
225 m_plotAreaBackground = new QGraphicsRectItem(rootItem());
226 else
226 else
227 m_plotAreaBackground = new QGraphicsEllipseItem(rootItem());
227 m_plotAreaBackground = new QGraphicsEllipseItem(rootItem());
228 // Use transparent pen instead of Qt::NoPen, as Qt::NoPen causes
228 // Use transparent pen instead of Qt::NoPen, as Qt::NoPen causes
229 // antialising artifacts with axis lines for some reason.
229 // antialising artifacts with axis lines for some reason.
230 m_plotAreaBackground->setPen(QPen(Qt::transparent));
230 m_plotAreaBackground->setPen(QPen(Qt::transparent));
231 m_plotAreaBackground->setBrush(Qt::NoBrush);
231 m_plotAreaBackground->setBrush(Qt::NoBrush);
232 m_plotAreaBackground->setZValue(ChartPresenter::PlotAreaZValue);
232 m_plotAreaBackground->setZValue(ChartPresenter::PlotAreaZValue);
233 m_plotAreaBackground->setVisible(false);
233 m_plotAreaBackground->setVisible(false);
234 }
234 }
235 }
235 }
236
236
237 void ChartPresenter::createTitleItem()
237 void ChartPresenter::createTitleItem()
238 {
238 {
239 if (!m_title) {
239 if (!m_title) {
240 m_title = new ChartTitle(rootItem());
240 m_title = new ChartTitle(rootItem());
241 m_title->setZValue(ChartPresenter::BackgroundZValue);
241 m_title->setZValue(ChartPresenter::BackgroundZValue);
242 }
242 }
243 }
243 }
244
244
245 void ChartPresenter::startAnimation(ChartAnimation *animation)
245 void ChartPresenter::startAnimation(ChartAnimation *animation)
246 {
246 {
247 animation->stop();
247 animation->stop();
248 QTimer::singleShot(0, animation, SLOT(startChartAnimation()));
248 QTimer::singleShot(0, animation, SLOT(startChartAnimation()));
249 }
249 }
250
250
251 void ChartPresenter::setBackgroundBrush(const QBrush &brush)
251 void ChartPresenter::setBackgroundBrush(const QBrush &brush)
252 {
252 {
253 createBackgroundItem();
253 createBackgroundItem();
254 m_background->setBrush(brush);
254 m_background->setBrush(brush);
255 m_layout->invalidate();
255 m_layout->invalidate();
256 }
256 }
257
257
258 QBrush ChartPresenter::backgroundBrush() const
258 QBrush ChartPresenter::backgroundBrush() const
259 {
259 {
260 if (!m_background)
260 if (!m_background)
261 return QBrush();
261 return QBrush();
262 return m_background->brush();
262 return m_background->brush();
263 }
263 }
264
264
265 void ChartPresenter::setBackgroundPen(const QPen &pen)
265 void ChartPresenter::setBackgroundPen(const QPen &pen)
266 {
266 {
267 createBackgroundItem();
267 createBackgroundItem();
268 m_background->setPen(pen);
268 m_background->setPen(pen);
269 m_layout->invalidate();
269 m_layout->invalidate();
270 }
270 }
271
271
272 QPen ChartPresenter::backgroundPen() const
272 QPen ChartPresenter::backgroundPen() const
273 {
273 {
274 if (!m_background)
274 if (!m_background)
275 return QPen();
275 return QPen();
276 return m_background->pen();
276 return m_background->pen();
277 }
277 }
278
278
279 void ChartPresenter::setBackgroundRoundness(qreal diameter)
279 void ChartPresenter::setBackgroundRoundness(qreal diameter)
280 {
280 {
281 createBackgroundItem();
281 createBackgroundItem();
282 m_background->setDiameter(diameter);
282 m_background->setDiameter(diameter);
283 m_layout->invalidate();
283 m_layout->invalidate();
284 }
284 }
285
285
286 qreal ChartPresenter::backgroundRoundness() const
286 qreal ChartPresenter::backgroundRoundness() const
287 {
287 {
288 if (!m_background)
288 if (!m_background)
289 return 0;
289 return 0;
290 return m_background->diameter();
290 return m_background->diameter();
291 }
291 }
292
292
293 void ChartPresenter::setPlotAreaBackgroundBrush(const QBrush &brush)
293 void ChartPresenter::setPlotAreaBackgroundBrush(const QBrush &brush)
294 {
294 {
295 createPlotAreaBackgroundItem();
295 createPlotAreaBackgroundItem();
296 m_plotAreaBackground->setBrush(brush);
296 m_plotAreaBackground->setBrush(brush);
297 m_layout->invalidate();
297 m_layout->invalidate();
298 }
298 }
299
299
300 QBrush ChartPresenter::plotAreaBackgroundBrush() const
300 QBrush ChartPresenter::plotAreaBackgroundBrush() const
301 {
301 {
302 if (!m_plotAreaBackground)
302 if (!m_plotAreaBackground)
303 return QBrush();
303 return QBrush();
304 return m_plotAreaBackground->brush();
304 return m_plotAreaBackground->brush();
305 }
305 }
306
306
307 void ChartPresenter::setPlotAreaBackgroundPen(const QPen &pen)
307 void ChartPresenter::setPlotAreaBackgroundPen(const QPen &pen)
308 {
308 {
309 createPlotAreaBackgroundItem();
309 createPlotAreaBackgroundItem();
310 m_plotAreaBackground->setPen(pen);
310 m_plotAreaBackground->setPen(pen);
311 m_layout->invalidate();
311 m_layout->invalidate();
312 }
312 }
313
313
314 QPen ChartPresenter::plotAreaBackgroundPen() const
314 QPen ChartPresenter::plotAreaBackgroundPen() const
315 {
315 {
316 if (!m_plotAreaBackground)
316 if (!m_plotAreaBackground)
317 return QPen();
317 return QPen();
318 return m_plotAreaBackground->pen();
318 return m_plotAreaBackground->pen();
319 }
319 }
320
320
321 void ChartPresenter::setTitle(const QString &title)
321 void ChartPresenter::setTitle(const QString &title)
322 {
322 {
323 createTitleItem();
323 createTitleItem();
324 m_title->setText(title);
324 m_title->setText(title);
325 m_layout->invalidate();
325 m_layout->invalidate();
326 }
326 }
327
327
328 QString ChartPresenter::title() const
328 QString ChartPresenter::title() const
329 {
329 {
330 if (!m_title)
330 if (!m_title)
331 return QString();
331 return QString();
332 return m_title->text();
332 return m_title->text();
333 }
333 }
334
334
335 void ChartPresenter::setTitleFont(const QFont &font)
335 void ChartPresenter::setTitleFont(const QFont &font)
336 {
336 {
337 createTitleItem();
337 createTitleItem();
338 m_title->setFont(font);
338 m_title->setFont(font);
339 m_layout->invalidate();
339 m_layout->invalidate();
340 }
340 }
341
341
342 QFont ChartPresenter::titleFont() const
342 QFont ChartPresenter::titleFont() const
343 {
343 {
344 if (!m_title)
344 if (!m_title)
345 return QFont();
345 return QFont();
346 return m_title->font();
346 return m_title->font();
347 }
347 }
348
348
349 void ChartPresenter::setTitleBrush(const QBrush &brush)
349 void ChartPresenter::setTitleBrush(const QBrush &brush)
350 {
350 {
351 createTitleItem();
351 createTitleItem();
352 m_title->setDefaultTextColor(brush.color());
352 m_title->setDefaultTextColor(brush.color());
353 m_layout->invalidate();
353 m_layout->invalidate();
354 }
354 }
355
355
356 QBrush ChartPresenter::titleBrush() const
356 QBrush ChartPresenter::titleBrush() const
357 {
357 {
358 if (!m_title)
358 if (!m_title)
359 return QBrush();
359 return QBrush();
360 return QBrush(m_title->defaultTextColor());
360 return QBrush(m_title->defaultTextColor());
361 }
361 }
362
362
363 void ChartPresenter::setBackgroundVisible(bool visible)
363 void ChartPresenter::setBackgroundVisible(bool visible)
364 {
364 {
365 createBackgroundItem();
365 createBackgroundItem();
366 m_background->setVisible(visible);
366 m_background->setVisible(visible);
367 }
367 }
368
368
369
369
370 bool ChartPresenter::isBackgroundVisible() const
370 bool ChartPresenter::isBackgroundVisible() const
371 {
371 {
372 if (!m_background)
372 if (!m_background)
373 return false;
373 return false;
374 return m_background->isVisible();
374 return m_background->isVisible();
375 }
375 }
376
376
377 void ChartPresenter::setPlotAreaBackgroundVisible(bool visible)
377 void ChartPresenter::setPlotAreaBackgroundVisible(bool visible)
378 {
378 {
379 createPlotAreaBackgroundItem();
379 createPlotAreaBackgroundItem();
380 m_plotAreaBackground->setVisible(visible);
380 m_plotAreaBackground->setVisible(visible);
381 }
381 }
382
382
383 bool ChartPresenter::isPlotAreaBackgroundVisible() const
383 bool ChartPresenter::isPlotAreaBackgroundVisible() const
384 {
384 {
385 if (!m_plotAreaBackground)
385 if (!m_plotAreaBackground)
386 return false;
386 return false;
387 return m_plotAreaBackground->isVisible();
387 return m_plotAreaBackground->isVisible();
388 }
388 }
389
389
390 void ChartPresenter::setBackgroundDropShadowEnabled(bool enabled)
390 void ChartPresenter::setBackgroundDropShadowEnabled(bool enabled)
391 {
391 {
392 createBackgroundItem();
392 createBackgroundItem();
393 m_background->setDropShadowEnabled(enabled);
393 m_background->setDropShadowEnabled(enabled);
394 }
394 }
395
395
396 bool ChartPresenter::isBackgroundDropShadowEnabled() const
396 bool ChartPresenter::isBackgroundDropShadowEnabled() const
397 {
397 {
398 if (!m_background)
398 if (!m_background)
399 return false;
399 return false;
400 return m_background->isDropShadowEnabled();
400 return m_background->isDropShadowEnabled();
401 }
401 }
402
402
403 void ChartPresenter::setLocalizeNumbers(bool localize)
403 void ChartPresenter::setLocalizeNumbers(bool localize)
404 {
404 {
405 m_localizeNumbers = localize;
405 m_localizeNumbers = localize;
406 m_layout->invalidate();
406 m_layout->invalidate();
407 }
407 }
408
408
409 void ChartPresenter::setLocale(const QLocale &locale)
409 void ChartPresenter::setLocale(const QLocale &locale)
410 {
410 {
411 m_locale = locale;
411 m_locale = locale;
412 m_layout->invalidate();
412 m_layout->invalidate();
413 }
413 }
414
414
415 AbstractChartLayout *ChartPresenter::layout()
415 AbstractChartLayout *ChartPresenter::layout()
416 {
416 {
417 return m_layout;
417 return m_layout;
418 }
418 }
419
419
420 QLegend *ChartPresenter::legend()
420 QLegend *ChartPresenter::legend()
421 {
421 {
422 return m_chart->legend();
422 return m_chart->legend();
423 }
423 }
424
424
425 void ChartPresenter::setVisible(bool visible)
425 void ChartPresenter::setVisible(bool visible)
426 {
426 {
427 m_chart->setVisible(visible);
427 m_chart->setVisible(visible);
428 }
428 }
429
429
430 ChartBackground *ChartPresenter::backgroundElement()
430 ChartBackground *ChartPresenter::backgroundElement()
431 {
431 {
432 return m_background;
432 return m_background;
433 }
433 }
434
434
435 QAbstractGraphicsShapeItem *ChartPresenter::plotAreaElement()
435 QAbstractGraphicsShapeItem *ChartPresenter::plotAreaElement()
436 {
436 {
437 return m_plotAreaBackground;
437 return m_plotAreaBackground;
438 }
438 }
439
439
440 QList<ChartAxisElement *> ChartPresenter::axisItems() const
440 QList<ChartAxisElement *> ChartPresenter::axisItems() const
441 {
441 {
442 return m_axisItems;
442 return m_axisItems;
443 }
443 }
444
444
445 QList<ChartItem *> ChartPresenter::chartItems() const
445 QList<ChartItem *> ChartPresenter::chartItems() const
446 {
446 {
447 return m_chartItems;
447 return m_chartItems;
448 }
448 }
449
449
450 ChartTitle *ChartPresenter::titleElement()
450 ChartTitle *ChartPresenter::titleElement()
451 {
451 {
452 return m_title;
452 return m_title;
453 }
453 }
454
454
455 QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, qreal angle)
455 QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, qreal angle)
456 {
456 {
457 static QGraphicsTextItem dummyTextItem;
457 static QGraphicsTextItem dummyTextItem;
458 static bool initMargin = true;
458 static bool initMargin = true;
459 if (initMargin) {
459 if (initMargin) {
460 dummyTextItem.document()->setDocumentMargin(textMargin());
460 dummyTextItem.document()->setDocumentMargin(textMargin());
461 initMargin = false;
461 initMargin = false;
462 }
462 }
463
463
464 dummyTextItem.setFont(font);
464 dummyTextItem.setFont(font);
465 dummyTextItem.setHtml(text);
465 dummyTextItem.setHtml(text);
466 QRectF boundingRect = dummyTextItem.boundingRect();
466 QRectF boundingRect = dummyTextItem.boundingRect();
467
467
468 // Take rotation into account
468 // Take rotation into account
469 if (angle) {
469 if (angle) {
470 QTransform transform;
470 QTransform transform;
471 transform.rotate(angle);
471 transform.rotate(angle);
472 boundingRect = transform.mapRect(boundingRect);
472 boundingRect = transform.mapRect(boundingRect);
473 }
473 }
474
474
475 return boundingRect;
475 return boundingRect;
476 }
476 }
477
477
478 // boundingRect parameter returns the rotated bounding rect of the text
478 // boundingRect parameter returns the rotated bounding rect of the text
479 QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle,
479 QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle,
480 qreal maxWidth, qreal maxHeight, QRectF &boundingRect)
480 qreal maxWidth, qreal maxHeight, QRectF &boundingRect)
481 {
481 {
482 QString truncatedString(text);
482 QString truncatedString(text);
483 boundingRect = textBoundingRect(font, truncatedString, angle);
483 boundingRect = textBoundingRect(font, truncatedString, angle);
484 if (boundingRect.width() > maxWidth || boundingRect.height() > maxHeight) {
484 if (boundingRect.width() > maxWidth || boundingRect.height() > maxHeight) {
485 // It can be assumed that almost any amount of string manipulation is faster
485 // It can be assumed that almost any amount of string manipulation is faster
486 // than calculating one bounding rectangle, so first prepare a list of truncated strings
486 // than calculating one bounding rectangle, so first prepare a list of truncated strings
487 // to try.
487 // to try.
488 static QRegExp truncateMatcher(QStringLiteral("&#?[0-9a-zA-Z]*;$"));
488 static QRegExp truncateMatcher(QStringLiteral("&#?[0-9a-zA-Z]*;$"));
489
489
490 QVector<QString> testStrings(text.length());
490 QVector<QString> testStrings(text.length());
491 int count(0);
491 int count(0);
492 static QLatin1Char closeTag('>');
492 static QLatin1Char closeTag('>');
493 static QLatin1Char openTag('<');
493 static QLatin1Char openTag('<');
494 static QLatin1Char semiColon(';');
494 static QLatin1Char semiColon(';');
495 static QLatin1String ellipsis("...");
495 static QLatin1String ellipsis("...");
496 while (truncatedString.length() > 1) {
496 while (truncatedString.length() > 1) {
497 int chopIndex(-1);
497 int chopIndex(-1);
498 int chopCount(1);
498 int chopCount(1);
499 QChar lastChar(truncatedString.at(truncatedString.length() - 1));
499 QChar lastChar(truncatedString.at(truncatedString.length() - 1));
500
500
501 if (lastChar == closeTag)
501 if (lastChar == closeTag)
502 chopIndex = truncatedString.lastIndexOf(openTag);
502 chopIndex = truncatedString.lastIndexOf(openTag);
503 else if (lastChar == semiColon)
503 else if (lastChar == semiColon)
504 chopIndex = truncateMatcher.indexIn(truncatedString, 0);
504 chopIndex = truncateMatcher.indexIn(truncatedString, 0);
505
505
506 if (chopIndex != -1)
506 if (chopIndex != -1)
507 chopCount = truncatedString.length() - chopIndex;
507 chopCount = truncatedString.length() - chopIndex;
508 truncatedString.chop(chopCount);
508 truncatedString.chop(chopCount);
509 testStrings[count] = truncatedString + ellipsis;
509 testStrings[count] = truncatedString + ellipsis;
510 count++;
510 count++;
511 }
511 }
512
512
513 // Binary search for best fit
513 // Binary search for best fit
514 int minIndex(0);
514 int minIndex(0);
515 int maxIndex(count - 1);
515 int maxIndex(count - 1);
516 int bestIndex(count);
516 int bestIndex(count);
517 QRectF checkRect;
517 QRectF checkRect;
518
518
519 while (maxIndex >= minIndex) {
519 while (maxIndex >= minIndex) {
520 int mid = (maxIndex + minIndex) / 2;
520 int mid = (maxIndex + minIndex) / 2;
521 checkRect = textBoundingRect(font, testStrings.at(mid), angle);
521 checkRect = textBoundingRect(font, testStrings.at(mid), angle);
522 if (checkRect.width() > maxWidth || checkRect.height() > maxHeight) {
522 if (checkRect.width() > maxWidth || checkRect.height() > maxHeight) {
523 // Checked index too large, all under this are also too large
523 // Checked index too large, all under this are also too large
524 minIndex = mid + 1;
524 minIndex = mid + 1;
525 } else {
525 } else {
526 // Checked index fits, all over this also fit
526 // Checked index fits, all over this also fit
527 maxIndex = mid - 1;
527 maxIndex = mid - 1;
528 bestIndex = mid;
528 bestIndex = mid;
529 boundingRect = checkRect;
529 boundingRect = checkRect;
530 }
530 }
531 }
531 }
532 // Default to "..." if nothing fits
532 // Default to "..." if nothing fits
533 if (bestIndex == count) {
533 if (bestIndex == count) {
534 boundingRect = textBoundingRect(font, ellipsis, angle);
534 boundingRect = textBoundingRect(font, ellipsis, angle);
535 truncatedString = ellipsis;
535 truncatedString = ellipsis;
536 } else {
536 } else {
537 truncatedString = testStrings.at(bestIndex);
537 truncatedString = testStrings.at(bestIndex);
538 }
538 }
539 }
539 }
540
540
541 return truncatedString;
541 return truncatedString;
542 }
542 }
543
543
544 QString ChartPresenter::numberToString(double value, char f, int prec)
544 QString ChartPresenter::numberToString(double value, char f, int prec)
545 {
545 {
546 if (m_localizeNumbers)
546 if (m_localizeNumbers)
547 return m_locale.toString(value, f, prec);
547 return m_locale.toString(value, f, prec);
548 else
548 else
549 return QString::number(value, f, prec);
549 return QString::number(value, f, prec);
550 }
550 }
551
551
552 QString ChartPresenter::numberToString(int value)
552 QString ChartPresenter::numberToString(int value)
553 {
553 {
554 if (m_localizeNumbers)
554 if (m_localizeNumbers)
555 return m_locale.toString(value);
555 return m_locale.toString(value);
556 else
556 else
557 return QString::number(value);
557 return QString::number(value);
558 }
558 }
559
559
560 void ChartPresenter::ensureGLWidget()
560 void ChartPresenter::updateGLWidget()
561 {
561 {
562 #ifndef QT_NO_OPENGL
562 #ifndef QT_NO_OPENGL
563 // GLWidget pointer is wrapped in QPointer as its parent is not in our control, and therefore
563 // GLWidget pointer is wrapped in QPointer as its parent is not in our control, and therefore
564 // can potentially get deleted unexpectedly.
564 // can potentially get deleted unexpectedly.
565 if (m_glWidget.isNull() && m_glUseWidget && m_chart->scene()) {
565 if (m_glWidget.isNull() && m_glUseWidget && m_chart->scene()) {
566 // Find the view of the scene. If the scene has multiple views, only the first view is
566 // Find the view of the scene. If the scene has multiple views, only the first view is
567 // chosen.
567 // chosen.
568 QList<QGraphicsView *> views = m_chart->scene()->views();
568 QList<QGraphicsView *> views = m_chart->scene()->views();
569 if (views.size()) {
569 if (views.size()) {
570 QGraphicsView *firstView = views.at(0);
570 QGraphicsView *firstView = views.at(0);
571 m_glWidget = new GLWidget(m_chart->d_ptr->m_dataset->glXYSeriesDataManager(),
571 m_glWidget = new GLWidget(m_chart->d_ptr->m_dataset->glXYSeriesDataManager(),
572 firstView);
572 firstView);
573 m_glWidget->setGeometry(m_rect.toRect());
573 m_glWidget->setGeometry(m_rect.toRect());
574 m_glWidget->show();
574 m_glWidget->show();
575 }
575 }
576 }
576 }
577 // Make sure we update the widget in a timely manner
578 if (!m_glWidget.isNull())
579 m_glWidget->update();
577 #endif
580 #endif
578 }
581 }
579
582
580 #include "moc_chartpresenter_p.cpp"
583 #include "moc_chartpresenter_p.cpp"
581
584
582 QT_CHARTS_END_NAMESPACE
585 QT_CHARTS_END_NAMESPACE
@@ -1,220 +1,220
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
4 ** Contact: https://www.qt.io/licensing/
5 **
5 **
6 ** This file is part of the Qt Charts module of the Qt Toolkit.
6 ** This file is part of the Qt Charts module of the Qt Toolkit.
7 **
7 **
8 ** $QT_BEGIN_LICENSE:GPL$
8 ** $QT_BEGIN_LICENSE:GPL$
9 ** Commercial License Usage
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
16 **
17 ** GNU General Public License Usage
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 or (at your option) any later version
19 ** General Public License version 3 or (at your option) any later version
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
22 ** included in the packaging of this file. Please review the following
22 ** included in the packaging of this file. Please review the following
23 ** information to ensure the GNU General Public License requirements will
23 ** information to ensure the GNU General Public License requirements will
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25 **
25 **
26 ** $QT_END_LICENSE$
26 ** $QT_END_LICENSE$
27 **
27 **
28 ****************************************************************************/
28 ****************************************************************************/
29
29
30 // W A R N I N G
30 // W A R N I N G
31 // -------------
31 // -------------
32 //
32 //
33 // This file is not part of the Qt Chart API. It exists purely as an
33 // This file is not part of the Qt Chart API. It exists purely as an
34 // implementation detail. This header file may change from version to
34 // implementation detail. This header file may change from version to
35 // version without notice, or even be removed.
35 // version without notice, or even be removed.
36 //
36 //
37 // We mean it.
37 // We mean it.
38
38
39 #ifndef CHARTPRESENTER_H
39 #ifndef CHARTPRESENTER_H
40 #define CHARTPRESENTER_H
40 #define CHARTPRESENTER_H
41
41
42 #include <QtCharts/QChartGlobal>
42 #include <QtCharts/QChartGlobal>
43 #include <QtCharts/QChart> //because of QChart::ChartThemeId
43 #include <QtCharts/QChart> //because of QChart::ChartThemeId
44 #include <private/glwidget_p.h>
44 #include <private/glwidget_p.h>
45 #include <QtCore/QRectF>
45 #include <QtCore/QRectF>
46 #include <QtCore/QMargins>
46 #include <QtCore/QMargins>
47 #include <QtCore/QLocale>
47 #include <QtCore/QLocale>
48 #include <QtCore/QPointer>
48 #include <QtCore/QPointer>
49 #include <QtCore/QEasingCurve>
49 #include <QtCore/QEasingCurve>
50
50
51 QT_CHARTS_BEGIN_NAMESPACE
51 QT_CHARTS_BEGIN_NAMESPACE
52
52
53 class ChartItem;
53 class ChartItem;
54 class AxisItem;
54 class AxisItem;
55 class QAbstractSeries;
55 class QAbstractSeries;
56 class ChartDataSet;
56 class ChartDataSet;
57 class AbstractDomain;
57 class AbstractDomain;
58 class ChartAxisElement;
58 class ChartAxisElement;
59 class ChartAnimator;
59 class ChartAnimator;
60 class ChartBackground;
60 class ChartBackground;
61 class ChartTitle;
61 class ChartTitle;
62 class ChartAnimation;
62 class ChartAnimation;
63 class AbstractChartLayout;
63 class AbstractChartLayout;
64
64
65 class ChartPresenter: public QObject
65 class ChartPresenter: public QObject
66 {
66 {
67 Q_OBJECT
67 Q_OBJECT
68 public:
68 public:
69 enum ZValues {
69 enum ZValues {
70 BackgroundZValue = -1,
70 BackgroundZValue = -1,
71 PlotAreaZValue,
71 PlotAreaZValue,
72 ShadesZValue,
72 ShadesZValue,
73 GridZValue,
73 GridZValue,
74 AxisZValue,
74 AxisZValue,
75 SeriesZValue,
75 SeriesZValue,
76 LineChartZValue = SeriesZValue,
76 LineChartZValue = SeriesZValue,
77 SplineChartZValue = SeriesZValue,
77 SplineChartZValue = SeriesZValue,
78 BarSeriesZValue = SeriesZValue,
78 BarSeriesZValue = SeriesZValue,
79 ScatterSeriesZValue = SeriesZValue,
79 ScatterSeriesZValue = SeriesZValue,
80 PieSeriesZValue = SeriesZValue,
80 PieSeriesZValue = SeriesZValue,
81 BoxPlotSeriesZValue = SeriesZValue,
81 BoxPlotSeriesZValue = SeriesZValue,
82 LegendZValue,
82 LegendZValue,
83 TopMostZValue
83 TopMostZValue
84 };
84 };
85
85
86 enum State {
86 enum State {
87 ShowState,
87 ShowState,
88 ScrollUpState,
88 ScrollUpState,
89 ScrollDownState,
89 ScrollDownState,
90 ScrollLeftState,
90 ScrollLeftState,
91 ScrollRightState,
91 ScrollRightState,
92 ZoomInState,
92 ZoomInState,
93 ZoomOutState
93 ZoomOutState
94 };
94 };
95
95
96 ChartPresenter(QChart *chart, QChart::ChartType type);
96 ChartPresenter(QChart *chart, QChart::ChartType type);
97 virtual ~ChartPresenter();
97 virtual ~ChartPresenter();
98
98
99
99
100 void setGeometry(QRectF rect);
100 void setGeometry(QRectF rect);
101 QRectF geometry() const;
101 QRectF geometry() const;
102
102
103 QGraphicsItem *rootItem(){ return m_chart; }
103 QGraphicsItem *rootItem(){ return m_chart; }
104 ChartBackground *backgroundElement();
104 ChartBackground *backgroundElement();
105 QAbstractGraphicsShapeItem *plotAreaElement();
105 QAbstractGraphicsShapeItem *plotAreaElement();
106 ChartTitle *titleElement();
106 ChartTitle *titleElement();
107 QList<ChartAxisElement *> axisItems() const;
107 QList<ChartAxisElement *> axisItems() const;
108 QList<ChartItem *> chartItems() const;
108 QList<ChartItem *> chartItems() const;
109
109
110 QLegend *legend();
110 QLegend *legend();
111
111
112 void setBackgroundBrush(const QBrush &brush);
112 void setBackgroundBrush(const QBrush &brush);
113 QBrush backgroundBrush() const;
113 QBrush backgroundBrush() const;
114
114
115 void setBackgroundPen(const QPen &pen);
115 void setBackgroundPen(const QPen &pen);
116 QPen backgroundPen() const;
116 QPen backgroundPen() const;
117
117
118 void setBackgroundRoundness(qreal diameter);
118 void setBackgroundRoundness(qreal diameter);
119 qreal backgroundRoundness() const;
119 qreal backgroundRoundness() const;
120
120
121 void setPlotAreaBackgroundBrush(const QBrush &brush);
121 void setPlotAreaBackgroundBrush(const QBrush &brush);
122 QBrush plotAreaBackgroundBrush() const;
122 QBrush plotAreaBackgroundBrush() const;
123
123
124 void setPlotAreaBackgroundPen(const QPen &pen);
124 void setPlotAreaBackgroundPen(const QPen &pen);
125 QPen plotAreaBackgroundPen() const;
125 QPen plotAreaBackgroundPen() const;
126
126
127 void setTitle(const QString &title);
127 void setTitle(const QString &title);
128 QString title() const;
128 QString title() const;
129
129
130 void setTitleFont(const QFont &font);
130 void setTitleFont(const QFont &font);
131 QFont titleFont() const;
131 QFont titleFont() const;
132
132
133 void setTitleBrush(const QBrush &brush);
133 void setTitleBrush(const QBrush &brush);
134 QBrush titleBrush() const;
134 QBrush titleBrush() const;
135
135
136 void setBackgroundVisible(bool visible);
136 void setBackgroundVisible(bool visible);
137 bool isBackgroundVisible() const;
137 bool isBackgroundVisible() const;
138
138
139 void setPlotAreaBackgroundVisible(bool visible);
139 void setPlotAreaBackgroundVisible(bool visible);
140 bool isPlotAreaBackgroundVisible() const;
140 bool isPlotAreaBackgroundVisible() const;
141
141
142 void setBackgroundDropShadowEnabled(bool enabled);
142 void setBackgroundDropShadowEnabled(bool enabled);
143 bool isBackgroundDropShadowEnabled() const;
143 bool isBackgroundDropShadowEnabled() const;
144
144
145 void setLocalizeNumbers(bool localize);
145 void setLocalizeNumbers(bool localize);
146 inline bool localizeNumbers() const { return m_localizeNumbers; }
146 inline bool localizeNumbers() const { return m_localizeNumbers; }
147 void setLocale(const QLocale &locale);
147 void setLocale(const QLocale &locale);
148 inline const QLocale &locale() const { return m_locale; }
148 inline const QLocale &locale() const { return m_locale; }
149
149
150 void setVisible(bool visible);
150 void setVisible(bool visible);
151
151
152 void setAnimationOptions(QChart::AnimationOptions options);
152 void setAnimationOptions(QChart::AnimationOptions options);
153 QChart::AnimationOptions animationOptions() const;
153 QChart::AnimationOptions animationOptions() const;
154 void setAnimationDuration(int msecs);
154 void setAnimationDuration(int msecs);
155 int animationDuration() const { return m_animationDuration; }
155 int animationDuration() const { return m_animationDuration; }
156 void setAnimationEasingCurve(const QEasingCurve &curve);
156 void setAnimationEasingCurve(const QEasingCurve &curve);
157 QEasingCurve animationEasingCurve() const { return m_animationCurve; }
157 QEasingCurve animationEasingCurve() const { return m_animationCurve; }
158
158
159 void startAnimation(ChartAnimation *animation);
159 void startAnimation(ChartAnimation *animation);
160
160
161 void setState(State state,QPointF point);
161 void setState(State state,QPointF point);
162 State state() const { return m_state; }
162 State state() const { return m_state; }
163 QPointF statePoint() const { return m_statePoint; }
163 QPointF statePoint() const { return m_statePoint; }
164 AbstractChartLayout *layout();
164 AbstractChartLayout *layout();
165
165
166 QChart::ChartType chartType() const { return m_chart->chartType(); }
166 QChart::ChartType chartType() const { return m_chart->chartType(); }
167 QChart *chart() { return m_chart; }
167 QChart *chart() { return m_chart; }
168
168
169 static QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0);
169 static QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0);
170 static QString truncatedText(const QFont &font, const QString &text, qreal angle,
170 static QString truncatedText(const QFont &font, const QString &text, qreal angle,
171 qreal maxWidth, qreal maxHeight, QRectF &boundingRect);
171 qreal maxWidth, qreal maxHeight, QRectF &boundingRect);
172 inline static qreal textMargin() { return qreal(0.5); }
172 inline static qreal textMargin() { return qreal(0.5); }
173
173
174 QString numberToString(double value, char f = 'g', int prec = 6);
174 QString numberToString(double value, char f = 'g', int prec = 6);
175 QString numberToString(int value);
175 QString numberToString(int value);
176
176
177 void ensureGLWidget();
177 void updateGLWidget();
178 void glSetUseWidget(bool enable) { m_glUseWidget = enable; }
178 void glSetUseWidget(bool enable) { m_glUseWidget = enable; }
179
179
180 private:
180 private:
181 void createBackgroundItem();
181 void createBackgroundItem();
182 void createPlotAreaBackgroundItem();
182 void createPlotAreaBackgroundItem();
183 void createTitleItem();
183 void createTitleItem();
184
184
185 public Q_SLOTS:
185 public Q_SLOTS:
186 void handleSeriesAdded(QAbstractSeries *series);
186 void handleSeriesAdded(QAbstractSeries *series);
187 void handleSeriesRemoved(QAbstractSeries *series);
187 void handleSeriesRemoved(QAbstractSeries *series);
188 void handleAxisAdded(QAbstractAxis *axis);
188 void handleAxisAdded(QAbstractAxis *axis);
189 void handleAxisRemoved(QAbstractAxis *axis);
189 void handleAxisRemoved(QAbstractAxis *axis);
190
190
191 Q_SIGNALS:
191 Q_SIGNALS:
192 void plotAreaChanged(const QRectF &plotArea);
192 void plotAreaChanged(const QRectF &plotArea);
193
193
194 private:
194 private:
195 QChart *m_chart;
195 QChart *m_chart;
196 QList<ChartItem *> m_chartItems;
196 QList<ChartItem *> m_chartItems;
197 QList<ChartAxisElement *> m_axisItems;
197 QList<ChartAxisElement *> m_axisItems;
198 QList<QAbstractSeries *> m_series;
198 QList<QAbstractSeries *> m_series;
199 QList<QAbstractAxis *> m_axes;
199 QList<QAbstractAxis *> m_axes;
200 QChart::AnimationOptions m_options;
200 QChart::AnimationOptions m_options;
201 int m_animationDuration;
201 int m_animationDuration;
202 QEasingCurve m_animationCurve;
202 QEasingCurve m_animationCurve;
203 State m_state;
203 State m_state;
204 QPointF m_statePoint;
204 QPointF m_statePoint;
205 AbstractChartLayout *m_layout;
205 AbstractChartLayout *m_layout;
206 ChartBackground *m_background;
206 ChartBackground *m_background;
207 QAbstractGraphicsShapeItem *m_plotAreaBackground;
207 QAbstractGraphicsShapeItem *m_plotAreaBackground;
208 ChartTitle *m_title;
208 ChartTitle *m_title;
209 QRectF m_rect;
209 QRectF m_rect;
210 bool m_localizeNumbers;
210 bool m_localizeNumbers;
211 QLocale m_locale;
211 QLocale m_locale;
212 #ifndef QT_NO_OPENGL
212 #ifndef QT_NO_OPENGL
213 QPointer<GLWidget> m_glWidget;
213 QPointer<GLWidget> m_glWidget;
214 #endif
214 #endif
215 bool m_glUseWidget;
215 bool m_glUseWidget;
216 };
216 };
217
217
218 QT_CHARTS_END_NAMESPACE
218 QT_CHARTS_END_NAMESPACE
219
219
220 #endif /* CHARTPRESENTER_H */
220 #endif /* CHARTPRESENTER_H */
@@ -1,246 +1,246
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
4 ** Contact: https://www.qt.io/licensing/
5 **
5 **
6 ** This file is part of the Qt Charts module of the Qt Toolkit.
6 ** This file is part of the Qt Charts module of the Qt Toolkit.
7 **
7 **
8 ** $QT_BEGIN_LICENSE:GPL$
8 ** $QT_BEGIN_LICENSE:GPL$
9 ** Commercial License Usage
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
16 **
17 ** GNU General Public License Usage
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 or (at your option) any later version
19 ** General Public License version 3 or (at your option) any later version
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
22 ** included in the packaging of this file. Please review the following
22 ** included in the packaging of this file. Please review the following
23 ** information to ensure the GNU General Public License requirements will
23 ** information to ensure the GNU General Public License requirements will
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25 **
25 **
26 ** $QT_END_LICENSE$
26 ** $QT_END_LICENSE$
27 **
27 **
28 ****************************************************************************/
28 ****************************************************************************/
29
29
30 #include <private/xychart_p.h>
30 #include <private/xychart_p.h>
31 #include <QtCharts/QXYSeries>
31 #include <QtCharts/QXYSeries>
32 #include <private/qxyseries_p.h>
32 #include <private/qxyseries_p.h>
33 #include <private/chartpresenter_p.h>
33 #include <private/chartpresenter_p.h>
34 #include <private/abstractdomain_p.h>
34 #include <private/abstractdomain_p.h>
35 #include <private/chartdataset_p.h>
35 #include <private/chartdataset_p.h>
36 #include <private/glxyseriesdata_p.h>
36 #include <private/glxyseriesdata_p.h>
37 #include <QtCharts/QXYModelMapper>
37 #include <QtCharts/QXYModelMapper>
38 #include <private/qabstractaxis_p.h>
38 #include <private/qabstractaxis_p.h>
39 #include <QtGui/QPainter>
39 #include <QtGui/QPainter>
40 #include <QtCore/QAbstractItemModel>
40 #include <QtCore/QAbstractItemModel>
41
41
42
42
43 QT_CHARTS_BEGIN_NAMESPACE
43 QT_CHARTS_BEGIN_NAMESPACE
44
44
45 XYChart::XYChart(QXYSeries *series, QGraphicsItem *item):
45 XYChart::XYChart(QXYSeries *series, QGraphicsItem *item):
46 ChartItem(series->d_func(),item),
46 ChartItem(series->d_func(),item),
47 m_series(series),
47 m_series(series),
48 m_animation(0),
48 m_animation(0),
49 m_dirty(true)
49 m_dirty(true)
50 {
50 {
51 QObject::connect(series, SIGNAL(pointReplaced(int)), this, SLOT(handlePointReplaced(int)));
51 QObject::connect(series, SIGNAL(pointReplaced(int)), this, SLOT(handlePointReplaced(int)));
52 QObject::connect(series, SIGNAL(pointsReplaced()), this, SLOT(handlePointsReplaced()));
52 QObject::connect(series, SIGNAL(pointsReplaced()), this, SLOT(handlePointsReplaced()));
53 QObject::connect(series, SIGNAL(pointAdded(int)), this, SLOT(handlePointAdded(int)));
53 QObject::connect(series, SIGNAL(pointAdded(int)), this, SLOT(handlePointAdded(int)));
54 QObject::connect(series, SIGNAL(pointRemoved(int)), this, SLOT(handlePointRemoved(int)));
54 QObject::connect(series, SIGNAL(pointRemoved(int)), this, SLOT(handlePointRemoved(int)));
55 QObject::connect(series, SIGNAL(pointsRemoved(int, int)), this, SLOT(handlePointsRemoved(int, int)));
55 QObject::connect(series, SIGNAL(pointsRemoved(int, int)), this, SLOT(handlePointsRemoved(int, int)));
56 QObject::connect(this, SIGNAL(clicked(QPointF)), series, SIGNAL(clicked(QPointF)));
56 QObject::connect(this, SIGNAL(clicked(QPointF)), series, SIGNAL(clicked(QPointF)));
57 QObject::connect(this, SIGNAL(hovered(QPointF,bool)), series, SIGNAL(hovered(QPointF,bool)));
57 QObject::connect(this, SIGNAL(hovered(QPointF,bool)), series, SIGNAL(hovered(QPointF,bool)));
58 QObject::connect(this, SIGNAL(pressed(QPointF)), series, SIGNAL(pressed(QPointF)));
58 QObject::connect(this, SIGNAL(pressed(QPointF)), series, SIGNAL(pressed(QPointF)));
59 QObject::connect(this, SIGNAL(released(QPointF)), series, SIGNAL(released(QPointF)));
59 QObject::connect(this, SIGNAL(released(QPointF)), series, SIGNAL(released(QPointF)));
60 QObject::connect(this, SIGNAL(doubleClicked(QPointF)), series, SIGNAL(doubleClicked(QPointF)));
60 QObject::connect(this, SIGNAL(doubleClicked(QPointF)), series, SIGNAL(doubleClicked(QPointF)));
61 }
61 }
62
62
63 void XYChart::setGeometryPoints(const QVector<QPointF> &points)
63 void XYChart::setGeometryPoints(const QVector<QPointF> &points)
64 {
64 {
65 m_points = points;
65 m_points = points;
66 }
66 }
67
67
68 void XYChart::setAnimation(XYAnimation *animation)
68 void XYChart::setAnimation(XYAnimation *animation)
69 {
69 {
70 m_animation = animation;
70 m_animation = animation;
71 }
71 }
72
72
73 void XYChart::setDirty(bool dirty)
73 void XYChart::setDirty(bool dirty)
74 {
74 {
75 m_dirty = dirty;
75 m_dirty = dirty;
76 }
76 }
77
77
78 // Returns a vector with same size as geometryPoints vector, indicating
78 // Returns a vector with same size as geometryPoints vector, indicating
79 // the off grid status of points.
79 // the off grid status of points.
80 QVector<bool> XYChart::offGridStatusVector()
80 QVector<bool> XYChart::offGridStatusVector()
81 {
81 {
82 qreal minX = domain()->minX();
82 qreal minX = domain()->minX();
83 qreal maxX = domain()->maxX();
83 qreal maxX = domain()->maxX();
84 qreal minY = domain()->minY();
84 qreal minY = domain()->minY();
85 qreal maxY = domain()->maxY();
85 qreal maxY = domain()->maxY();
86
86
87 QVector<bool> returnVector;
87 QVector<bool> returnVector;
88 returnVector.resize(m_points.size());
88 returnVector.resize(m_points.size());
89 // During remove animation series may have different number of points,
89 // During remove animation series may have different number of points,
90 // so ensure we don't go over the index. No need to check for zero points, this
90 // so ensure we don't go over the index. No need to check for zero points, this
91 // will not be called in such a situation.
91 // will not be called in such a situation.
92 const int seriesLastIndex = m_series->count() - 1;
92 const int seriesLastIndex = m_series->count() - 1;
93
93
94 for (int i = 0; i < m_points.size(); i++) {
94 for (int i = 0; i < m_points.size(); i++) {
95 const QPointF &seriesPoint = m_series->at(qMin(seriesLastIndex, i));
95 const QPointF &seriesPoint = m_series->at(qMin(seriesLastIndex, i));
96 if (seriesPoint.x() < minX
96 if (seriesPoint.x() < minX
97 || seriesPoint.x() > maxX
97 || seriesPoint.x() > maxX
98 || seriesPoint.y() < minY
98 || seriesPoint.y() < minY
99 || seriesPoint.y() > maxY) {
99 || seriesPoint.y() > maxY) {
100 returnVector[i] = true;
100 returnVector[i] = true;
101 } else {
101 } else {
102 returnVector[i] = false;
102 returnVector[i] = false;
103 }
103 }
104 }
104 }
105 return returnVector;
105 return returnVector;
106 }
106 }
107
107
108 void XYChart::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
108 void XYChart::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
109 {
109 {
110
110
111 if (m_animation) {
111 if (m_animation) {
112 m_animation->setup(oldPoints, newPoints, index);
112 m_animation->setup(oldPoints, newPoints, index);
113 m_points = newPoints;
113 m_points = newPoints;
114 setDirty(false);
114 setDirty(false);
115 presenter()->startAnimation(m_animation);
115 presenter()->startAnimation(m_animation);
116 } else {
116 } else {
117 m_points = newPoints;
117 m_points = newPoints;
118 updateGeometry();
118 updateGeometry();
119 }
119 }
120 }
120 }
121
121
122 void XYChart::updateGlChart()
122 void XYChart::updateGlChart()
123 {
123 {
124 presenter()->ensureGLWidget();
125 dataSet()->glXYSeriesDataManager()->setPoints(m_series, domain());
124 dataSet()->glXYSeriesDataManager()->setPoints(m_series, domain());
125 presenter()->updateGLWidget();
126 updateGeometry();
126 updateGeometry();
127 }
127 }
128
128
129 //handlers
129 //handlers
130
130
131 void XYChart::handlePointAdded(int index)
131 void XYChart::handlePointAdded(int index)
132 {
132 {
133 Q_ASSERT(index < m_series->count());
133 Q_ASSERT(index < m_series->count());
134 Q_ASSERT(index >= 0);
134 Q_ASSERT(index >= 0);
135
135
136 if (m_series->useOpenGL()) {
136 if (m_series->useOpenGL()) {
137 updateGlChart();
137 updateGlChart();
138 } else {
138 } else {
139 QVector<QPointF> points;
139 QVector<QPointF> points;
140 if (m_dirty || m_points.isEmpty()) {
140 if (m_dirty || m_points.isEmpty()) {
141 points = domain()->calculateGeometryPoints(m_series->pointsVector());
141 points = domain()->calculateGeometryPoints(m_series->pointsVector());
142 } else {
142 } else {
143 points = m_points;
143 points = m_points;
144 QPointF point = domain()->calculateGeometryPoint(m_series->pointsVector().at(index),
144 QPointF point = domain()->calculateGeometryPoint(m_series->pointsVector().at(index),
145 m_validData);
145 m_validData);
146 if (!m_validData)
146 if (!m_validData)
147 m_points.clear();
147 m_points.clear();
148 else
148 else
149 points.insert(index, point);
149 points.insert(index, point);
150 }
150 }
151 updateChart(m_points, points, index);
151 updateChart(m_points, points, index);
152 }
152 }
153 }
153 }
154
154
155 void XYChart::handlePointRemoved(int index)
155 void XYChart::handlePointRemoved(int index)
156 {
156 {
157 Q_ASSERT(index <= m_series->count());
157 Q_ASSERT(index <= m_series->count());
158 Q_ASSERT(index >= 0);
158 Q_ASSERT(index >= 0);
159
159
160 if (m_series->useOpenGL()) {
160 if (m_series->useOpenGL()) {
161 updateGlChart();
161 updateGlChart();
162 } else {
162 } else {
163 QVector<QPointF> points;
163 QVector<QPointF> points;
164 if (m_dirty || m_points.isEmpty()) {
164 if (m_dirty || m_points.isEmpty()) {
165 points = domain()->calculateGeometryPoints(m_series->pointsVector());
165 points = domain()->calculateGeometryPoints(m_series->pointsVector());
166 } else {
166 } else {
167 points = m_points;
167 points = m_points;
168 points.remove(index);
168 points.remove(index);
169 }
169 }
170 updateChart(m_points, points, index);
170 updateChart(m_points, points, index);
171 }
171 }
172 }
172 }
173
173
174 void XYChart::handlePointsRemoved(int index, int count)
174 void XYChart::handlePointsRemoved(int index, int count)
175 {
175 {
176 Q_ASSERT(index <= m_series->count());
176 Q_ASSERT(index <= m_series->count());
177 Q_ASSERT(index >= 0);
177 Q_ASSERT(index >= 0);
178
178
179 if (m_series->useOpenGL()) {
179 if (m_series->useOpenGL()) {
180 updateGlChart();
180 updateGlChart();
181 } else {
181 } else {
182 QVector<QPointF> points;
182 QVector<QPointF> points;
183 if (m_dirty || m_points.isEmpty()) {
183 if (m_dirty || m_points.isEmpty()) {
184 points = domain()->calculateGeometryPoints(m_series->pointsVector());
184 points = domain()->calculateGeometryPoints(m_series->pointsVector());
185 } else {
185 } else {
186 points = m_points;
186 points = m_points;
187 points.remove(index, count);
187 points.remove(index, count);
188 }
188 }
189 updateChart(m_points, points, index);
189 updateChart(m_points, points, index);
190 }
190 }
191 }
191 }
192
192
193 void XYChart::handlePointReplaced(int index)
193 void XYChart::handlePointReplaced(int index)
194 {
194 {
195 Q_ASSERT(index < m_series->count());
195 Q_ASSERT(index < m_series->count());
196 Q_ASSERT(index >= 0);
196 Q_ASSERT(index >= 0);
197
197
198 if (m_series->useOpenGL()) {
198 if (m_series->useOpenGL()) {
199 updateGlChart();
199 updateGlChart();
200 } else {
200 } else {
201 QVector<QPointF> points;
201 QVector<QPointF> points;
202 if (m_dirty || m_points.isEmpty()) {
202 if (m_dirty || m_points.isEmpty()) {
203 points = domain()->calculateGeometryPoints(m_series->pointsVector());
203 points = domain()->calculateGeometryPoints(m_series->pointsVector());
204 } else {
204 } else {
205 QPointF point = domain()->calculateGeometryPoint(m_series->pointsVector().at(index),
205 QPointF point = domain()->calculateGeometryPoint(m_series->pointsVector().at(index),
206 m_validData);
206 m_validData);
207 if (!m_validData)
207 if (!m_validData)
208 m_points.clear();
208 m_points.clear();
209 points = m_points;
209 points = m_points;
210 if (m_validData)
210 if (m_validData)
211 points.replace(index, point);
211 points.replace(index, point);
212 }
212 }
213 updateChart(m_points, points, index);
213 updateChart(m_points, points, index);
214 }
214 }
215 }
215 }
216
216
217 void XYChart::handlePointsReplaced()
217 void XYChart::handlePointsReplaced()
218 {
218 {
219 if (m_series->useOpenGL()) {
219 if (m_series->useOpenGL()) {
220 updateGlChart();
220 updateGlChart();
221 } else {
221 } else {
222 // All the points were replaced -> recalculate
222 // All the points were replaced -> recalculate
223 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->pointsVector());
223 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->pointsVector());
224 updateChart(m_points, points, -1);
224 updateChart(m_points, points, -1);
225 }
225 }
226 }
226 }
227
227
228 void XYChart::handleDomainUpdated()
228 void XYChart::handleDomainUpdated()
229 {
229 {
230 if (m_series->useOpenGL()) {
230 if (m_series->useOpenGL()) {
231 updateGlChart();
231 updateGlChart();
232 } else {
232 } else {
233 if (isEmpty()) return;
233 if (isEmpty()) return;
234 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->pointsVector());
234 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->pointsVector());
235 updateChart(m_points, points);
235 updateChart(m_points, points);
236 }
236 }
237 }
237 }
238
238
239 bool XYChart::isEmpty()
239 bool XYChart::isEmpty()
240 {
240 {
241 return domain()->isEmpty() || m_series->points().isEmpty();
241 return domain()->isEmpty() || m_series->points().isEmpty();
242 }
242 }
243
243
244 #include "moc_xychart_p.cpp"
244 #include "moc_xychart_p.cpp"
245
245
246 QT_CHARTS_END_NAMESPACE
246 QT_CHARTS_END_NAMESPACE
@@ -1,1248 +1,1250
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
4 ** Contact: https://www.qt.io/licensing/
5 **
5 **
6 ** This file is part of the Qt Charts module of the Qt Toolkit.
6 ** This file is part of the Qt Charts module of the Qt Toolkit.
7 **
7 **
8 ** $QT_BEGIN_LICENSE:GPL$
8 ** $QT_BEGIN_LICENSE:GPL$
9 ** Commercial License Usage
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
16 **
17 ** GNU General Public License Usage
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 or (at your option) any later version
19 ** General Public License version 3 or (at your option) any later version
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
22 ** included in the packaging of this file. Please review the following
22 ** included in the packaging of this file. Please review the following
23 ** information to ensure the GNU General Public License requirements will
23 ** information to ensure the GNU General Public License requirements will
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25 **
25 **
26 ** $QT_END_LICENSE$
26 ** $QT_END_LICENSE$
27 **
27 **
28 ****************************************************************************/
28 ****************************************************************************/
29
29
30 #include "declarativechart.h"
30 #include "declarativechart.h"
31 #include <QtGui/QPainter>
31 #include <QtGui/QPainter>
32 #include "declarativelineseries.h"
32 #include "declarativelineseries.h"
33 #include "declarativeareaseries.h"
33 #include "declarativeareaseries.h"
34 #include "declarativebarseries.h"
34 #include "declarativebarseries.h"
35 #include "declarativepieseries.h"
35 #include "declarativepieseries.h"
36 #include "declarativesplineseries.h"
36 #include "declarativesplineseries.h"
37 #include "declarativeboxplotseries.h"
37 #include "declarativeboxplotseries.h"
38 #include "declarativescatterseries.h"
38 #include "declarativescatterseries.h"
39 #include "declarativechartnode.h"
39 #include "declarativechartnode.h"
40 #include "declarativerendernode.h"
40 #include "declarativerendernode.h"
41 #include <QtCharts/QBarCategoryAxis>
41 #include <QtCharts/QBarCategoryAxis>
42 #include <QtCharts/QValueAxis>
42 #include <QtCharts/QValueAxis>
43 #include <QtCharts/QLogValueAxis>
43 #include <QtCharts/QLogValueAxis>
44 #include <QtCharts/QCategoryAxis>
44 #include <QtCharts/QCategoryAxis>
45 #include <private/qabstractseries_p.h>
45 #include <private/qabstractseries_p.h>
46 #include "declarativemargins.h"
46 #include "declarativemargins.h"
47 #include <private/chartdataset_p.h>
47 #include <private/chartdataset_p.h>
48 #include "declarativeaxes.h"
48 #include "declarativeaxes.h"
49 #include <private/qchart_p.h>
49 #include <private/qchart_p.h>
50 #include <private/chartpresenter_p.h>
50 #include <private/chartpresenter_p.h>
51 #include <QtCharts/QPolarChart>
51 #include <QtCharts/QPolarChart>
52
52
53 #ifndef QT_QREAL_IS_FLOAT
53 #ifndef QT_QREAL_IS_FLOAT
54 #include <QtCharts/QDateTimeAxis>
54 #include <QtCharts/QDateTimeAxis>
55 #endif
55 #endif
56
56
57 #include <QtWidgets/QGraphicsSceneMouseEvent>
57 #include <QtWidgets/QGraphicsSceneMouseEvent>
58 #include <QtWidgets/QGraphicsSceneHoverEvent>
58 #include <QtWidgets/QGraphicsSceneHoverEvent>
59 #include <QtWidgets/QApplication>
59 #include <QtWidgets/QApplication>
60 #include <QtCore/QTimer>
60 #include <QtCore/QTimer>
61 #include <QtCore/QThread>
61 #include <QtCore/QThread>
62
62
63 QT_CHARTS_BEGIN_NAMESPACE
63 QT_CHARTS_BEGIN_NAMESPACE
64
64
65 /*!
65 /*!
66 \qmltype ChartView
66 \qmltype ChartView
67 \instantiates DeclarativeChart
67 \instantiates DeclarativeChart
68 \inqmlmodule QtCharts
68 \inqmlmodule QtCharts
69
69
70 \brief Chart element.
70 \brief Chart element.
71
71
72 ChartView element is the parent that is responsible for showing different chart series types.
72 ChartView element is the parent that is responsible for showing different chart series types.
73
73
74 The following QML shows how to create a simple chart with one pie series:
74 The following QML shows how to create a simple chart with one pie series:
75 \snippet qmlpiechart/qml/qmlpiechart/main.qml 1
75 \snippet qmlpiechart/qml/qmlpiechart/main.qml 1
76 \snippet qmlpiechart/qml/qmlpiechart/main.qml 2
76 \snippet qmlpiechart/qml/qmlpiechart/main.qml 2
77 \snippet qmlpiechart/qml/qmlpiechart/main.qml 3
77 \snippet qmlpiechart/qml/qmlpiechart/main.qml 3
78
78
79 \beginfloatleft
79 \beginfloatleft
80 \image examples_qmlpiechart.png
80 \image examples_qmlpiechart.png
81 \endfloat
81 \endfloat
82 \clearfloat
82 \clearfloat
83 */
83 */
84
84
85 /*!
85 /*!
86 \qmlproperty Theme ChartView::theme
86 \qmlproperty Theme ChartView::theme
87 Theme defines the visual appearance of the chart, including for example colors, fonts, line
87 Theme defines the visual appearance of the chart, including for example colors, fonts, line
88 widths and chart background.
88 widths and chart background.
89 */
89 */
90
90
91 /*!
91 /*!
92 \qmlproperty Animation ChartView::animationOptions
92 \qmlproperty Animation ChartView::animationOptions
93 Animation configuration of the chart. One of ChartView.NoAnimation, ChartView.GridAxisAnimations,
93 Animation configuration of the chart. One of ChartView.NoAnimation, ChartView.GridAxisAnimations,
94 ChartView.SeriesAnimations or ChartView.AllAnimations.
94 ChartView.SeriesAnimations or ChartView.AllAnimations.
95 */
95 */
96
96
97 /*!
97 /*!
98 \qmlproperty int ChartView::animationDuration
98 \qmlproperty int ChartView::animationDuration
99 The duration of the animation for the chart.
99 The duration of the animation for the chart.
100 */
100 */
101
101
102 /*!
102 /*!
103 \qmlproperty easing ChartView::animationEasingCurve
103 \qmlproperty easing ChartView::animationEasingCurve
104 The easing curve of the animation for the chart.
104 The easing curve of the animation for the chart.
105 */
105 */
106
106
107 /*!
107 /*!
108 \qmlproperty Font ChartView::titleFont
108 \qmlproperty Font ChartView::titleFont
109 The title font of the chart.
109 The title font of the chart.
110
110
111 See the Qt documentation for more details of Font.
111 See the Qt documentation for more details of Font.
112 */
112 */
113
113
114 /*!
114 /*!
115 \qmlproperty string ChartView::title
115 \qmlproperty string ChartView::title
116 The title of the chart, shown on top of the chart.
116 The title of the chart, shown on top of the chart.
117 \sa ChartView::titleColor
117 \sa ChartView::titleColor
118 */
118 */
119
119
120 /*!
120 /*!
121 \qmlproperty color ChartView::titleColor
121 \qmlproperty color ChartView::titleColor
122 The color of the title text.
122 The color of the title text.
123 */
123 */
124
124
125 /*!
125 /*!
126 \qmlproperty Legend ChartView::legend
126 \qmlproperty Legend ChartView::legend
127 The legend of the chart. Legend lists all the series, pie slices and bar sets added on the chart.
127 The legend of the chart. Legend lists all the series, pie slices and bar sets added on the chart.
128 */
128 */
129
129
130 /*!
130 /*!
131 \qmlproperty int ChartView::count
131 \qmlproperty int ChartView::count
132 The count of series added to the chart.
132 The count of series added to the chart.
133 */
133 */
134
134
135 /*!
135 /*!
136 \qmlproperty color ChartView::backgroundColor
136 \qmlproperty color ChartView::backgroundColor
137 The color of the chart's background. By default background color is defined by chart theme.
137 The color of the chart's background. By default background color is defined by chart theme.
138 \sa ChartView::theme
138 \sa ChartView::theme
139 */
139 */
140
140
141 /*!
141 /*!
142 \qmlproperty real ChartView::backgroundRoundness
142 \qmlproperty real ChartView::backgroundRoundness
143 The diameter of the rounding circle at the corners of the chart background.
143 The diameter of the rounding circle at the corners of the chart background.
144 */
144 */
145
145
146 /*!
146 /*!
147 \qmlproperty color ChartView::plotAreaColor
147 \qmlproperty color ChartView::plotAreaColor
148 The color of the background of the chart's plot area. By default plot area background uses chart's
148 The color of the background of the chart's plot area. By default plot area background uses chart's
149 background color.
149 background color.
150 \sa ChartView::backgroundColor
150 \sa ChartView::backgroundColor
151 */
151 */
152
152
153 /*!
153 /*!
154 \qmlproperty list<AbstractAxis> ChartView::axes
154 \qmlproperty list<AbstractAxis> ChartView::axes
155 The axes of the ChartView.
155 The axes of the ChartView.
156 */
156 */
157
157
158 /*!
158 /*!
159 \qmlproperty bool ChartView::dropShadowEnabled
159 \qmlproperty bool ChartView::dropShadowEnabled
160 The chart's border drop shadow. Set to true to enable drop shadow.
160 The chart's border drop shadow. Set to true to enable drop shadow.
161 */
161 */
162
162
163 /*!
163 /*!
164 \qmlproperty rect ChartView::plotArea
164 \qmlproperty rect ChartView::plotArea
165 The area on the ChartView that is used for drawing series. This is the ChartView rect without the
165 The area on the ChartView that is used for drawing series. This is the ChartView rect without the
166 margins.
166 margins.
167 \sa ChartView::margins
167 \sa ChartView::margins
168 */
168 */
169
169
170 /*!
170 /*!
171 \qmlproperty Margins ChartView::margins
171 \qmlproperty Margins ChartView::margins
172 The minimum margins allowed between the outer bounds and the plotArea of the ChartView. Margins
172 The minimum margins allowed between the outer bounds and the plotArea of the ChartView. Margins
173 area of ChartView is used for drawing title, axes and legend.
173 area of ChartView is used for drawing title, axes and legend.
174 */
174 */
175
175
176 /*!
176 /*!
177 \qmlproperty bool ChartView::localizeNumbers
177 \qmlproperty bool ChartView::localizeNumbers
178 \since QtCharts 2.0
178 \since QtCharts 2.0
179 When \c{true}, all generated numbers appearing in various series and axis labels will be
179 When \c{true}, all generated numbers appearing in various series and axis labels will be
180 localized using the default QLocale of the application, which defaults to the system locale.
180 localized using the default QLocale of the application, which defaults to the system locale.
181 When \c{false}, the "C" locale is always used.
181 When \c{false}, the "C" locale is always used.
182 Defaults to \c{false}.
182 Defaults to \c{false}.
183
183
184 \sa locale
184 \sa locale
185 */
185 */
186
186
187 /*!
187 /*!
188 \qmlproperty locale ChartView::locale
188 \qmlproperty locale ChartView::locale
189 \since QtCharts 2.0
189 \since QtCharts 2.0
190 Sets the locale used to format various chart labels when localizeNumbers is \c{true}.
190 Sets the locale used to format various chart labels when localizeNumbers is \c{true}.
191 This also determines the locale used to format DateTimeAxis labels regardless of
191 This also determines the locale used to format DateTimeAxis labels regardless of
192 localizeNumbers property.
192 localizeNumbers property.
193 Defaults to application default locale at the time the chart is constructed.
193 Defaults to application default locale at the time the chart is constructed.
194
194
195 \sa localizeNumbers
195 \sa localizeNumbers
196 */
196 */
197
197
198 /*!
198 /*!
199 \qmlmethod AbstractSeries ChartView::series(int index)
199 \qmlmethod AbstractSeries ChartView::series(int index)
200 Returns the series with \a index on the chart. This allows you to loop through the series of a chart together with
200 Returns the series with \a index on the chart. This allows you to loop through the series of a chart together with
201 the count property of the chart.
201 the count property of the chart.
202 */
202 */
203
203
204 /*!
204 /*!
205 \qmlmethod AbstractSeries ChartView::series(string name)
205 \qmlmethod AbstractSeries ChartView::series(string name)
206 Returns the first series on the chart with \a name. If there is no series with that name, returns null.
206 Returns the first series on the chart with \a name. If there is no series with that name, returns null.
207 */
207 */
208
208
209 /*!
209 /*!
210 \qmlmethod AbstractSeries ChartView::createSeries(SeriesType type, string name, AbstractAxis axisX, AbstractAxis axisY)
210 \qmlmethod AbstractSeries ChartView::createSeries(SeriesType type, string name, AbstractAxis axisX, AbstractAxis axisY)
211 Creates a series object of \a type to the chart with name \a name, optional axis \a axisX and
211 Creates a series object of \a type to the chart with name \a name, optional axis \a axisX and
212 optional axis \a axisY. For example:
212 optional axis \a axisY. For example:
213 \code
213 \code
214 // lineSeries is a LineSeries object that has already been added to the ChartView; re-use it's axes
214 // lineSeries is a LineSeries object that has already been added to the ChartView; re-use it's axes
215 var myAxisX = chartView.axisX(lineSeries);
215 var myAxisX = chartView.axisX(lineSeries);
216 var myAxisY = chartView.axisY(lineSeries);
216 var myAxisY = chartView.axisY(lineSeries);
217 var scatter = chartView.createSeries(ChartView.SeriesTypeScatter, "scatter series", myAxisX, myAxisY);
217 var scatter = chartView.createSeries(ChartView.SeriesTypeScatter, "scatter series", myAxisX, myAxisY);
218 \endcode
218 \endcode
219 */
219 */
220
220
221 /*!
221 /*!
222 \qmlmethod ChartView::removeSeries(AbstractSeries series)
222 \qmlmethod ChartView::removeSeries(AbstractSeries series)
223 Removes the \a series from the chart. The series object is also destroyed.
223 Removes the \a series from the chart. The series object is also destroyed.
224 */
224 */
225
225
226 /*!
226 /*!
227 \qmlmethod ChartView::removeAllSeries()
227 \qmlmethod ChartView::removeAllSeries()
228 Removes all series from the chart. All the series objects are also destroyed.
228 Removes all series from the chart. All the series objects are also destroyed.
229 */
229 */
230
230
231 /*!
231 /*!
232 \qmlmethod Axis ChartView::axisX(AbstractSeries series)
232 \qmlmethod Axis ChartView::axisX(AbstractSeries series)
233 The x-axis of the series.
233 The x-axis of the series.
234 */
234 */
235
235
236 /*!
236 /*!
237 \qmlmethod ChartView::setAxisX(AbstractAxis axis, AbstractSeries series)
237 \qmlmethod ChartView::setAxisX(AbstractAxis axis, AbstractSeries series)
238 Set the x-axis of the series.
238 Set the x-axis of the series.
239 */
239 */
240
240
241 /*!
241 /*!
242 \qmlmethod Axis ChartView::axisY(AbstractSeries series)
242 \qmlmethod Axis ChartView::axisY(AbstractSeries series)
243 The y-axis of the series.
243 The y-axis of the series.
244 */
244 */
245
245
246 /*!
246 /*!
247 \qmlmethod ChartView::setAxisY(AbstractAxis axis, AbstractSeries series)
247 \qmlmethod ChartView::setAxisY(AbstractAxis axis, AbstractSeries series)
248 Set the y-axis of the series.
248 Set the y-axis of the series.
249 */
249 */
250
250
251 /*!
251 /*!
252 \qmlmethod ChartView::zoom(real factor)
252 \qmlmethod ChartView::zoom(real factor)
253 Zooms in by \a factor on the center of the chart.
253 Zooms in by \a factor on the center of the chart.
254
254
255 A factor over 1.0 zooms the view in and factor between 0.0 and 1.0 zooms out.
255 A factor over 1.0 zooms the view in and factor between 0.0 and 1.0 zooms out.
256 */
256 */
257
257
258 /*!
258 /*!
259 \qmlmethod ChartView::zoomIn()
259 \qmlmethod ChartView::zoomIn()
260 Zooms in the view by a factor of two.
260 Zooms in the view by a factor of two.
261 */
261 */
262
262
263 /*!
263 /*!
264 \qmlmethod ChartView::zoomIn(rect rectangle)
264 \qmlmethod ChartView::zoomIn(rect rectangle)
265 Zooms in the view to a maximum level at which \a rectangle is still fully visible.
265 Zooms in the view to a maximum level at which \a rectangle is still fully visible.
266 \note This is not supported for polar charts.
266 \note This is not supported for polar charts.
267 */
267 */
268
268
269 /*!
269 /*!
270 \qmlmethod ChartView::zoomOut()
270 \qmlmethod ChartView::zoomOut()
271 Zooms out the view by a factor of two.
271 Zooms out the view by a factor of two.
272 */
272 */
273
273
274 /*!
274 /*!
275 \qmlmethod ChartView::zoomReset()
275 \qmlmethod ChartView::zoomReset()
276 Resets the series domains to what they were before any zoom method was called.
276 Resets the series domains to what they were before any zoom method was called.
277 Note that this will also reset any scrolls and explicit axis range settings done between
277 Note that this will also reset any scrolls and explicit axis range settings done between
278 the first zoom operation and calling this method. If no zoom operation has been
278 the first zoom operation and calling this method. If no zoom operation has been
279 done, this method does nothing.
279 done, this method does nothing.
280 */
280 */
281
281
282 /*!
282 /*!
283 \qmlmethod ChartView::isZoomed()
283 \qmlmethod ChartView::isZoomed()
284 Returns true if any series has a zoomed domain.
284 Returns true if any series has a zoomed domain.
285 */
285 */
286
286
287 /*!
287 /*!
288 \qmlmethod ChartView::scrollLeft(real pixels)
288 \qmlmethod ChartView::scrollLeft(real pixels)
289 Scrolls to left by \a pixels. This is a convenience function that suits for example for key navigation.
289 Scrolls to left by \a pixels. This is a convenience function that suits for example for key navigation.
290 */
290 */
291
291
292 /*!
292 /*!
293 \qmlmethod ChartView::scrollRight(real pixels)
293 \qmlmethod ChartView::scrollRight(real pixels)
294 Scrolls to right by \a pixels. This is a convenience function that suits for example for key navigation.
294 Scrolls to right by \a pixels. This is a convenience function that suits for example for key navigation.
295 */
295 */
296
296
297 /*!
297 /*!
298 \qmlmethod ChartView::scrollUp(real pixels)
298 \qmlmethod ChartView::scrollUp(real pixels)
299 Scrolls up by \a pixels. This is a convenience function that suits for example for key navigation.
299 Scrolls up by \a pixels. This is a convenience function that suits for example for key navigation.
300 */
300 */
301
301
302 /*!
302 /*!
303 \qmlmethod ChartView::scrollDown(real pixels)
303 \qmlmethod ChartView::scrollDown(real pixels)
304 Scrolls down by \a pixels. This is a convenience function that suits for example for key navigation.
304 Scrolls down by \a pixels. This is a convenience function that suits for example for key navigation.
305 */
305 */
306
306
307 /*!
307 /*!
308 \qmlmethod point ChartView::mapToValue(point position, AbstractSeries series)
308 \qmlmethod point ChartView::mapToValue(point position, AbstractSeries series)
309 Returns the value in the \a series domain that corresponds to the \a position relative to the
309 Returns the value in the \a series domain that corresponds to the \a position relative to the
310 chart.
310 chart.
311 */
311 */
312
312
313 /*!
313 /*!
314 \qmlmethod point ChartView::mapToPosition(point value, AbstractSeries series)
314 \qmlmethod point ChartView::mapToPosition(point value, AbstractSeries series)
315 Returns the position on the chart that corresponds to the \a value in the \a series domain.
315 Returns the position on the chart that corresponds to the \a value in the \a series domain.
316 */
316 */
317
317
318 /*!
318 /*!
319 \qmlsignal ChartView::seriesAdded(AbstractSeries series)
319 \qmlsignal ChartView::seriesAdded(AbstractSeries series)
320 The \a series has been added to the chart.
320 The \a series has been added to the chart.
321 */
321 */
322
322
323 /*!
323 /*!
324 \qmlsignal ChartView::seriesRemoved(AbstractSeries series)
324 \qmlsignal ChartView::seriesRemoved(AbstractSeries series)
325 The \a series has been removed from the chart. Please note that \a series is no longer a valid
325 The \a series has been removed from the chart. Please note that \a series is no longer a valid
326 object after the signal handler has completed.
326 object after the signal handler has completed.
327 */
327 */
328
328
329 DeclarativeChart::DeclarativeChart(QQuickItem *parent)
329 DeclarativeChart::DeclarativeChart(QQuickItem *parent)
330 : QQuickItem(parent)
330 : QQuickItem(parent)
331 {
331 {
332 initChart(QChart::ChartTypeCartesian);
332 initChart(QChart::ChartTypeCartesian);
333 }
333 }
334
334
335 DeclarativeChart::DeclarativeChart(QChart::ChartType type, QQuickItem *parent)
335 DeclarativeChart::DeclarativeChart(QChart::ChartType type, QQuickItem *parent)
336 : QQuickItem(parent)
336 : QQuickItem(parent)
337 {
337 {
338 initChart(type);
338 initChart(type);
339 }
339 }
340
340
341 void DeclarativeChart::initChart(QChart::ChartType type)
341 void DeclarativeChart::initChart(QChart::ChartType type)
342 {
342 {
343 m_sceneImage = 0;
343 m_sceneImage = 0;
344 m_sceneImageDirty = false;
344 m_sceneImageDirty = false;
345 m_sceneImageNeedsClear = false;
345 m_sceneImageNeedsClear = false;
346 m_guiThreadId = QThread::currentThreadId();
346 m_guiThreadId = QThread::currentThreadId();
347 m_paintThreadId = 0;
347 m_paintThreadId = 0;
348 m_updatePending = false;
348 m_updatePending = false;
349
349
350 setFlag(ItemHasContents, true);
350 setFlag(ItemHasContents, true);
351
351
352 if (type == QChart::ChartTypePolar)
352 if (type == QChart::ChartTypePolar)
353 m_chart = new QPolarChart();
353 m_chart = new QPolarChart();
354 else
354 else
355 m_chart = new QChart();
355 m_chart = new QChart();
356
356
357 m_chart->d_ptr->m_presenter->glSetUseWidget(false);
357 m_chart->d_ptr->m_presenter->glSetUseWidget(false);
358 m_glXYDataManager = m_chart->d_ptr->m_dataset->glXYSeriesDataManager();
358 m_glXYDataManager = m_chart->d_ptr->m_dataset->glXYSeriesDataManager();
359
359
360 m_scene = new QGraphicsScene(this);
360 m_scene = new QGraphicsScene(this);
361 m_scene->addItem(m_chart);
361 m_scene->addItem(m_chart);
362
362
363 setAntialiasing(QQuickItem::antialiasing());
363 setAntialiasing(QQuickItem::antialiasing());
364 connect(m_scene, &QGraphicsScene::changed, this, &DeclarativeChart::sceneChanged);
364 connect(m_scene, &QGraphicsScene::changed, this, &DeclarativeChart::sceneChanged);
365 connect(this, &DeclarativeChart::needRender, this, &DeclarativeChart::renderScene,
365 connect(this, &DeclarativeChart::needRender, this, &DeclarativeChart::renderScene,
366 Qt::QueuedConnection);
366 Qt::QueuedConnection);
367 connect(this, SIGNAL(antialiasingChanged(bool)), this, SLOT(handleAntialiasingChanged(bool)));
367 connect(this, SIGNAL(antialiasingChanged(bool)), this, SLOT(handleAntialiasingChanged(bool)));
368
368
369 setAcceptedMouseButtons(Qt::AllButtons);
369 setAcceptedMouseButtons(Qt::AllButtons);
370 setAcceptHoverEvents(true);
370 setAcceptHoverEvents(true);
371
371
372 m_margins = new DeclarativeMargins(this);
372 m_margins = new DeclarativeMargins(this);
373 m_margins->setTop(m_chart->margins().top());
373 m_margins->setTop(m_chart->margins().top());
374 m_margins->setLeft(m_chart->margins().left());
374 m_margins->setLeft(m_chart->margins().left());
375 m_margins->setRight(m_chart->margins().right());
375 m_margins->setRight(m_chart->margins().right());
376 m_margins->setBottom(m_chart->margins().bottom());
376 m_margins->setBottom(m_chart->margins().bottom());
377 connect(m_margins, SIGNAL(topChanged(int,int,int,int)),
377 connect(m_margins, SIGNAL(topChanged(int,int,int,int)),
378 this, SLOT(changeMargins(int,int,int,int)));
378 this, SLOT(changeMargins(int,int,int,int)));
379 connect(m_margins, SIGNAL(bottomChanged(int,int,int,int)),
379 connect(m_margins, SIGNAL(bottomChanged(int,int,int,int)),
380 this, SLOT(changeMargins(int,int,int,int)));
380 this, SLOT(changeMargins(int,int,int,int)));
381 connect(m_margins, SIGNAL(leftChanged(int,int,int,int)),
381 connect(m_margins, SIGNAL(leftChanged(int,int,int,int)),
382 this, SLOT(changeMargins(int,int,int,int)));
382 this, SLOT(changeMargins(int,int,int,int)));
383 connect(m_margins, SIGNAL(rightChanged(int,int,int,int)),
383 connect(m_margins, SIGNAL(rightChanged(int,int,int,int)),
384 this, SLOT(changeMargins(int,int,int,int)));
384 this, SLOT(changeMargins(int,int,int,int)));
385 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesAdded(QAbstractSeries*)));
385 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesAdded(QAbstractSeries*)));
386 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SIGNAL(seriesRemoved(QAbstractSeries*)));
386 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SIGNAL(seriesRemoved(QAbstractSeries*)));
387 connect(m_chart, &QChart::plotAreaChanged, this, &DeclarativeChart::plotAreaChanged);
387 connect(m_chart, &QChart::plotAreaChanged, this, &DeclarativeChart::plotAreaChanged);
388 }
388 }
389
389
390 void DeclarativeChart::handleSeriesAdded(QAbstractSeries *series)
390 void DeclarativeChart::handleSeriesAdded(QAbstractSeries *series)
391 {
391 {
392 emit seriesAdded(series);
392 emit seriesAdded(series);
393 }
393 }
394
394
395 void DeclarativeChart::changeMargins(int top, int bottom, int left, int right)
395 void DeclarativeChart::changeMargins(int top, int bottom, int left, int right)
396 {
396 {
397 m_chart->setMargins(QMargins(left, top, right, bottom));
397 m_chart->setMargins(QMargins(left, top, right, bottom));
398 emit marginsChanged();
398 emit marginsChanged();
399 }
399 }
400
400
401 DeclarativeChart::~DeclarativeChart()
401 DeclarativeChart::~DeclarativeChart()
402 {
402 {
403 delete m_chart;
403 delete m_chart;
404 delete m_sceneImage;
404 delete m_sceneImage;
405 }
405 }
406
406
407 void DeclarativeChart::childEvent(QChildEvent *event)
407 void DeclarativeChart::childEvent(QChildEvent *event)
408 {
408 {
409 if (event->type() == QEvent::ChildAdded) {
409 if (event->type() == QEvent::ChildAdded) {
410 if (qobject_cast<QAbstractSeries *>(event->child())) {
410 if (qobject_cast<QAbstractSeries *>(event->child())) {
411 m_chart->addSeries(qobject_cast<QAbstractSeries *>(event->child()));
411 m_chart->addSeries(qobject_cast<QAbstractSeries *>(event->child()));
412 }
412 }
413 }
413 }
414 }
414 }
415
415
416 void DeclarativeChart::componentComplete()
416 void DeclarativeChart::componentComplete()
417 {
417 {
418 foreach (QObject *child, children()) {
418 foreach (QObject *child, children()) {
419 if (qobject_cast<QAbstractSeries *>(child)) {
419 if (qobject_cast<QAbstractSeries *>(child)) {
420 // Add series to the chart
420 // Add series to the chart
421 QAbstractSeries *series = qobject_cast<QAbstractSeries *>(child);
421 QAbstractSeries *series = qobject_cast<QAbstractSeries *>(child);
422 m_chart->addSeries(series);
422 m_chart->addSeries(series);
423
423
424 // Connect to axis changed signals (unless this is a pie series)
424 // Connect to axis changed signals (unless this is a pie series)
425 if (!qobject_cast<DeclarativePieSeries *>(series)) {
425 if (!qobject_cast<DeclarativePieSeries *>(series)) {
426 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
426 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
427 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXTopSet(QAbstractAxis*)));
427 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXTopSet(QAbstractAxis*)));
428 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
428 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
429 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
429 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
430 }
430 }
431
431
432 initializeAxes(series);
432 initializeAxes(series);
433 }
433 }
434 }
434 }
435
435
436 QQuickItem::componentComplete();
436 QQuickItem::componentComplete();
437 }
437 }
438
438
439 void DeclarativeChart::seriesAxisAttachHelper(QAbstractSeries *series, QAbstractAxis *axis,
439 void DeclarativeChart::seriesAxisAttachHelper(QAbstractSeries *series, QAbstractAxis *axis,
440 Qt::Orientations orientation,
440 Qt::Orientations orientation,
441 Qt::Alignment alignment)
441 Qt::Alignment alignment)
442 {
442 {
443 if (!series->attachedAxes().contains(axis)) {
443 if (!series->attachedAxes().contains(axis)) {
444 // Remove & delete old axes that are not attached to any other series
444 // Remove & delete old axes that are not attached to any other series
445 foreach (QAbstractAxis* oldAxis, m_chart->axes(orientation, series)) {
445 foreach (QAbstractAxis* oldAxis, m_chart->axes(orientation, series)) {
446 bool otherAttachments = false;
446 bool otherAttachments = false;
447 if (oldAxis != axis) {
447 if (oldAxis != axis) {
448 foreach (QAbstractSeries *oldSeries, m_chart->series()) {
448 foreach (QAbstractSeries *oldSeries, m_chart->series()) {
449 if (oldSeries != series && oldSeries->attachedAxes().contains(oldAxis)) {
449 if (oldSeries != series && oldSeries->attachedAxes().contains(oldAxis)) {
450 otherAttachments = true;
450 otherAttachments = true;
451 break;
451 break;
452 }
452 }
453 }
453 }
454 if (!otherAttachments) {
454 if (!otherAttachments) {
455 m_chart->removeAxis(oldAxis);
455 m_chart->removeAxis(oldAxis);
456 delete oldAxis;
456 delete oldAxis;
457 }
457 }
458 }
458 }
459 }
459 }
460 if (!m_chart->axes(orientation).contains(axis))
460 if (!m_chart->axes(orientation).contains(axis))
461 m_chart->addAxis(axis, alignment);
461 m_chart->addAxis(axis, alignment);
462
462
463 series->attachAxis(axis);
463 series->attachAxis(axis);
464 }
464 }
465 }
465 }
466
466
467 void DeclarativeChart::handleAxisXSet(QAbstractAxis *axis)
467 void DeclarativeChart::handleAxisXSet(QAbstractAxis *axis)
468 {
468 {
469 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
469 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
470 if (axis && s) {
470 if (axis && s) {
471 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignBottom);
471 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignBottom);
472 } else {
472 } else {
473 qWarning() << "Trying to set axisX to null.";
473 qWarning() << "Trying to set axisX to null.";
474 }
474 }
475 }
475 }
476
476
477 void DeclarativeChart::handleAxisXTopSet(QAbstractAxis *axis)
477 void DeclarativeChart::handleAxisXTopSet(QAbstractAxis *axis)
478 {
478 {
479 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
479 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
480 if (axis && s) {
480 if (axis && s) {
481 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignTop);
481 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignTop);
482 } else {
482 } else {
483 qWarning() << "Trying to set axisXTop to null.";
483 qWarning() << "Trying to set axisXTop to null.";
484 }
484 }
485 }
485 }
486
486
487 void DeclarativeChart::handleAxisYSet(QAbstractAxis *axis)
487 void DeclarativeChart::handleAxisYSet(QAbstractAxis *axis)
488 {
488 {
489 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
489 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
490 if (axis && s) {
490 if (axis && s) {
491 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignLeft);
491 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignLeft);
492 } else {
492 } else {
493 qWarning() << "Trying to set axisY to null.";
493 qWarning() << "Trying to set axisY to null.";
494 }
494 }
495 }
495 }
496
496
497 void DeclarativeChart::handleAxisYRightSet(QAbstractAxis *axis)
497 void DeclarativeChart::handleAxisYRightSet(QAbstractAxis *axis)
498 {
498 {
499 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
499 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
500 if (axis && s) {
500 if (axis && s) {
501 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignRight);
501 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignRight);
502 } else {
502 } else {
503 qWarning() << "Trying to set axisYRight to null.";
503 qWarning() << "Trying to set axisYRight to null.";
504 }
504 }
505 }
505 }
506
506
507 void DeclarativeChart::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
507 void DeclarativeChart::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
508 {
508 {
509 if (newGeometry.isValid()) {
509 if (newGeometry.isValid()) {
510 if (newGeometry.width() > 0 && newGeometry.height() > 0) {
510 if (newGeometry.width() > 0 && newGeometry.height() > 0) {
511 m_chart->resize(newGeometry.width(), newGeometry.height());
511 m_chart->resize(newGeometry.width(), newGeometry.height());
512 }
512 }
513 }
513 }
514 QQuickItem::geometryChanged(newGeometry, oldGeometry);
514 QQuickItem::geometryChanged(newGeometry, oldGeometry);
515 }
515 }
516
516
517 QSGNode *DeclarativeChart::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
517 QSGNode *DeclarativeChart::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
518 {
518 {
519 DeclarativeChartNode *node = static_cast<DeclarativeChartNode *>(oldNode);
519 DeclarativeChartNode *node = static_cast<DeclarativeChartNode *>(oldNode);
520
520
521 if (!node) {
521 if (!node) {
522 node = new DeclarativeChartNode(window());
522 node = new DeclarativeChartNode(window());
523 connect(window(), &QQuickWindow::beforeRendering,
523 connect(window(), &QQuickWindow::beforeRendering,
524 node->glRenderNode(), &DeclarativeRenderNode::render);
524 node->glRenderNode(), &DeclarativeRenderNode::render);
525 }
525 }
526
526
527 const QRectF &bRect = boundingRect();
527 const QRectF &bRect = boundingRect();
528
528
529 // Update GL data
529 // Update GL data
530 if (m_glXYDataManager->dataMap().size() || m_glXYDataManager->mapDirty()) {
530 if (m_glXYDataManager->dataMap().size() || m_glXYDataManager->mapDirty()) {
531 const QRectF &plotArea = m_chart->plotArea();
531 const QRectF &plotArea = m_chart->plotArea();
532 const QSizeF &chartAreaSize = m_chart->size();
532 const QSizeF &chartAreaSize = m_chart->size();
533
533
534 // We can't use chart's plot area directly, as graphicscene has some internal minimum size
534 // We can't use chart's plot area directly, as graphicscene has some internal minimum size
535 const qreal normalizedX = plotArea.x() / chartAreaSize.width();
535 const qreal normalizedX = plotArea.x() / chartAreaSize.width();
536 const qreal normalizedY = plotArea.y() / chartAreaSize.height();
536 const qreal normalizedY = plotArea.y() / chartAreaSize.height();
537 const qreal normalizedWidth = plotArea.width() / chartAreaSize.width();
537 const qreal normalizedWidth = plotArea.width() / chartAreaSize.width();
538 const qreal normalizedHeight = plotArea.height() / chartAreaSize.height();
538 const qreal normalizedHeight = plotArea.height() / chartAreaSize.height();
539
539
540 QRectF adjustedPlotArea(normalizedX * bRect.width(),
540 QRectF adjustedPlotArea(normalizedX * bRect.width(),
541 normalizedY * bRect.height(),
541 normalizedY * bRect.height(),
542 normalizedWidth * bRect.width(),
542 normalizedWidth * bRect.width(),
543 normalizedHeight * bRect.height());
543 normalizedHeight * bRect.height());
544
544
545 const QSize &adjustedPlotSize = adjustedPlotArea.size().toSize();
545 const QSize &adjustedPlotSize = adjustedPlotArea.size().toSize();
546 if (adjustedPlotSize != node->glRenderNode()->textureSize())
546 if (adjustedPlotSize != node->glRenderNode()->textureSize())
547 node->glRenderNode()->setTextureSize(adjustedPlotSize);
547 node->glRenderNode()->setTextureSize(adjustedPlotSize);
548
548
549 node->glRenderNode()->setRect(adjustedPlotArea);
549 node->glRenderNode()->setRect(adjustedPlotArea);
550 node->glRenderNode()->setSeriesData(m_glXYDataManager->mapDirty(),
550 node->glRenderNode()->setSeriesData(m_glXYDataManager->mapDirty(),
551 m_glXYDataManager->dataMap());
551 m_glXYDataManager->dataMap());
552
552
553 // Clear dirty flags from original xy data
553 // Clear dirty flags from original xy data
554 m_glXYDataManager->clearAllDirty();
554 m_glXYDataManager->clearAllDirty();
555 }
555 }
556
556
557 // Copy chart (if dirty) to chart node
557 // Copy chart (if dirty) to chart node
558 if (m_sceneImageDirty) {
558 if (m_sceneImageDirty) {
559 node->createTextureFromImage(*m_sceneImage);
559 node->createTextureFromImage(*m_sceneImage);
560 m_sceneImageDirty = false;
560 m_sceneImageDirty = false;
561 }
561 }
562
562
563 node->setRect(bRect);
563 node->setRect(bRect);
564
564
565 return node;
565 return node;
566 }
566 }
567
567
568 void DeclarativeChart::sceneChanged(QList<QRectF> region)
568 void DeclarativeChart::sceneChanged(QList<QRectF> region)
569 {
569 {
570 const int count = region.size();
570 const int count = region.size();
571 const qreal limitSize = 0.01;
571 const qreal limitSize = 0.01;
572 if (count && !m_updatePending) {
572 if (count && !m_updatePending) {
573 qreal totalSize = 0.0;
573 qreal totalSize = 0.0;
574 for (int i = 0; i < count; i++) {
574 for (int i = 0; i < count; i++) {
575 const QRectF &reg = region.at(i);
575 const QRectF &reg = region.at(i);
576 totalSize += (reg.height() * reg.width());
576 totalSize += (reg.height() * reg.width());
577 if (totalSize >= limitSize)
577 if (totalSize >= limitSize)
578 break;
578 break;
579 }
579 }
580 // Ignore region updates that change less than small fraction of a pixel, as there is
580 // Ignore region updates that change less than small fraction of a pixel, as there is
581 // little point regenerating the image in these cases. These are typically cases
581 // little point regenerating the image in these cases. These are typically cases
582 // where OpenGL series are drawn to otherwise static chart.
582 // where OpenGL series are drawn to otherwise static chart.
583 if (totalSize >= limitSize) {
583 if (totalSize >= limitSize) {
584 m_updatePending = true;
584 m_updatePending = true;
585 // Do async render to avoid some unnecessary renders.
585 // Do async render to avoid some unnecessary renders.
586 emit needRender();
586 emit needRender();
587 } else {
587 } else {
588 // We do want to call update to trigger possible gl series updates.
588 // We do want to call update to trigger possible gl series updates.
589 update();
589 update();
590 }
590 }
591 }
591 }
592 }
592 }
593
593
594 void DeclarativeChart::renderScene()
594 void DeclarativeChart::renderScene()
595 {
595 {
596 m_updatePending = false;
596 m_updatePending = false;
597 m_sceneImageDirty = true;
597 m_sceneImageDirty = true;
598 QSize chartSize = m_chart->size().toSize();
598 QSize chartSize = m_chart->size().toSize();
599 if (!m_sceneImage || chartSize != m_sceneImage->size()) {
599 if (!m_sceneImage || chartSize != m_sceneImage->size()) {
600 delete m_sceneImage;
600 delete m_sceneImage;
601 m_sceneImage = new QImage(chartSize, QImage::Format_ARGB32);
601 qreal dpr = window() ? window()->devicePixelRatio() : 1.0;
602 m_sceneImage = new QImage(chartSize * dpr, QImage::Format_ARGB32);
603 m_sceneImage->setDevicePixelRatio(dpr);
602 m_sceneImageNeedsClear = true;
604 m_sceneImageNeedsClear = true;
603 }
605 }
604
606
605 if (m_sceneImageNeedsClear) {
607 if (m_sceneImageNeedsClear) {
606 m_sceneImage->fill(Qt::transparent);
608 m_sceneImage->fill(Qt::transparent);
607 // Don't clear the flag if chart background has any transparent element to it
609 // Don't clear the flag if chart background has any transparent element to it
608 if (m_chart->backgroundBrush().color().alpha() == 0xff && !m_chart->isDropShadowEnabled())
610 if (m_chart->backgroundBrush().color().alpha() == 0xff && !m_chart->isDropShadowEnabled())
609 m_sceneImageNeedsClear = false;
611 m_sceneImageNeedsClear = false;
610 }
612 }
611 QPainter painter(m_sceneImage);
613 QPainter painter(m_sceneImage);
612 if (antialiasing()) {
614 if (antialiasing()) {
613 painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing
615 painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing
614 | QPainter::SmoothPixmapTransform);
616 | QPainter::SmoothPixmapTransform);
615 }
617 }
616 QRect renderRect(QPoint(0, 0), chartSize);
618 QRect renderRect(QPoint(0, 0), chartSize);
617 m_scene->render(&painter, renderRect, renderRect);
619 m_scene->render(&painter, renderRect, renderRect);
618 update();
620 update();
619 }
621 }
620
622
621 void DeclarativeChart::mousePressEvent(QMouseEvent *event)
623 void DeclarativeChart::mousePressEvent(QMouseEvent *event)
622 {
624 {
623 m_mousePressScenePoint = event->pos();
625 m_mousePressScenePoint = event->pos();
624 m_mousePressScreenPoint = event->globalPos();
626 m_mousePressScreenPoint = event->globalPos();
625 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
627 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
626 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
628 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
627 m_mousePressButton = event->button();
629 m_mousePressButton = event->button();
628 m_mousePressButtons = event->buttons();
630 m_mousePressButtons = event->buttons();
629
631
630 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
632 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
631 mouseEvent.setWidget(0);
633 mouseEvent.setWidget(0);
632 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
634 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
633 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
635 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
634 mouseEvent.setScenePos(m_mousePressScenePoint);
636 mouseEvent.setScenePos(m_mousePressScenePoint);
635 mouseEvent.setScreenPos(m_mousePressScreenPoint);
637 mouseEvent.setScreenPos(m_mousePressScreenPoint);
636 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
638 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
637 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
639 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
638 mouseEvent.setButtons(m_mousePressButtons);
640 mouseEvent.setButtons(m_mousePressButtons);
639 mouseEvent.setButton(m_mousePressButton);
641 mouseEvent.setButton(m_mousePressButton);
640 mouseEvent.setModifiers(event->modifiers());
642 mouseEvent.setModifiers(event->modifiers());
641 mouseEvent.setAccepted(false);
643 mouseEvent.setAccepted(false);
642
644
643 QApplication::sendEvent(m_scene, &mouseEvent);
645 QApplication::sendEvent(m_scene, &mouseEvent);
644 }
646 }
645
647
646 void DeclarativeChart::mouseReleaseEvent(QMouseEvent *event)
648 void DeclarativeChart::mouseReleaseEvent(QMouseEvent *event)
647 {
649 {
648 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
650 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
649 mouseEvent.setWidget(0);
651 mouseEvent.setWidget(0);
650 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
652 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
651 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
653 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
652 mouseEvent.setScenePos(event->pos());
654 mouseEvent.setScenePos(event->pos());
653 mouseEvent.setScreenPos(event->globalPos());
655 mouseEvent.setScreenPos(event->globalPos());
654 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
656 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
655 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
657 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
656 mouseEvent.setButtons(event->buttons());
658 mouseEvent.setButtons(event->buttons());
657 mouseEvent.setButton(event->button());
659 mouseEvent.setButton(event->button());
658 mouseEvent.setModifiers(event->modifiers());
660 mouseEvent.setModifiers(event->modifiers());
659 mouseEvent.setAccepted(false);
661 mouseEvent.setAccepted(false);
660
662
661 QApplication::sendEvent(m_scene, &mouseEvent);
663 QApplication::sendEvent(m_scene, &mouseEvent);
662
664
663 m_mousePressButtons = event->buttons();
665 m_mousePressButtons = event->buttons();
664 m_mousePressButton = Qt::NoButton;
666 m_mousePressButton = Qt::NoButton;
665 }
667 }
666
668
667 void DeclarativeChart::hoverMoveEvent(QHoverEvent *event)
669 void DeclarativeChart::hoverMoveEvent(QHoverEvent *event)
668 {
670 {
669 // Convert hover move to mouse move, since we don't seem to get actual mouse move events.
671 // Convert hover move to mouse move, since we don't seem to get actual mouse move events.
670 // QGraphicsScene generates hover events from mouse move events, so we don't need
672 // QGraphicsScene generates hover events from mouse move events, so we don't need
671 // to pass hover events there.
673 // to pass hover events there.
672 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
674 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
673 mouseEvent.setWidget(0);
675 mouseEvent.setWidget(0);
674 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
676 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
675 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
677 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
676 mouseEvent.setScenePos(event->pos());
678 mouseEvent.setScenePos(event->pos());
677 // Hover events do not have global pos in them, and the screen position doesn't seem to
679 // Hover events do not have global pos in them, and the screen position doesn't seem to
678 // matter anyway in this use case, so just pass event pos instead of trying to
680 // matter anyway in this use case, so just pass event pos instead of trying to
679 // calculate the real screen position.
681 // calculate the real screen position.
680 mouseEvent.setScreenPos(event->pos());
682 mouseEvent.setScreenPos(event->pos());
681 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
683 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
682 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
684 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
683 mouseEvent.setButtons(m_mousePressButtons);
685 mouseEvent.setButtons(m_mousePressButtons);
684 mouseEvent.setButton(m_mousePressButton);
686 mouseEvent.setButton(m_mousePressButton);
685 mouseEvent.setModifiers(event->modifiers());
687 mouseEvent.setModifiers(event->modifiers());
686 m_lastMouseMoveScenePoint = mouseEvent.scenePos();
688 m_lastMouseMoveScenePoint = mouseEvent.scenePos();
687 m_lastMouseMoveScreenPoint = mouseEvent.screenPos();
689 m_lastMouseMoveScreenPoint = mouseEvent.screenPos();
688 mouseEvent.setAccepted(false);
690 mouseEvent.setAccepted(false);
689
691
690 QApplication::sendEvent(m_scene, &mouseEvent);
692 QApplication::sendEvent(m_scene, &mouseEvent);
691 }
693 }
692
694
693 void DeclarativeChart::mouseDoubleClickEvent(QMouseEvent *event)
695 void DeclarativeChart::mouseDoubleClickEvent(QMouseEvent *event)
694 {
696 {
695 m_mousePressScenePoint = event->pos();
697 m_mousePressScenePoint = event->pos();
696 m_mousePressScreenPoint = event->globalPos();
698 m_mousePressScreenPoint = event->globalPos();
697 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
699 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
698 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
700 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
699 m_mousePressButton = event->button();
701 m_mousePressButton = event->button();
700 m_mousePressButtons = event->buttons();
702 m_mousePressButtons = event->buttons();
701
703
702 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseDoubleClick);
704 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseDoubleClick);
703 mouseEvent.setWidget(0);
705 mouseEvent.setWidget(0);
704 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
706 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
705 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
707 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
706 mouseEvent.setScenePos(m_mousePressScenePoint);
708 mouseEvent.setScenePos(m_mousePressScenePoint);
707 mouseEvent.setScreenPos(m_mousePressScreenPoint);
709 mouseEvent.setScreenPos(m_mousePressScreenPoint);
708 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
710 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
709 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
711 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
710 mouseEvent.setButtons(m_mousePressButtons);
712 mouseEvent.setButtons(m_mousePressButtons);
711 mouseEvent.setButton(m_mousePressButton);
713 mouseEvent.setButton(m_mousePressButton);
712 mouseEvent.setModifiers(event->modifiers());
714 mouseEvent.setModifiers(event->modifiers());
713 mouseEvent.setAccepted(false);
715 mouseEvent.setAccepted(false);
714
716
715 QApplication::sendEvent(m_scene, &mouseEvent);
717 QApplication::sendEvent(m_scene, &mouseEvent);
716 }
718 }
717
719
718 void DeclarativeChart::handleAntialiasingChanged(bool enable)
720 void DeclarativeChart::handleAntialiasingChanged(bool enable)
719 {
721 {
720 setAntialiasing(enable);
722 setAntialiasing(enable);
721 }
723 }
722
724
723 void DeclarativeChart::setTheme(DeclarativeChart::Theme theme)
725 void DeclarativeChart::setTheme(DeclarativeChart::Theme theme)
724 {
726 {
725 QChart::ChartTheme chartTheme = (QChart::ChartTheme) theme;
727 QChart::ChartTheme chartTheme = (QChart::ChartTheme) theme;
726 if (chartTheme != m_chart->theme())
728 if (chartTheme != m_chart->theme())
727 m_chart->setTheme(chartTheme);
729 m_chart->setTheme(chartTheme);
728 }
730 }
729
731
730 DeclarativeChart::Theme DeclarativeChart::theme()
732 DeclarativeChart::Theme DeclarativeChart::theme()
731 {
733 {
732 return (DeclarativeChart::Theme) m_chart->theme();
734 return (DeclarativeChart::Theme) m_chart->theme();
733 }
735 }
734
736
735 void DeclarativeChart::setAnimationOptions(DeclarativeChart::Animation animations)
737 void DeclarativeChart::setAnimationOptions(DeclarativeChart::Animation animations)
736 {
738 {
737 QChart::AnimationOption animationOptions = (QChart::AnimationOption) animations;
739 QChart::AnimationOption animationOptions = (QChart::AnimationOption) animations;
738 if (animationOptions != m_chart->animationOptions())
740 if (animationOptions != m_chart->animationOptions())
739 m_chart->setAnimationOptions(animationOptions);
741 m_chart->setAnimationOptions(animationOptions);
740 }
742 }
741
743
742 DeclarativeChart::Animation DeclarativeChart::animationOptions()
744 DeclarativeChart::Animation DeclarativeChart::animationOptions()
743 {
745 {
744 if (m_chart->animationOptions().testFlag(QChart::AllAnimations))
746 if (m_chart->animationOptions().testFlag(QChart::AllAnimations))
745 return DeclarativeChart::AllAnimations;
747 return DeclarativeChart::AllAnimations;
746 else if (m_chart->animationOptions().testFlag(QChart::GridAxisAnimations))
748 else if (m_chart->animationOptions().testFlag(QChart::GridAxisAnimations))
747 return DeclarativeChart::GridAxisAnimations;
749 return DeclarativeChart::GridAxisAnimations;
748 else if (m_chart->animationOptions().testFlag(QChart::SeriesAnimations))
750 else if (m_chart->animationOptions().testFlag(QChart::SeriesAnimations))
749 return DeclarativeChart::SeriesAnimations;
751 return DeclarativeChart::SeriesAnimations;
750 else
752 else
751 return DeclarativeChart::NoAnimation;
753 return DeclarativeChart::NoAnimation;
752 }
754 }
753
755
754 void DeclarativeChart::setAnimationDuration(int msecs)
756 void DeclarativeChart::setAnimationDuration(int msecs)
755 {
757 {
756 if (msecs != m_chart->animationDuration()) {
758 if (msecs != m_chart->animationDuration()) {
757 m_chart->setAnimationDuration(msecs);
759 m_chart->setAnimationDuration(msecs);
758 emit animationDurationChanged(msecs);
760 emit animationDurationChanged(msecs);
759 }
761 }
760 }
762 }
761
763
762 int DeclarativeChart::animationDuration() const
764 int DeclarativeChart::animationDuration() const
763 {
765 {
764 return m_chart->animationDuration();
766 return m_chart->animationDuration();
765 }
767 }
766
768
767 void DeclarativeChart::setAnimationEasingCurve(const QEasingCurve &curve)
769 void DeclarativeChart::setAnimationEasingCurve(const QEasingCurve &curve)
768 {
770 {
769 if (curve != m_chart->animationEasingCurve()) {
771 if (curve != m_chart->animationEasingCurve()) {
770 m_chart->setAnimationEasingCurve(curve);
772 m_chart->setAnimationEasingCurve(curve);
771 emit animationEasingCurveChanged(curve);
773 emit animationEasingCurveChanged(curve);
772 }
774 }
773 }
775 }
774
776
775 QEasingCurve DeclarativeChart::animationEasingCurve() const
777 QEasingCurve DeclarativeChart::animationEasingCurve() const
776 {
778 {
777 return m_chart->animationEasingCurve();
779 return m_chart->animationEasingCurve();
778 }
780 }
779
781
780 void DeclarativeChart::setTitle(QString title)
782 void DeclarativeChart::setTitle(QString title)
781 {
783 {
782 if (title != m_chart->title())
784 if (title != m_chart->title())
783 m_chart->setTitle(title);
785 m_chart->setTitle(title);
784 }
786 }
785 QString DeclarativeChart::title()
787 QString DeclarativeChart::title()
786 {
788 {
787 return m_chart->title();
789 return m_chart->title();
788 }
790 }
789
791
790 QAbstractAxis *DeclarativeChart::axisX(QAbstractSeries *series)
792 QAbstractAxis *DeclarativeChart::axisX(QAbstractSeries *series)
791 {
793 {
792 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Horizontal, series);
794 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Horizontal, series);
793 if (axes.count())
795 if (axes.count())
794 return axes[0];
796 return axes[0];
795 return 0;
797 return 0;
796 }
798 }
797
799
798 QAbstractAxis *DeclarativeChart::axisY(QAbstractSeries *series)
800 QAbstractAxis *DeclarativeChart::axisY(QAbstractSeries *series)
799 {
801 {
800 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Vertical, series);
802 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Vertical, series);
801 if (axes.count())
803 if (axes.count())
802 return axes[0];
804 return axes[0];
803 return 0;
805 return 0;
804 }
806 }
805
807
806 QLegend *DeclarativeChart::legend()
808 QLegend *DeclarativeChart::legend()
807 {
809 {
808 return m_chart->legend();
810 return m_chart->legend();
809 }
811 }
810
812
811 void DeclarativeChart::setTitleColor(QColor color)
813 void DeclarativeChart::setTitleColor(QColor color)
812 {
814 {
813 QBrush b = m_chart->titleBrush();
815 QBrush b = m_chart->titleBrush();
814 if (color != b.color()) {
816 if (color != b.color()) {
815 b.setColor(color);
817 b.setColor(color);
816 m_chart->setTitleBrush(b);
818 m_chart->setTitleBrush(b);
817 emit titleColorChanged(color);
819 emit titleColorChanged(color);
818 }
820 }
819 }
821 }
820
822
821 QFont DeclarativeChart::titleFont() const
823 QFont DeclarativeChart::titleFont() const
822 {
824 {
823 return m_chart->titleFont();
825 return m_chart->titleFont();
824 }
826 }
825
827
826 void DeclarativeChart::setTitleFont(const QFont &font)
828 void DeclarativeChart::setTitleFont(const QFont &font)
827 {
829 {
828 m_chart->setTitleFont(font);
830 m_chart->setTitleFont(font);
829 }
831 }
830
832
831 QColor DeclarativeChart::titleColor()
833 QColor DeclarativeChart::titleColor()
832 {
834 {
833 return m_chart->titleBrush().color();
835 return m_chart->titleBrush().color();
834 }
836 }
835
837
836 void DeclarativeChart::setBackgroundColor(QColor color)
838 void DeclarativeChart::setBackgroundColor(QColor color)
837 {
839 {
838 QBrush b = m_chart->backgroundBrush();
840 QBrush b = m_chart->backgroundBrush();
839 if (b.style() != Qt::SolidPattern || color != b.color()) {
841 if (b.style() != Qt::SolidPattern || color != b.color()) {
840 if (color.alpha() < 0xff)
842 if (color.alpha() < 0xff)
841 m_sceneImageNeedsClear = true;
843 m_sceneImageNeedsClear = true;
842 b.setStyle(Qt::SolidPattern);
844 b.setStyle(Qt::SolidPattern);
843 b.setColor(color);
845 b.setColor(color);
844 m_chart->setBackgroundBrush(b);
846 m_chart->setBackgroundBrush(b);
845 emit backgroundColorChanged();
847 emit backgroundColorChanged();
846 }
848 }
847 }
849 }
848
850
849 QColor DeclarativeChart::backgroundColor()
851 QColor DeclarativeChart::backgroundColor()
850 {
852 {
851 return m_chart->backgroundBrush().color();
853 return m_chart->backgroundBrush().color();
852 }
854 }
853
855
854 void QtCharts::DeclarativeChart::setPlotAreaColor(QColor color)
856 void QtCharts::DeclarativeChart::setPlotAreaColor(QColor color)
855 {
857 {
856 QBrush b = m_chart->plotAreaBackgroundBrush();
858 QBrush b = m_chart->plotAreaBackgroundBrush();
857 if (b.style() != Qt::SolidPattern || color != b.color()) {
859 if (b.style() != Qt::SolidPattern || color != b.color()) {
858 b.setStyle(Qt::SolidPattern);
860 b.setStyle(Qt::SolidPattern);
859 b.setColor(color);
861 b.setColor(color);
860 m_chart->setPlotAreaBackgroundBrush(b);
862 m_chart->setPlotAreaBackgroundBrush(b);
861 m_chart->setPlotAreaBackgroundVisible(true);
863 m_chart->setPlotAreaBackgroundVisible(true);
862 emit plotAreaColorChanged();
864 emit plotAreaColorChanged();
863 }
865 }
864 }
866 }
865
867
866 QColor QtCharts::DeclarativeChart::plotAreaColor()
868 QColor QtCharts::DeclarativeChart::plotAreaColor()
867 {
869 {
868 return m_chart->plotAreaBackgroundBrush().color();
870 return m_chart->plotAreaBackgroundBrush().color();
869 }
871 }
870
872
871 void DeclarativeChart::setLocalizeNumbers(bool localize)
873 void DeclarativeChart::setLocalizeNumbers(bool localize)
872 {
874 {
873 if (m_chart->localizeNumbers() != localize) {
875 if (m_chart->localizeNumbers() != localize) {
874 m_chart->setLocalizeNumbers(localize);
876 m_chart->setLocalizeNumbers(localize);
875 emit localizeNumbersChanged();
877 emit localizeNumbersChanged();
876 }
878 }
877 }
879 }
878
880
879 bool DeclarativeChart::localizeNumbers() const
881 bool DeclarativeChart::localizeNumbers() const
880 {
882 {
881 return m_chart->localizeNumbers();
883 return m_chart->localizeNumbers();
882 }
884 }
883
885
884 void QtCharts::DeclarativeChart::setLocale(const QLocale &locale)
886 void QtCharts::DeclarativeChart::setLocale(const QLocale &locale)
885 {
887 {
886 if (m_chart->locale() != locale) {
888 if (m_chart->locale() != locale) {
887 m_chart->setLocale(locale);
889 m_chart->setLocale(locale);
888 emit localeChanged();
890 emit localeChanged();
889 }
891 }
890 }
892 }
891
893
892 QLocale QtCharts::DeclarativeChart::locale() const
894 QLocale QtCharts::DeclarativeChart::locale() const
893 {
895 {
894 return m_chart->locale();
896 return m_chart->locale();
895 }
897 }
896
898
897 int DeclarativeChart::count()
899 int DeclarativeChart::count()
898 {
900 {
899 return m_chart->series().count();
901 return m_chart->series().count();
900 }
902 }
901
903
902 void DeclarativeChart::setDropShadowEnabled(bool enabled)
904 void DeclarativeChart::setDropShadowEnabled(bool enabled)
903 {
905 {
904 if (enabled != m_chart->isDropShadowEnabled()) {
906 if (enabled != m_chart->isDropShadowEnabled()) {
905 m_sceneImageNeedsClear = true;
907 m_sceneImageNeedsClear = true;
906 m_chart->setDropShadowEnabled(enabled);
908 m_chart->setDropShadowEnabled(enabled);
907 dropShadowEnabledChanged(enabled);
909 dropShadowEnabledChanged(enabled);
908 }
910 }
909 }
911 }
910
912
911 bool DeclarativeChart::dropShadowEnabled()
913 bool DeclarativeChart::dropShadowEnabled()
912 {
914 {
913 return m_chart->isDropShadowEnabled();
915 return m_chart->isDropShadowEnabled();
914 }
916 }
915
917
916 qreal DeclarativeChart::backgroundRoundness() const
918 qreal DeclarativeChart::backgroundRoundness() const
917 {
919 {
918 return m_chart->backgroundRoundness();
920 return m_chart->backgroundRoundness();
919 }
921 }
920
922
921 void DeclarativeChart::setBackgroundRoundness(qreal diameter)
923 void DeclarativeChart::setBackgroundRoundness(qreal diameter)
922 {
924 {
923 if (m_chart->backgroundRoundness() != diameter) {
925 if (m_chart->backgroundRoundness() != diameter) {
924 m_sceneImageNeedsClear = true;
926 m_sceneImageNeedsClear = true;
925 m_chart->setBackgroundRoundness(diameter);
927 m_chart->setBackgroundRoundness(diameter);
926 emit backgroundRoundnessChanged(diameter);
928 emit backgroundRoundnessChanged(diameter);
927 }
929 }
928 }
930 }
929
931
930 void DeclarativeChart::zoom(qreal factor)
932 void DeclarativeChart::zoom(qreal factor)
931 {
933 {
932 m_chart->zoom(factor);
934 m_chart->zoom(factor);
933 }
935 }
934
936
935 void DeclarativeChart::zoomIn()
937 void DeclarativeChart::zoomIn()
936 {
938 {
937 m_chart->zoomIn();
939 m_chart->zoomIn();
938 }
940 }
939
941
940 void DeclarativeChart::zoomIn(const QRectF &rectangle)
942 void DeclarativeChart::zoomIn(const QRectF &rectangle)
941 {
943 {
942 m_chart->zoomIn(rectangle);
944 m_chart->zoomIn(rectangle);
943 }
945 }
944
946
945 void DeclarativeChart::zoomOut()
947 void DeclarativeChart::zoomOut()
946 {
948 {
947 m_chart->zoomOut();
949 m_chart->zoomOut();
948 }
950 }
949
951
950 void DeclarativeChart::zoomReset()
952 void DeclarativeChart::zoomReset()
951 {
953 {
952 m_chart->zoomReset();
954 m_chart->zoomReset();
953 }
955 }
954
956
955 bool DeclarativeChart::isZoomed()
957 bool DeclarativeChart::isZoomed()
956 {
958 {
957 return m_chart->isZoomed();
959 return m_chart->isZoomed();
958 }
960 }
959
961
960 void DeclarativeChart::scrollLeft(qreal pixels)
962 void DeclarativeChart::scrollLeft(qreal pixels)
961 {
963 {
962 m_chart->scroll(-pixels, 0);
964 m_chart->scroll(-pixels, 0);
963 }
965 }
964
966
965 void DeclarativeChart::scrollRight(qreal pixels)
967 void DeclarativeChart::scrollRight(qreal pixels)
966 {
968 {
967 m_chart->scroll(pixels, 0);
969 m_chart->scroll(pixels, 0);
968 }
970 }
969
971
970 void DeclarativeChart::scrollUp(qreal pixels)
972 void DeclarativeChart::scrollUp(qreal pixels)
971 {
973 {
972 m_chart->scroll(0, pixels);
974 m_chart->scroll(0, pixels);
973 }
975 }
974
976
975 void DeclarativeChart::scrollDown(qreal pixels)
977 void DeclarativeChart::scrollDown(qreal pixels)
976 {
978 {
977 m_chart->scroll(0, -pixels);
979 m_chart->scroll(0, -pixels);
978 }
980 }
979
981
980 QQmlListProperty<QAbstractAxis> DeclarativeChart::axes()
982 QQmlListProperty<QAbstractAxis> DeclarativeChart::axes()
981 {
983 {
982 return QQmlListProperty<QAbstractAxis>(this, 0,
984 return QQmlListProperty<QAbstractAxis>(this, 0,
983 &DeclarativeChart::axesAppendFunc,
985 &DeclarativeChart::axesAppendFunc,
984 &DeclarativeChart::axesCountFunc,
986 &DeclarativeChart::axesCountFunc,
985 &DeclarativeChart::axesAtFunc,
987 &DeclarativeChart::axesAtFunc,
986 &DeclarativeChart::axesClearFunc);
988 &DeclarativeChart::axesClearFunc);
987 }
989 }
988
990
989 void DeclarativeChart::axesAppendFunc(QQmlListProperty<QAbstractAxis> *list, QAbstractAxis *element)
991 void DeclarativeChart::axesAppendFunc(QQmlListProperty<QAbstractAxis> *list, QAbstractAxis *element)
990 {
992 {
991 // Empty implementation
993 // Empty implementation
992 Q_UNUSED(list);
994 Q_UNUSED(list);
993 Q_UNUSED(element);
995 Q_UNUSED(element);
994 }
996 }
995
997
996 int DeclarativeChart::axesCountFunc(QQmlListProperty<QAbstractAxis> *list)
998 int DeclarativeChart::axesCountFunc(QQmlListProperty<QAbstractAxis> *list)
997 {
999 {
998 if (qobject_cast<DeclarativeChart *>(list->object)) {
1000 if (qobject_cast<DeclarativeChart *>(list->object)) {
999 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
1001 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
1000 return chart->m_chart->axes(Qt::Horizontal | Qt::Vertical).count();
1002 return chart->m_chart->axes(Qt::Horizontal | Qt::Vertical).count();
1001 }
1003 }
1002 return 0;
1004 return 0;
1003 }
1005 }
1004
1006
1005 QAbstractAxis *DeclarativeChart::axesAtFunc(QQmlListProperty<QAbstractAxis> *list, int index)
1007 QAbstractAxis *DeclarativeChart::axesAtFunc(QQmlListProperty<QAbstractAxis> *list, int index)
1006 {
1008 {
1007 if (qobject_cast<DeclarativeChart *>(list->object)) {
1009 if (qobject_cast<DeclarativeChart *>(list->object)) {
1008 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
1010 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
1009 QList<QAbstractAxis *> axes = chart->m_chart->axes(Qt::Horizontal | Qt::Vertical, chart->m_chart->series()[0]);
1011 QList<QAbstractAxis *> axes = chart->m_chart->axes(Qt::Horizontal | Qt::Vertical, chart->m_chart->series()[0]);
1010 return axes.at(index);
1012 return axes.at(index);
1011 }
1013 }
1012 return 0;
1014 return 0;
1013 }
1015 }
1014
1016
1015 void DeclarativeChart::axesClearFunc(QQmlListProperty<QAbstractAxis> *list)
1017 void DeclarativeChart::axesClearFunc(QQmlListProperty<QAbstractAxis> *list)
1016 {
1018 {
1017 // Empty implementation
1019 // Empty implementation
1018 Q_UNUSED(list);
1020 Q_UNUSED(list);
1019 }
1021 }
1020
1022
1021
1023
1022 QAbstractSeries *DeclarativeChart::series(int index)
1024 QAbstractSeries *DeclarativeChart::series(int index)
1023 {
1025 {
1024 if (index < m_chart->series().count()) {
1026 if (index < m_chart->series().count()) {
1025 return m_chart->series().at(index);
1027 return m_chart->series().at(index);
1026 }
1028 }
1027 return 0;
1029 return 0;
1028 }
1030 }
1029
1031
1030 QAbstractSeries *DeclarativeChart::series(QString seriesName)
1032 QAbstractSeries *DeclarativeChart::series(QString seriesName)
1031 {
1033 {
1032 foreach (QAbstractSeries *series, m_chart->series()) {
1034 foreach (QAbstractSeries *series, m_chart->series()) {
1033 if (series->name() == seriesName)
1035 if (series->name() == seriesName)
1034 return series;
1036 return series;
1035 }
1037 }
1036 return 0;
1038 return 0;
1037 }
1039 }
1038
1040
1039 QAbstractSeries *DeclarativeChart::createSeries(int type, QString name, QAbstractAxis *axisX, QAbstractAxis *axisY)
1041 QAbstractSeries *DeclarativeChart::createSeries(int type, QString name, QAbstractAxis *axisX, QAbstractAxis *axisY)
1040 {
1042 {
1041 QAbstractSeries *series = 0;
1043 QAbstractSeries *series = 0;
1042
1044
1043 switch (type) {
1045 switch (type) {
1044 case DeclarativeChart::SeriesTypeLine:
1046 case DeclarativeChart::SeriesTypeLine:
1045 series = new DeclarativeLineSeries();
1047 series = new DeclarativeLineSeries();
1046 break;
1048 break;
1047 case DeclarativeChart::SeriesTypeArea: {
1049 case DeclarativeChart::SeriesTypeArea: {
1048 DeclarativeAreaSeries *area = new DeclarativeAreaSeries();
1050 DeclarativeAreaSeries *area = new DeclarativeAreaSeries();
1049 DeclarativeLineSeries *line = new DeclarativeLineSeries();
1051 DeclarativeLineSeries *line = new DeclarativeLineSeries();
1050 line->setParent(area);
1052 line->setParent(area);
1051 area->setUpperSeries(line);
1053 area->setUpperSeries(line);
1052 series = area;
1054 series = area;
1053 break;
1055 break;
1054 }
1056 }
1055 case DeclarativeChart::SeriesTypeStackedBar:
1057 case DeclarativeChart::SeriesTypeStackedBar:
1056 series = new DeclarativeStackedBarSeries();
1058 series = new DeclarativeStackedBarSeries();
1057 break;
1059 break;
1058 case DeclarativeChart::SeriesTypePercentBar:
1060 case DeclarativeChart::SeriesTypePercentBar:
1059 series = new DeclarativePercentBarSeries();
1061 series = new DeclarativePercentBarSeries();
1060 break;
1062 break;
1061 case DeclarativeChart::SeriesTypeBar:
1063 case DeclarativeChart::SeriesTypeBar:
1062 series = new DeclarativeBarSeries();
1064 series = new DeclarativeBarSeries();
1063 break;
1065 break;
1064 case DeclarativeChart::SeriesTypeHorizontalBar:
1066 case DeclarativeChart::SeriesTypeHorizontalBar:
1065 series = new DeclarativeHorizontalBarSeries();
1067 series = new DeclarativeHorizontalBarSeries();
1066 break;
1068 break;
1067 case DeclarativeChart::SeriesTypeHorizontalPercentBar:
1069 case DeclarativeChart::SeriesTypeHorizontalPercentBar:
1068 series = new DeclarativeHorizontalPercentBarSeries();
1070 series = new DeclarativeHorizontalPercentBarSeries();
1069 break;
1071 break;
1070 case DeclarativeChart::SeriesTypeHorizontalStackedBar:
1072 case DeclarativeChart::SeriesTypeHorizontalStackedBar:
1071 series = new DeclarativeHorizontalStackedBarSeries();
1073 series = new DeclarativeHorizontalStackedBarSeries();
1072 break;
1074 break;
1073 case DeclarativeChart::SeriesTypeBoxPlot:
1075 case DeclarativeChart::SeriesTypeBoxPlot:
1074 series = new DeclarativeBoxPlotSeries();
1076 series = new DeclarativeBoxPlotSeries();
1075 break;
1077 break;
1076 case DeclarativeChart::SeriesTypePie:
1078 case DeclarativeChart::SeriesTypePie:
1077 series = new DeclarativePieSeries();
1079 series = new DeclarativePieSeries();
1078 break;
1080 break;
1079 case DeclarativeChart::SeriesTypeScatter:
1081 case DeclarativeChart::SeriesTypeScatter:
1080 series = new DeclarativeScatterSeries();
1082 series = new DeclarativeScatterSeries();
1081 break;
1083 break;
1082 case DeclarativeChart::SeriesTypeSpline:
1084 case DeclarativeChart::SeriesTypeSpline:
1083 series = new DeclarativeSplineSeries();
1085 series = new DeclarativeSplineSeries();
1084 break;
1086 break;
1085 default:
1087 default:
1086 qWarning() << "Illegal series type";
1088 qWarning() << "Illegal series type";
1087 }
1089 }
1088
1090
1089 if (series) {
1091 if (series) {
1090 // Connect to axis changed signals (unless this is a pie series)
1092 // Connect to axis changed signals (unless this is a pie series)
1091 if (!qobject_cast<DeclarativePieSeries *>(series)) {
1093 if (!qobject_cast<DeclarativePieSeries *>(series)) {
1092 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1094 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1093 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1095 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1094 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
1096 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
1095 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
1097 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
1096 }
1098 }
1097
1099
1098 series->setName(name);
1100 series->setName(name);
1099 m_chart->addSeries(series);
1101 m_chart->addSeries(series);
1100
1102
1101 if (!axisX || !axisY)
1103 if (!axisX || !axisY)
1102 initializeAxes(series);
1104 initializeAxes(series);
1103
1105
1104 if (axisX)
1106 if (axisX)
1105 setAxisX(axisX, series);
1107 setAxisX(axisX, series);
1106 if (axisY)
1108 if (axisY)
1107 setAxisY(axisY, series);
1109 setAxisY(axisY, series);
1108 }
1110 }
1109
1111
1110 return series;
1112 return series;
1111 }
1113 }
1112
1114
1113 void DeclarativeChart::removeSeries(QAbstractSeries *series)
1115 void DeclarativeChart::removeSeries(QAbstractSeries *series)
1114 {
1116 {
1115 if (series)
1117 if (series)
1116 m_chart->removeSeries(series);
1118 m_chart->removeSeries(series);
1117 else
1119 else
1118 qWarning("removeSeries: cannot remove null");
1120 qWarning("removeSeries: cannot remove null");
1119 }
1121 }
1120
1122
1121 void DeclarativeChart::setAxisX(QAbstractAxis *axis, QAbstractSeries *series)
1123 void DeclarativeChart::setAxisX(QAbstractAxis *axis, QAbstractSeries *series)
1122 {
1124 {
1123 if (axis && series)
1125 if (axis && series)
1124 seriesAxisAttachHelper(series, axis, Qt::Horizontal, Qt::AlignBottom);
1126 seriesAxisAttachHelper(series, axis, Qt::Horizontal, Qt::AlignBottom);
1125 }
1127 }
1126
1128
1127 void DeclarativeChart::setAxisY(QAbstractAxis *axis, QAbstractSeries *series)
1129 void DeclarativeChart::setAxisY(QAbstractAxis *axis, QAbstractSeries *series)
1128 {
1130 {
1129 if (axis && series)
1131 if (axis && series)
1130 seriesAxisAttachHelper(series, axis, Qt::Vertical, Qt::AlignLeft);
1132 seriesAxisAttachHelper(series, axis, Qt::Vertical, Qt::AlignLeft);
1131 }
1133 }
1132
1134
1133 QAbstractAxis *DeclarativeChart::defaultAxis(Qt::Orientation orientation, QAbstractSeries *series)
1135 QAbstractAxis *DeclarativeChart::defaultAxis(Qt::Orientation orientation, QAbstractSeries *series)
1134 {
1136 {
1135 if (!series) {
1137 if (!series) {
1136 qWarning() << "No axis type defined for null series";
1138 qWarning() << "No axis type defined for null series";
1137 return 0;
1139 return 0;
1138 }
1140 }
1139
1141
1140 foreach (QAbstractAxis *existingAxis, m_chart->axes(orientation)) {
1142 foreach (QAbstractAxis *existingAxis, m_chart->axes(orientation)) {
1141 if (existingAxis->type() == series->d_ptr->defaultAxisType(orientation))
1143 if (existingAxis->type() == series->d_ptr->defaultAxisType(orientation))
1142 return existingAxis;
1144 return existingAxis;
1143 }
1145 }
1144
1146
1145 switch (series->d_ptr->defaultAxisType(orientation)) {
1147 switch (series->d_ptr->defaultAxisType(orientation)) {
1146 case QAbstractAxis::AxisTypeValue:
1148 case QAbstractAxis::AxisTypeValue:
1147 return new QValueAxis(this);
1149 return new QValueAxis(this);
1148 case QAbstractAxis::AxisTypeBarCategory:
1150 case QAbstractAxis::AxisTypeBarCategory:
1149 return new QBarCategoryAxis(this);
1151 return new QBarCategoryAxis(this);
1150 case QAbstractAxis::AxisTypeCategory:
1152 case QAbstractAxis::AxisTypeCategory:
1151 return new QCategoryAxis(this);
1153 return new QCategoryAxis(this);
1152 #ifndef QT_QREAL_IS_FLOAT
1154 #ifndef QT_QREAL_IS_FLOAT
1153 case QAbstractAxis::AxisTypeDateTime:
1155 case QAbstractAxis::AxisTypeDateTime:
1154 return new QDateTimeAxis(this);
1156 return new QDateTimeAxis(this);
1155 #endif
1157 #endif
1156 case QAbstractAxis::AxisTypeLogValue:
1158 case QAbstractAxis::AxisTypeLogValue:
1157 return new QLogValueAxis(this);
1159 return new QLogValueAxis(this);
1158 default:
1160 default:
1159 // assume AxisTypeNoAxis
1161 // assume AxisTypeNoAxis
1160 return 0;
1162 return 0;
1161 }
1163 }
1162 }
1164 }
1163
1165
1164 void DeclarativeChart::initializeAxes(QAbstractSeries *series)
1166 void DeclarativeChart::initializeAxes(QAbstractSeries *series)
1165 {
1167 {
1166 if (qobject_cast<DeclarativeLineSeries *>(series))
1168 if (qobject_cast<DeclarativeLineSeries *>(series))
1167 doInitializeAxes(series, qobject_cast<DeclarativeLineSeries *>(series)->m_axes);
1169 doInitializeAxes(series, qobject_cast<DeclarativeLineSeries *>(series)->m_axes);
1168 else if (qobject_cast<DeclarativeScatterSeries *>(series))
1170 else if (qobject_cast<DeclarativeScatterSeries *>(series))
1169 doInitializeAxes(series, qobject_cast<DeclarativeScatterSeries *>(series)->m_axes);
1171 doInitializeAxes(series, qobject_cast<DeclarativeScatterSeries *>(series)->m_axes);
1170 else if (qobject_cast<DeclarativeSplineSeries *>(series))
1172 else if (qobject_cast<DeclarativeSplineSeries *>(series))
1171 doInitializeAxes(series, qobject_cast<DeclarativeSplineSeries *>(series)->m_axes);
1173 doInitializeAxes(series, qobject_cast<DeclarativeSplineSeries *>(series)->m_axes);
1172 else if (qobject_cast<DeclarativeAreaSeries *>(series))
1174 else if (qobject_cast<DeclarativeAreaSeries *>(series))
1173 doInitializeAxes(series, qobject_cast<DeclarativeAreaSeries *>(series)->m_axes);
1175 doInitializeAxes(series, qobject_cast<DeclarativeAreaSeries *>(series)->m_axes);
1174 else if (qobject_cast<DeclarativeBarSeries *>(series))
1176 else if (qobject_cast<DeclarativeBarSeries *>(series))
1175 doInitializeAxes(series, qobject_cast<DeclarativeBarSeries *>(series)->m_axes);
1177 doInitializeAxes(series, qobject_cast<DeclarativeBarSeries *>(series)->m_axes);
1176 else if (qobject_cast<DeclarativeStackedBarSeries *>(series))
1178 else if (qobject_cast<DeclarativeStackedBarSeries *>(series))
1177 doInitializeAxes(series, qobject_cast<DeclarativeStackedBarSeries *>(series)->m_axes);
1179 doInitializeAxes(series, qobject_cast<DeclarativeStackedBarSeries *>(series)->m_axes);
1178 else if (qobject_cast<DeclarativePercentBarSeries *>(series))
1180 else if (qobject_cast<DeclarativePercentBarSeries *>(series))
1179 doInitializeAxes(series, qobject_cast<DeclarativePercentBarSeries *>(series)->m_axes);
1181 doInitializeAxes(series, qobject_cast<DeclarativePercentBarSeries *>(series)->m_axes);
1180 else if (qobject_cast<DeclarativeHorizontalBarSeries *>(series))
1182 else if (qobject_cast<DeclarativeHorizontalBarSeries *>(series))
1181 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalBarSeries *>(series)->m_axes);
1183 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalBarSeries *>(series)->m_axes);
1182 else if (qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series))
1184 else if (qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series))
1183 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series)->m_axes);
1185 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series)->m_axes);
1184 else if (qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series))
1186 else if (qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series))
1185 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series)->m_axes);
1187 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series)->m_axes);
1186 else if (qobject_cast<DeclarativeBoxPlotSeries *>(series))
1188 else if (qobject_cast<DeclarativeBoxPlotSeries *>(series))
1187 doInitializeAxes(series, qobject_cast<DeclarativeBoxPlotSeries *>(series)->m_axes);
1189 doInitializeAxes(series, qobject_cast<DeclarativeBoxPlotSeries *>(series)->m_axes);
1188 // else: do nothing
1190 // else: do nothing
1189 }
1191 }
1190
1192
1191 void DeclarativeChart::doInitializeAxes(QAbstractSeries *series, DeclarativeAxes *axes)
1193 void DeclarativeChart::doInitializeAxes(QAbstractSeries *series, DeclarativeAxes *axes)
1192 {
1194 {
1193 qreal min;
1195 qreal min;
1194 qreal max;
1196 qreal max;
1195 // Initialize axis X
1197 // Initialize axis X
1196 if (axes->axisX()) {
1198 if (axes->axisX()) {
1197 axes->emitAxisXChanged();
1199 axes->emitAxisXChanged();
1198 } else if (axes->axisXTop()) {
1200 } else if (axes->axisXTop()) {
1199 axes->emitAxisXTopChanged();
1201 axes->emitAxisXTopChanged();
1200 } else {
1202 } else {
1201 axes->setAxisX(defaultAxis(Qt::Horizontal, series));
1203 axes->setAxisX(defaultAxis(Qt::Horizontal, series));
1202 findMinMaxForSeries(series, Qt::Horizontal, min, max);
1204 findMinMaxForSeries(series, Qt::Horizontal, min, max);
1203 axes->axisX()->setRange(min, max);
1205 axes->axisX()->setRange(min, max);
1204 }
1206 }
1205
1207
1206 // Initialize axis Y
1208 // Initialize axis Y
1207 if (axes->axisY()) {
1209 if (axes->axisY()) {
1208 axes->emitAxisYChanged();
1210 axes->emitAxisYChanged();
1209 } else if (axes->axisYRight()) {
1211 } else if (axes->axisYRight()) {
1210 axes->emitAxisYRightChanged();
1212 axes->emitAxisYRightChanged();
1211 } else {
1213 } else {
1212 axes->setAxisY(defaultAxis(Qt::Vertical, series));
1214 axes->setAxisY(defaultAxis(Qt::Vertical, series));
1213 findMinMaxForSeries(series, Qt::Vertical, min, max);
1215 findMinMaxForSeries(series, Qt::Vertical, min, max);
1214 axes->axisY()->setRange(min, max);
1216 axes->axisY()->setRange(min, max);
1215 }
1217 }
1216 }
1218 }
1217
1219
1218 void DeclarativeChart::findMinMaxForSeries(QAbstractSeries *series, Qt::Orientations orientation,
1220 void DeclarativeChart::findMinMaxForSeries(QAbstractSeries *series, Qt::Orientations orientation,
1219 qreal &min, qreal &max)
1221 qreal &min, qreal &max)
1220 {
1222 {
1221 if (!series) {
1223 if (!series) {
1222 min = 0.5;
1224 min = 0.5;
1223 max = 0.5;
1225 max = 0.5;
1224 } else {
1226 } else {
1225 AbstractDomain *domain = series->d_ptr->domain();
1227 AbstractDomain *domain = series->d_ptr->domain();
1226 min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
1228 min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
1227 max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
1229 max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
1228
1230
1229 if (min == max) {
1231 if (min == max) {
1230 min -= 0.5;
1232 min -= 0.5;
1231 max += 0.5;
1233 max += 0.5;
1232 }
1234 }
1233 }
1235 }
1234 }
1236 }
1235
1237
1236 QPointF DeclarativeChart::mapToValue(const QPointF &position, QAbstractSeries *series)
1238 QPointF DeclarativeChart::mapToValue(const QPointF &position, QAbstractSeries *series)
1237 {
1239 {
1238 return m_chart->mapToValue(position, series);
1240 return m_chart->mapToValue(position, series);
1239 }
1241 }
1240
1242
1241 QPointF DeclarativeChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
1243 QPointF DeclarativeChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
1242 {
1244 {
1243 return m_chart->mapToPosition(value, series);
1245 return m_chart->mapToPosition(value, series);
1244 }
1246 }
1245
1247
1246 #include "moc_declarativechart.cpp"
1248 #include "moc_declarativechart.cpp"
1247
1249
1248 QT_CHARTS_END_NAMESPACE
1250 QT_CHARTS_END_NAMESPACE
@@ -1,18 +1,18
1 %modules = ( # path to module name map
1 %modules = ( # path to module name map
2 "QtCharts" => "$basedir/src/charts",
2 "QtCharts" => "$basedir/src/charts",
3 );
3 );
4 %moduleheaders = ( # restrict the module headers to those found in relative path
4 %moduleheaders = ( # restrict the module headers to those found in relative path
5 );
5 );
6 %classnames = (
6 %classnames = (
7 "qchartglobal.h" => "QChartGlobal"
7 "qchartglobal.h" => "QChartGlobal"
8 );
8 );
9 # Module dependencies.
9 # Module dependencies.
10 # Every module that is required to build this module should have one entry.
10 # Every module that is required to build this module should have one entry.
11 # Each of the module version specifiers can take one of the following values:
11 # Each of the module version specifiers can take one of the following values:
12 # - A specific Git revision.
12 # - A specific Git revision.
13 # - any git symbolic ref resolvable from the module's repository (e.g. "refs/heads/master" to track master branch)
13 # - any git symbolic ref resolvable from the module's repository (e.g. "refs/heads/master" to track master branch)
14 #
14 #
15 %dependencies = (
15 %dependencies = (
16 "qtbase" => "refs/heads/dev",
16 "qtbase" => "",
17 "qtdeclarative" => "refs/heads/dev",
17 "qtdeclarative" => "",
18 );
18 );
General Comments 0
You need to be logged in to leave comments. Login now