##// END OF EJS Templates
Explicitly update GLWidget when we set new points...
Miikka Heikkinen -
r2865:672ea1cb191f
parent child
Show More
@@ -1,574 +1,577
1 /******************************************************************************
1 /******************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
4 ** Contact: http://www.qt.io/licensing/
5 **
5 **
6 ** This file is part of the Qt Charts module.
6 ** This file is part of the Qt Charts module.
7 **
7 **
8 ** $QT_BEGIN_LICENSE:COMM$
8 ** $QT_BEGIN_LICENSE:COMM$
9 **
9 **
10 ** Commercial License Usage
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** and conditions see http://www.qt.io/terms-conditions. For further
16 ** information use the contact form at http://www.qt.io/contact-us.
16 ** information use the contact form at http://www.qt.io/contact-us.
17 **
17 **
18 ** $QT_END_LICENSE$
18 ** $QT_END_LICENSE$
19 **
19 **
20 ******************************************************************************/
20 ******************************************************************************/
21 #include <private/chartpresenter_p.h>
21 #include <private/chartpresenter_p.h>
22 #include <QtCharts/QChart>
22 #include <QtCharts/QChart>
23 #include <private/chartitem_p.h>
23 #include <private/chartitem_p.h>
24 #include <private/qchart_p.h>
24 #include <private/qchart_p.h>
25 #include <QtCharts/QAbstractAxis>
25 #include <QtCharts/QAbstractAxis>
26 #include <private/qabstractaxis_p.h>
26 #include <private/qabstractaxis_p.h>
27 #include <private/chartdataset_p.h>
27 #include <private/chartdataset_p.h>
28 #include <private/chartanimation_p.h>
28 #include <private/chartanimation_p.h>
29 #include <private/qabstractseries_p.h>
29 #include <private/qabstractseries_p.h>
30 #include <QtCharts/QAreaSeries>
30 #include <QtCharts/QAreaSeries>
31 #include <private/chartaxiselement_p.h>
31 #include <private/chartaxiselement_p.h>
32 #include <private/chartbackground_p.h>
32 #include <private/chartbackground_p.h>
33 #include <private/cartesianchartlayout_p.h>
33 #include <private/cartesianchartlayout_p.h>
34 #include <private/polarchartlayout_p.h>
34 #include <private/polarchartlayout_p.h>
35 #include <private/charttitle_p.h>
35 #include <private/charttitle_p.h>
36 #include <QtCore/QTimer>
36 #include <QtCore/QTimer>
37 #include <QtGui/QTextDocument>
37 #include <QtGui/QTextDocument>
38 #include <QtWidgets/QGraphicsScene>
38 #include <QtWidgets/QGraphicsScene>
39 #include <QtWidgets/QGraphicsView>
39 #include <QtWidgets/QGraphicsView>
40
40
41 QT_CHARTS_BEGIN_NAMESPACE
41 QT_CHARTS_BEGIN_NAMESPACE
42
42
43 ChartPresenter::ChartPresenter(QChart *chart, QChart::ChartType type)
43 ChartPresenter::ChartPresenter(QChart *chart, QChart::ChartType type)
44 : QObject(chart),
44 : QObject(chart),
45 m_chart(chart),
45 m_chart(chart),
46 m_options(QChart::NoAnimation),
46 m_options(QChart::NoAnimation),
47 m_animationDuration(ChartAnimationDuration),
47 m_animationDuration(ChartAnimationDuration),
48 m_animationCurve(QEasingCurve::OutQuart),
48 m_animationCurve(QEasingCurve::OutQuart),
49 m_state(ShowState),
49 m_state(ShowState),
50 m_background(0),
50 m_background(0),
51 m_plotAreaBackground(0),
51 m_plotAreaBackground(0),
52 m_title(0),
52 m_title(0),
53 m_localizeNumbers(false)
53 m_localizeNumbers(false)
54 #ifndef QT_NO_OPENGL
54 #ifndef QT_NO_OPENGL
55 , m_glWidget(0)
55 , m_glWidget(0)
56 , m_glUseWidget(true)
56 , m_glUseWidget(true)
57 #endif
57 #endif
58 {
58 {
59 if (type == QChart::ChartTypeCartesian)
59 if (type == QChart::ChartTypeCartesian)
60 m_layout = new CartesianChartLayout(this);
60 m_layout = new CartesianChartLayout(this);
61 else if (type == QChart::ChartTypePolar)
61 else if (type == QChart::ChartTypePolar)
62 m_layout = new PolarChartLayout(this);
62 m_layout = new PolarChartLayout(this);
63 Q_ASSERT(m_layout);
63 Q_ASSERT(m_layout);
64 }
64 }
65
65
66 ChartPresenter::~ChartPresenter()
66 ChartPresenter::~ChartPresenter()
67 {
67 {
68 #ifndef QT_NO_OPENGL
68 #ifndef QT_NO_OPENGL
69 delete m_glWidget.data();
69 delete m_glWidget.data();
70 #endif
70 #endif
71 }
71 }
72
72
73 void ChartPresenter::setGeometry(const QRectF rect)
73 void ChartPresenter::setGeometry(const QRectF rect)
74 {
74 {
75 if (m_rect != rect) {
75 if (m_rect != rect) {
76 m_rect = rect;
76 m_rect = rect;
77 foreach (ChartItem *chart, m_chartItems) {
77 foreach (ChartItem *chart, m_chartItems) {
78 chart->domain()->setSize(rect.size());
78 chart->domain()->setSize(rect.size());
79 chart->setPos(rect.topLeft());
79 chart->setPos(rect.topLeft());
80 }
80 }
81 #ifndef QT_NO_OPENGL
81 #ifndef QT_NO_OPENGL
82 if (!m_glWidget.isNull())
82 if (!m_glWidget.isNull())
83 m_glWidget->setGeometry(m_rect.toRect());
83 m_glWidget->setGeometry(m_rect.toRect());
84 #endif
84 #endif
85 emit plotAreaChanged(m_rect);
85 emit plotAreaChanged(m_rect);
86 }
86 }
87 }
87 }
88
88
89 QRectF ChartPresenter::geometry() const
89 QRectF ChartPresenter::geometry() const
90 {
90 {
91 return m_rect;
91 return m_rect;
92 }
92 }
93
93
94 void ChartPresenter::handleAxisAdded(QAbstractAxis *axis)
94 void ChartPresenter::handleAxisAdded(QAbstractAxis *axis)
95 {
95 {
96 axis->d_ptr->initializeGraphics(rootItem());
96 axis->d_ptr->initializeGraphics(rootItem());
97 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
97 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
98 ChartAxisElement *item = axis->d_ptr->axisItem();
98 ChartAxisElement *item = axis->d_ptr->axisItem();
99 item->setPresenter(this);
99 item->setPresenter(this);
100 item->setThemeManager(m_chart->d_ptr->m_themeManager);
100 item->setThemeManager(m_chart->d_ptr->m_themeManager);
101 m_axisItems<<item;
101 m_axisItems<<item;
102 m_axes<<axis;
102 m_axes<<axis;
103 m_layout->invalidate();
103 m_layout->invalidate();
104 }
104 }
105
105
106 void ChartPresenter::handleAxisRemoved(QAbstractAxis *axis)
106 void ChartPresenter::handleAxisRemoved(QAbstractAxis *axis)
107 {
107 {
108 ChartAxisElement *item = axis->d_ptr->m_item.take();
108 ChartAxisElement *item = axis->d_ptr->m_item.take();
109 if (item->animation())
109 if (item->animation())
110 item->animation()->stopAndDestroyLater();
110 item->animation()->stopAndDestroyLater();
111 item->hide();
111 item->hide();
112 item->disconnect();
112 item->disconnect();
113 item->deleteLater();
113 item->deleteLater();
114 m_axisItems.removeAll(item);
114 m_axisItems.removeAll(item);
115 m_axes.removeAll(axis);
115 m_axes.removeAll(axis);
116 m_layout->invalidate();
116 m_layout->invalidate();
117 }
117 }
118
118
119
119
120 void ChartPresenter::handleSeriesAdded(QAbstractSeries *series)
120 void ChartPresenter::handleSeriesAdded(QAbstractSeries *series)
121 {
121 {
122 series->d_ptr->initializeGraphics(rootItem());
122 series->d_ptr->initializeGraphics(rootItem());
123 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
123 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
124 series->d_ptr->setPresenter(this);
124 series->d_ptr->setPresenter(this);
125 ChartItem *chart = series->d_ptr->chartItem();
125 ChartItem *chart = series->d_ptr->chartItem();
126 chart->setPresenter(this);
126 chart->setPresenter(this);
127 chart->setThemeManager(m_chart->d_ptr->m_themeManager);
127 chart->setThemeManager(m_chart->d_ptr->m_themeManager);
128 chart->setDataSet(m_chart->d_ptr->m_dataset);
128 chart->setDataSet(m_chart->d_ptr->m_dataset);
129 chart->domain()->setSize(m_rect.size());
129 chart->domain()->setSize(m_rect.size());
130 chart->setPos(m_rect.topLeft());
130 chart->setPos(m_rect.topLeft());
131 chart->handleDomainUpdated(); //this could be moved to intializeGraphics when animator is refactored
131 chart->handleDomainUpdated(); //this could be moved to intializeGraphics when animator is refactored
132 m_chartItems<<chart;
132 m_chartItems<<chart;
133 m_series<<series;
133 m_series<<series;
134 m_layout->invalidate();
134 m_layout->invalidate();
135 }
135 }
136
136
137 void ChartPresenter::handleSeriesRemoved(QAbstractSeries *series)
137 void ChartPresenter::handleSeriesRemoved(QAbstractSeries *series)
138 {
138 {
139 ChartItem *chart = series->d_ptr->m_item.take();
139 ChartItem *chart = series->d_ptr->m_item.take();
140 chart->hide();
140 chart->hide();
141 chart->disconnect();
141 chart->disconnect();
142 chart->deleteLater();
142 chart->deleteLater();
143 if (chart->animation())
143 if (chart->animation())
144 chart->animation()->stopAndDestroyLater();
144 chart->animation()->stopAndDestroyLater();
145 m_chartItems.removeAll(chart);
145 m_chartItems.removeAll(chart);
146 m_series.removeAll(series);
146 m_series.removeAll(series);
147 m_layout->invalidate();
147 m_layout->invalidate();
148 }
148 }
149
149
150 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
150 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
151 {
151 {
152 if (m_options != options) {
152 if (m_options != options) {
153 QChart::AnimationOptions oldOptions = m_options;
153 QChart::AnimationOptions oldOptions = m_options;
154 m_options = options;
154 m_options = options;
155 if (options.testFlag(QChart::SeriesAnimations) != oldOptions.testFlag(QChart::SeriesAnimations)) {
155 if (options.testFlag(QChart::SeriesAnimations) != oldOptions.testFlag(QChart::SeriesAnimations)) {
156 foreach (QAbstractSeries *series, m_series)
156 foreach (QAbstractSeries *series, m_series)
157 series->d_ptr->initializeAnimations(m_options, m_animationDuration,
157 series->d_ptr->initializeAnimations(m_options, m_animationDuration,
158 m_animationCurve);
158 m_animationCurve);
159 }
159 }
160 if (options.testFlag(QChart::GridAxisAnimations) != oldOptions.testFlag(QChart::GridAxisAnimations)) {
160 if (options.testFlag(QChart::GridAxisAnimations) != oldOptions.testFlag(QChart::GridAxisAnimations)) {
161 foreach (QAbstractAxis *axis, m_axes)
161 foreach (QAbstractAxis *axis, m_axes)
162 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
162 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
163 }
163 }
164 m_layout->invalidate(); // So that existing animations don't just stop halfway
164 m_layout->invalidate(); // So that existing animations don't just stop halfway
165 }
165 }
166 }
166 }
167
167
168 void ChartPresenter::setAnimationDuration(int msecs)
168 void ChartPresenter::setAnimationDuration(int msecs)
169 {
169 {
170 if (m_animationDuration != msecs) {
170 if (m_animationDuration != msecs) {
171 m_animationDuration = msecs;
171 m_animationDuration = msecs;
172 foreach (QAbstractSeries *series, m_series)
172 foreach (QAbstractSeries *series, m_series)
173 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
173 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
174 foreach (QAbstractAxis *axis, m_axes)
174 foreach (QAbstractAxis *axis, m_axes)
175 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
175 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
176 m_layout->invalidate(); // So that existing animations don't just stop halfway
176 m_layout->invalidate(); // So that existing animations don't just stop halfway
177 }
177 }
178 }
178 }
179
179
180 void ChartPresenter::setAnimationEasingCurve(const QEasingCurve &curve)
180 void ChartPresenter::setAnimationEasingCurve(const QEasingCurve &curve)
181 {
181 {
182 if (m_animationCurve != curve) {
182 if (m_animationCurve != curve) {
183 m_animationCurve = curve;
183 m_animationCurve = curve;
184 foreach (QAbstractSeries *series, m_series)
184 foreach (QAbstractSeries *series, m_series)
185 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
185 series->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
186 foreach (QAbstractAxis *axis, m_axes)
186 foreach (QAbstractAxis *axis, m_axes)
187 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
187 axis->d_ptr->initializeAnimations(m_options, m_animationDuration, m_animationCurve);
188 m_layout->invalidate(); // So that existing animations don't just stop halfway
188 m_layout->invalidate(); // So that existing animations don't just stop halfway
189 }
189 }
190 }
190 }
191
191
192 void ChartPresenter::setState(State state,QPointF point)
192 void ChartPresenter::setState(State state,QPointF point)
193 {
193 {
194 m_state=state;
194 m_state=state;
195 m_statePoint=point;
195 m_statePoint=point;
196 }
196 }
197
197
198 QChart::AnimationOptions ChartPresenter::animationOptions() const
198 QChart::AnimationOptions ChartPresenter::animationOptions() const
199 {
199 {
200 return m_options;
200 return m_options;
201 }
201 }
202
202
203 void ChartPresenter::createBackgroundItem()
203 void ChartPresenter::createBackgroundItem()
204 {
204 {
205 if (!m_background) {
205 if (!m_background) {
206 m_background = new ChartBackground(rootItem());
206 m_background = new ChartBackground(rootItem());
207 m_background->setPen(Qt::NoPen); // Theme doesn't touch pen so don't use default
207 m_background->setPen(Qt::NoPen); // Theme doesn't touch pen so don't use default
208 m_background->setBrush(QChartPrivate::defaultBrush());
208 m_background->setBrush(QChartPrivate::defaultBrush());
209 m_background->setZValue(ChartPresenter::BackgroundZValue);
209 m_background->setZValue(ChartPresenter::BackgroundZValue);
210 }
210 }
211 }
211 }
212
212
213 void ChartPresenter::createPlotAreaBackgroundItem()
213 void ChartPresenter::createPlotAreaBackgroundItem()
214 {
214 {
215 if (!m_plotAreaBackground) {
215 if (!m_plotAreaBackground) {
216 if (m_chart->chartType() == QChart::ChartTypeCartesian)
216 if (m_chart->chartType() == QChart::ChartTypeCartesian)
217 m_plotAreaBackground = new QGraphicsRectItem(rootItem());
217 m_plotAreaBackground = new QGraphicsRectItem(rootItem());
218 else
218 else
219 m_plotAreaBackground = new QGraphicsEllipseItem(rootItem());
219 m_plotAreaBackground = new QGraphicsEllipseItem(rootItem());
220 // Use transparent pen instead of Qt::NoPen, as Qt::NoPen causes
220 // Use transparent pen instead of Qt::NoPen, as Qt::NoPen causes
221 // antialising artifacts with axis lines for some reason.
221 // antialising artifacts with axis lines for some reason.
222 m_plotAreaBackground->setPen(QPen(Qt::transparent));
222 m_plotAreaBackground->setPen(QPen(Qt::transparent));
223 m_plotAreaBackground->setBrush(Qt::NoBrush);
223 m_plotAreaBackground->setBrush(Qt::NoBrush);
224 m_plotAreaBackground->setZValue(ChartPresenter::PlotAreaZValue);
224 m_plotAreaBackground->setZValue(ChartPresenter::PlotAreaZValue);
225 m_plotAreaBackground->setVisible(false);
225 m_plotAreaBackground->setVisible(false);
226 }
226 }
227 }
227 }
228
228
229 void ChartPresenter::createTitleItem()
229 void ChartPresenter::createTitleItem()
230 {
230 {
231 if (!m_title) {
231 if (!m_title) {
232 m_title = new ChartTitle(rootItem());
232 m_title = new ChartTitle(rootItem());
233 m_title->setZValue(ChartPresenter::BackgroundZValue);
233 m_title->setZValue(ChartPresenter::BackgroundZValue);
234 }
234 }
235 }
235 }
236
236
237 void ChartPresenter::startAnimation(ChartAnimation *animation)
237 void ChartPresenter::startAnimation(ChartAnimation *animation)
238 {
238 {
239 animation->stop();
239 animation->stop();
240 QTimer::singleShot(0, animation, SLOT(startChartAnimation()));
240 QTimer::singleShot(0, animation, SLOT(startChartAnimation()));
241 }
241 }
242
242
243 void ChartPresenter::setBackgroundBrush(const QBrush &brush)
243 void ChartPresenter::setBackgroundBrush(const QBrush &brush)
244 {
244 {
245 createBackgroundItem();
245 createBackgroundItem();
246 m_background->setBrush(brush);
246 m_background->setBrush(brush);
247 m_layout->invalidate();
247 m_layout->invalidate();
248 }
248 }
249
249
250 QBrush ChartPresenter::backgroundBrush() const
250 QBrush ChartPresenter::backgroundBrush() const
251 {
251 {
252 if (!m_background)
252 if (!m_background)
253 return QBrush();
253 return QBrush();
254 return m_background->brush();
254 return m_background->brush();
255 }
255 }
256
256
257 void ChartPresenter::setBackgroundPen(const QPen &pen)
257 void ChartPresenter::setBackgroundPen(const QPen &pen)
258 {
258 {
259 createBackgroundItem();
259 createBackgroundItem();
260 m_background->setPen(pen);
260 m_background->setPen(pen);
261 m_layout->invalidate();
261 m_layout->invalidate();
262 }
262 }
263
263
264 QPen ChartPresenter::backgroundPen() const
264 QPen ChartPresenter::backgroundPen() const
265 {
265 {
266 if (!m_background)
266 if (!m_background)
267 return QPen();
267 return QPen();
268 return m_background->pen();
268 return m_background->pen();
269 }
269 }
270
270
271 void ChartPresenter::setBackgroundRoundness(qreal diameter)
271 void ChartPresenter::setBackgroundRoundness(qreal diameter)
272 {
272 {
273 createBackgroundItem();
273 createBackgroundItem();
274 m_background->setDiameter(diameter);
274 m_background->setDiameter(diameter);
275 m_layout->invalidate();
275 m_layout->invalidate();
276 }
276 }
277
277
278 qreal ChartPresenter::backgroundRoundness() const
278 qreal ChartPresenter::backgroundRoundness() const
279 {
279 {
280 if (!m_background)
280 if (!m_background)
281 return 0;
281 return 0;
282 return m_background->diameter();
282 return m_background->diameter();
283 }
283 }
284
284
285 void ChartPresenter::setPlotAreaBackgroundBrush(const QBrush &brush)
285 void ChartPresenter::setPlotAreaBackgroundBrush(const QBrush &brush)
286 {
286 {
287 createPlotAreaBackgroundItem();
287 createPlotAreaBackgroundItem();
288 m_plotAreaBackground->setBrush(brush);
288 m_plotAreaBackground->setBrush(brush);
289 m_layout->invalidate();
289 m_layout->invalidate();
290 }
290 }
291
291
292 QBrush ChartPresenter::plotAreaBackgroundBrush() const
292 QBrush ChartPresenter::plotAreaBackgroundBrush() const
293 {
293 {
294 if (!m_plotAreaBackground)
294 if (!m_plotAreaBackground)
295 return QBrush();
295 return QBrush();
296 return m_plotAreaBackground->brush();
296 return m_plotAreaBackground->brush();
297 }
297 }
298
298
299 void ChartPresenter::setPlotAreaBackgroundPen(const QPen &pen)
299 void ChartPresenter::setPlotAreaBackgroundPen(const QPen &pen)
300 {
300 {
301 createPlotAreaBackgroundItem();
301 createPlotAreaBackgroundItem();
302 m_plotAreaBackground->setPen(pen);
302 m_plotAreaBackground->setPen(pen);
303 m_layout->invalidate();
303 m_layout->invalidate();
304 }
304 }
305
305
306 QPen ChartPresenter::plotAreaBackgroundPen() const
306 QPen ChartPresenter::plotAreaBackgroundPen() const
307 {
307 {
308 if (!m_plotAreaBackground)
308 if (!m_plotAreaBackground)
309 return QPen();
309 return QPen();
310 return m_plotAreaBackground->pen();
310 return m_plotAreaBackground->pen();
311 }
311 }
312
312
313 void ChartPresenter::setTitle(const QString &title)
313 void ChartPresenter::setTitle(const QString &title)
314 {
314 {
315 createTitleItem();
315 createTitleItem();
316 m_title->setText(title);
316 m_title->setText(title);
317 m_layout->invalidate();
317 m_layout->invalidate();
318 }
318 }
319
319
320 QString ChartPresenter::title() const
320 QString ChartPresenter::title() const
321 {
321 {
322 if (!m_title)
322 if (!m_title)
323 return QString();
323 return QString();
324 return m_title->text();
324 return m_title->text();
325 }
325 }
326
326
327 void ChartPresenter::setTitleFont(const QFont &font)
327 void ChartPresenter::setTitleFont(const QFont &font)
328 {
328 {
329 createTitleItem();
329 createTitleItem();
330 m_title->setFont(font);
330 m_title->setFont(font);
331 m_layout->invalidate();
331 m_layout->invalidate();
332 }
332 }
333
333
334 QFont ChartPresenter::titleFont() const
334 QFont ChartPresenter::titleFont() const
335 {
335 {
336 if (!m_title)
336 if (!m_title)
337 return QFont();
337 return QFont();
338 return m_title->font();
338 return m_title->font();
339 }
339 }
340
340
341 void ChartPresenter::setTitleBrush(const QBrush &brush)
341 void ChartPresenter::setTitleBrush(const QBrush &brush)
342 {
342 {
343 createTitleItem();
343 createTitleItem();
344 m_title->setDefaultTextColor(brush.color());
344 m_title->setDefaultTextColor(brush.color());
345 m_layout->invalidate();
345 m_layout->invalidate();
346 }
346 }
347
347
348 QBrush ChartPresenter::titleBrush() const
348 QBrush ChartPresenter::titleBrush() const
349 {
349 {
350 if (!m_title)
350 if (!m_title)
351 return QBrush();
351 return QBrush();
352 return QBrush(m_title->defaultTextColor());
352 return QBrush(m_title->defaultTextColor());
353 }
353 }
354
354
355 void ChartPresenter::setBackgroundVisible(bool visible)
355 void ChartPresenter::setBackgroundVisible(bool visible)
356 {
356 {
357 createBackgroundItem();
357 createBackgroundItem();
358 m_background->setVisible(visible);
358 m_background->setVisible(visible);
359 }
359 }
360
360
361
361
362 bool ChartPresenter::isBackgroundVisible() const
362 bool ChartPresenter::isBackgroundVisible() const
363 {
363 {
364 if (!m_background)
364 if (!m_background)
365 return false;
365 return false;
366 return m_background->isVisible();
366 return m_background->isVisible();
367 }
367 }
368
368
369 void ChartPresenter::setPlotAreaBackgroundVisible(bool visible)
369 void ChartPresenter::setPlotAreaBackgroundVisible(bool visible)
370 {
370 {
371 createPlotAreaBackgroundItem();
371 createPlotAreaBackgroundItem();
372 m_plotAreaBackground->setVisible(visible);
372 m_plotAreaBackground->setVisible(visible);
373 }
373 }
374
374
375 bool ChartPresenter::isPlotAreaBackgroundVisible() const
375 bool ChartPresenter::isPlotAreaBackgroundVisible() const
376 {
376 {
377 if (!m_plotAreaBackground)
377 if (!m_plotAreaBackground)
378 return false;
378 return false;
379 return m_plotAreaBackground->isVisible();
379 return m_plotAreaBackground->isVisible();
380 }
380 }
381
381
382 void ChartPresenter::setBackgroundDropShadowEnabled(bool enabled)
382 void ChartPresenter::setBackgroundDropShadowEnabled(bool enabled)
383 {
383 {
384 createBackgroundItem();
384 createBackgroundItem();
385 m_background->setDropShadowEnabled(enabled);
385 m_background->setDropShadowEnabled(enabled);
386 }
386 }
387
387
388 bool ChartPresenter::isBackgroundDropShadowEnabled() const
388 bool ChartPresenter::isBackgroundDropShadowEnabled() const
389 {
389 {
390 if (!m_background)
390 if (!m_background)
391 return false;
391 return false;
392 return m_background->isDropShadowEnabled();
392 return m_background->isDropShadowEnabled();
393 }
393 }
394
394
395 void ChartPresenter::setLocalizeNumbers(bool localize)
395 void ChartPresenter::setLocalizeNumbers(bool localize)
396 {
396 {
397 m_localizeNumbers = localize;
397 m_localizeNumbers = localize;
398 m_layout->invalidate();
398 m_layout->invalidate();
399 }
399 }
400
400
401 void ChartPresenter::setLocale(const QLocale &locale)
401 void ChartPresenter::setLocale(const QLocale &locale)
402 {
402 {
403 m_locale = locale;
403 m_locale = locale;
404 m_layout->invalidate();
404 m_layout->invalidate();
405 }
405 }
406
406
407 AbstractChartLayout *ChartPresenter::layout()
407 AbstractChartLayout *ChartPresenter::layout()
408 {
408 {
409 return m_layout;
409 return m_layout;
410 }
410 }
411
411
412 QLegend *ChartPresenter::legend()
412 QLegend *ChartPresenter::legend()
413 {
413 {
414 return m_chart->legend();
414 return m_chart->legend();
415 }
415 }
416
416
417 void ChartPresenter::setVisible(bool visible)
417 void ChartPresenter::setVisible(bool visible)
418 {
418 {
419 m_chart->setVisible(visible);
419 m_chart->setVisible(visible);
420 }
420 }
421
421
422 ChartBackground *ChartPresenter::backgroundElement()
422 ChartBackground *ChartPresenter::backgroundElement()
423 {
423 {
424 return m_background;
424 return m_background;
425 }
425 }
426
426
427 QAbstractGraphicsShapeItem *ChartPresenter::plotAreaElement()
427 QAbstractGraphicsShapeItem *ChartPresenter::plotAreaElement()
428 {
428 {
429 return m_plotAreaBackground;
429 return m_plotAreaBackground;
430 }
430 }
431
431
432 QList<ChartAxisElement *> ChartPresenter::axisItems() const
432 QList<ChartAxisElement *> ChartPresenter::axisItems() const
433 {
433 {
434 return m_axisItems;
434 return m_axisItems;
435 }
435 }
436
436
437 QList<ChartItem *> ChartPresenter::chartItems() const
437 QList<ChartItem *> ChartPresenter::chartItems() const
438 {
438 {
439 return m_chartItems;
439 return m_chartItems;
440 }
440 }
441
441
442 ChartTitle *ChartPresenter::titleElement()
442 ChartTitle *ChartPresenter::titleElement()
443 {
443 {
444 return m_title;
444 return m_title;
445 }
445 }
446
446
447 QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, qreal angle)
447 QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, qreal angle)
448 {
448 {
449 static QGraphicsTextItem dummyTextItem;
449 static QGraphicsTextItem dummyTextItem;
450 static bool initMargin = true;
450 static bool initMargin = true;
451 if (initMargin) {
451 if (initMargin) {
452 dummyTextItem.document()->setDocumentMargin(textMargin());
452 dummyTextItem.document()->setDocumentMargin(textMargin());
453 initMargin = false;
453 initMargin = false;
454 }
454 }
455
455
456 dummyTextItem.setFont(font);
456 dummyTextItem.setFont(font);
457 dummyTextItem.setHtml(text);
457 dummyTextItem.setHtml(text);
458 QRectF boundingRect = dummyTextItem.boundingRect();
458 QRectF boundingRect = dummyTextItem.boundingRect();
459
459
460 // Take rotation into account
460 // Take rotation into account
461 if (angle) {
461 if (angle) {
462 QTransform transform;
462 QTransform transform;
463 transform.rotate(angle);
463 transform.rotate(angle);
464 boundingRect = transform.mapRect(boundingRect);
464 boundingRect = transform.mapRect(boundingRect);
465 }
465 }
466
466
467 return boundingRect;
467 return boundingRect;
468 }
468 }
469
469
470 // boundingRect parameter returns the rotated bounding rect of the text
470 // boundingRect parameter returns the rotated bounding rect of the text
471 QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle,
471 QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle,
472 qreal maxWidth, qreal maxHeight, QRectF &boundingRect)
472 qreal maxWidth, qreal maxHeight, QRectF &boundingRect)
473 {
473 {
474 QString truncatedString(text);
474 QString truncatedString(text);
475 boundingRect = textBoundingRect(font, truncatedString, angle);
475 boundingRect = textBoundingRect(font, truncatedString, angle);
476 if (boundingRect.width() > maxWidth || boundingRect.height() > maxHeight) {
476 if (boundingRect.width() > maxWidth || boundingRect.height() > maxHeight) {
477 // It can be assumed that almost any amount of string manipulation is faster
477 // It can be assumed that almost any amount of string manipulation is faster
478 // than calculating one bounding rectangle, so first prepare a list of truncated strings
478 // than calculating one bounding rectangle, so first prepare a list of truncated strings
479 // to try.
479 // to try.
480 static QRegExp truncateMatcher(QStringLiteral("&#?[0-9a-zA-Z]*;$"));
480 static QRegExp truncateMatcher(QStringLiteral("&#?[0-9a-zA-Z]*;$"));
481
481
482 QVector<QString> testStrings(text.length());
482 QVector<QString> testStrings(text.length());
483 int count(0);
483 int count(0);
484 static QLatin1Char closeTag('>');
484 static QLatin1Char closeTag('>');
485 static QLatin1Char openTag('<');
485 static QLatin1Char openTag('<');
486 static QLatin1Char semiColon(';');
486 static QLatin1Char semiColon(';');
487 static QLatin1String ellipsis("...");
487 static QLatin1String ellipsis("...");
488 while (truncatedString.length() > 1) {
488 while (truncatedString.length() > 1) {
489 int chopIndex(-1);
489 int chopIndex(-1);
490 int chopCount(1);
490 int chopCount(1);
491 QChar lastChar(truncatedString.at(truncatedString.length() - 1));
491 QChar lastChar(truncatedString.at(truncatedString.length() - 1));
492
492
493 if (lastChar == closeTag)
493 if (lastChar == closeTag)
494 chopIndex = truncatedString.lastIndexOf(openTag);
494 chopIndex = truncatedString.lastIndexOf(openTag);
495 else if (lastChar == semiColon)
495 else if (lastChar == semiColon)
496 chopIndex = truncateMatcher.indexIn(truncatedString, 0);
496 chopIndex = truncateMatcher.indexIn(truncatedString, 0);
497
497
498 if (chopIndex != -1)
498 if (chopIndex != -1)
499 chopCount = truncatedString.length() - chopIndex;
499 chopCount = truncatedString.length() - chopIndex;
500 truncatedString.chop(chopCount);
500 truncatedString.chop(chopCount);
501 testStrings[count] = truncatedString + ellipsis;
501 testStrings[count] = truncatedString + ellipsis;
502 count++;
502 count++;
503 }
503 }
504
504
505 // Binary search for best fit
505 // Binary search for best fit
506 int minIndex(0);
506 int minIndex(0);
507 int maxIndex(count - 1);
507 int maxIndex(count - 1);
508 int bestIndex(count);
508 int bestIndex(count);
509 QRectF checkRect;
509 QRectF checkRect;
510
510
511 while (maxIndex >= minIndex) {
511 while (maxIndex >= minIndex) {
512 int mid = (maxIndex + minIndex) / 2;
512 int mid = (maxIndex + minIndex) / 2;
513 checkRect = textBoundingRect(font, testStrings.at(mid), angle);
513 checkRect = textBoundingRect(font, testStrings.at(mid), angle);
514 if (checkRect.width() > maxWidth || checkRect.height() > maxHeight) {
514 if (checkRect.width() > maxWidth || checkRect.height() > maxHeight) {
515 // Checked index too large, all under this are also too large
515 // Checked index too large, all under this are also too large
516 minIndex = mid + 1;
516 minIndex = mid + 1;
517 } else {
517 } else {
518 // Checked index fits, all over this also fit
518 // Checked index fits, all over this also fit
519 maxIndex = mid - 1;
519 maxIndex = mid - 1;
520 bestIndex = mid;
520 bestIndex = mid;
521 boundingRect = checkRect;
521 boundingRect = checkRect;
522 }
522 }
523 }
523 }
524 // Default to "..." if nothing fits
524 // Default to "..." if nothing fits
525 if (bestIndex == count) {
525 if (bestIndex == count) {
526 boundingRect = textBoundingRect(font, ellipsis, angle);
526 boundingRect = textBoundingRect(font, ellipsis, angle);
527 truncatedString = ellipsis;
527 truncatedString = ellipsis;
528 } else {
528 } else {
529 truncatedString = testStrings.at(bestIndex);
529 truncatedString = testStrings.at(bestIndex);
530 }
530 }
531 }
531 }
532
532
533 return truncatedString;
533 return truncatedString;
534 }
534 }
535
535
536 QString ChartPresenter::numberToString(double value, char f, int prec)
536 QString ChartPresenter::numberToString(double value, char f, int prec)
537 {
537 {
538 if (m_localizeNumbers)
538 if (m_localizeNumbers)
539 return m_locale.toString(value, f, prec);
539 return m_locale.toString(value, f, prec);
540 else
540 else
541 return QString::number(value, f, prec);
541 return QString::number(value, f, prec);
542 }
542 }
543
543
544 QString ChartPresenter::numberToString(int value)
544 QString ChartPresenter::numberToString(int value)
545 {
545 {
546 if (m_localizeNumbers)
546 if (m_localizeNumbers)
547 return m_locale.toString(value);
547 return m_locale.toString(value);
548 else
548 else
549 return QString::number(value);
549 return QString::number(value);
550 }
550 }
551
551
552 void ChartPresenter::ensureGLWidget()
552 void ChartPresenter::updateGLWidget()
553 {
553 {
554 #ifndef QT_NO_OPENGL
554 #ifndef QT_NO_OPENGL
555 // GLWidget pointer is wrapped in QPointer as its parent is not in our control, and therefore
555 // GLWidget pointer is wrapped in QPointer as its parent is not in our control, and therefore
556 // can potentially get deleted unexpectedly.
556 // can potentially get deleted unexpectedly.
557 if (m_glWidget.isNull() && m_glUseWidget && m_chart->scene()) {
557 if (m_glWidget.isNull() && m_glUseWidget && m_chart->scene()) {
558 // Find the view of the scene. If the scene has multiple views, only the first view is
558 // Find the view of the scene. If the scene has multiple views, only the first view is
559 // chosen.
559 // chosen.
560 QList<QGraphicsView *> views = m_chart->scene()->views();
560 QList<QGraphicsView *> views = m_chart->scene()->views();
561 if (views.size()) {
561 if (views.size()) {
562 QGraphicsView *firstView = views.at(0);
562 QGraphicsView *firstView = views.at(0);
563 m_glWidget = new GLWidget(m_chart->d_ptr->m_dataset->glXYSeriesDataManager(),
563 m_glWidget = new GLWidget(m_chart->d_ptr->m_dataset->glXYSeriesDataManager(),
564 firstView);
564 firstView);
565 m_glWidget->setGeometry(m_rect.toRect());
565 m_glWidget->setGeometry(m_rect.toRect());
566 m_glWidget->show();
566 m_glWidget->show();
567 }
567 }
568 }
568 }
569 // Make sure we update the widget in a timely manner
570 if (!m_glWidget.isNull())
571 m_glWidget->update();
569 #endif
572 #endif
570 }
573 }
571
574
572 #include "moc_chartpresenter_p.cpp"
575 #include "moc_chartpresenter_p.cpp"
573
576
574 QT_CHARTS_END_NAMESPACE
577 QT_CHARTS_END_NAMESPACE
@@ -1,212 +1,212
1 /******************************************************************************
1 /******************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
4 ** Contact: http://www.qt.io/licensing/
5 **
5 **
6 ** This file is part of the Qt Charts module.
6 ** This file is part of the Qt Charts module.
7 **
7 **
8 ** $QT_BEGIN_LICENSE:COMM$
8 ** $QT_BEGIN_LICENSE:COMM$
9 **
9 **
10 ** Commercial License Usage
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** and conditions see http://www.qt.io/terms-conditions. For further
16 ** information use the contact form at http://www.qt.io/contact-us.
16 ** information use the contact form at http://www.qt.io/contact-us.
17 **
17 **
18 ** $QT_END_LICENSE$
18 ** $QT_END_LICENSE$
19 **
19 **
20 ******************************************************************************/
20 ******************************************************************************/
21
21
22 // W A R N I N G
22 // W A R N I N G
23 // -------------
23 // -------------
24 //
24 //
25 // This file is not part of the Qt Chart API. It exists purely as an
25 // This file is not part of the Qt Chart API. It exists purely as an
26 // implementation detail. This header file may change from version to
26 // implementation detail. This header file may change from version to
27 // version without notice, or even be removed.
27 // version without notice, or even be removed.
28 //
28 //
29 // We mean it.
29 // We mean it.
30
30
31 #ifndef CHARTPRESENTER_H
31 #ifndef CHARTPRESENTER_H
32 #define CHARTPRESENTER_H
32 #define CHARTPRESENTER_H
33
33
34 #include <QtCharts/QChartGlobal>
34 #include <QtCharts/QChartGlobal>
35 #include <QtCharts/QChart> //because of QChart::ChartThemeId
35 #include <QtCharts/QChart> //because of QChart::ChartThemeId
36 #include <private/glwidget_p.h>
36 #include <private/glwidget_p.h>
37 #include <QtCore/QRectF>
37 #include <QtCore/QRectF>
38 #include <QtCore/QMargins>
38 #include <QtCore/QMargins>
39 #include <QtCore/QLocale>
39 #include <QtCore/QLocale>
40 #include <QtCore/QPointer>
40 #include <QtCore/QPointer>
41 #include <QtCore/QEasingCurve>
41 #include <QtCore/QEasingCurve>
42
42
43 QT_CHARTS_BEGIN_NAMESPACE
43 QT_CHARTS_BEGIN_NAMESPACE
44
44
45 class ChartItem;
45 class ChartItem;
46 class AxisItem;
46 class AxisItem;
47 class QAbstractSeries;
47 class QAbstractSeries;
48 class ChartDataSet;
48 class ChartDataSet;
49 class AbstractDomain;
49 class AbstractDomain;
50 class ChartAxisElement;
50 class ChartAxisElement;
51 class ChartAnimator;
51 class ChartAnimator;
52 class ChartBackground;
52 class ChartBackground;
53 class ChartTitle;
53 class ChartTitle;
54 class ChartAnimation;
54 class ChartAnimation;
55 class AbstractChartLayout;
55 class AbstractChartLayout;
56
56
57 class ChartPresenter: public QObject
57 class ChartPresenter: public QObject
58 {
58 {
59 Q_OBJECT
59 Q_OBJECT
60 public:
60 public:
61 enum ZValues {
61 enum ZValues {
62 BackgroundZValue = -1,
62 BackgroundZValue = -1,
63 PlotAreaZValue,
63 PlotAreaZValue,
64 ShadesZValue,
64 ShadesZValue,
65 GridZValue,
65 GridZValue,
66 AxisZValue,
66 AxisZValue,
67 SeriesZValue,
67 SeriesZValue,
68 LineChartZValue = SeriesZValue,
68 LineChartZValue = SeriesZValue,
69 SplineChartZValue = SeriesZValue,
69 SplineChartZValue = SeriesZValue,
70 BarSeriesZValue = SeriesZValue,
70 BarSeriesZValue = SeriesZValue,
71 ScatterSeriesZValue = SeriesZValue,
71 ScatterSeriesZValue = SeriesZValue,
72 PieSeriesZValue = SeriesZValue,
72 PieSeriesZValue = SeriesZValue,
73 BoxPlotSeriesZValue = SeriesZValue,
73 BoxPlotSeriesZValue = SeriesZValue,
74 LegendZValue,
74 LegendZValue,
75 TopMostZValue
75 TopMostZValue
76 };
76 };
77
77
78 enum State {
78 enum State {
79 ShowState,
79 ShowState,
80 ScrollUpState,
80 ScrollUpState,
81 ScrollDownState,
81 ScrollDownState,
82 ScrollLeftState,
82 ScrollLeftState,
83 ScrollRightState,
83 ScrollRightState,
84 ZoomInState,
84 ZoomInState,
85 ZoomOutState
85 ZoomOutState
86 };
86 };
87
87
88 ChartPresenter(QChart *chart, QChart::ChartType type);
88 ChartPresenter(QChart *chart, QChart::ChartType type);
89 virtual ~ChartPresenter();
89 virtual ~ChartPresenter();
90
90
91
91
92 void setGeometry(QRectF rect);
92 void setGeometry(QRectF rect);
93 QRectF geometry() const;
93 QRectF geometry() const;
94
94
95 QGraphicsItem *rootItem(){ return m_chart; }
95 QGraphicsItem *rootItem(){ return m_chart; }
96 ChartBackground *backgroundElement();
96 ChartBackground *backgroundElement();
97 QAbstractGraphicsShapeItem *plotAreaElement();
97 QAbstractGraphicsShapeItem *plotAreaElement();
98 ChartTitle *titleElement();
98 ChartTitle *titleElement();
99 QList<ChartAxisElement *> axisItems() const;
99 QList<ChartAxisElement *> axisItems() const;
100 QList<ChartItem *> chartItems() const;
100 QList<ChartItem *> chartItems() const;
101
101
102 QLegend *legend();
102 QLegend *legend();
103
103
104 void setBackgroundBrush(const QBrush &brush);
104 void setBackgroundBrush(const QBrush &brush);
105 QBrush backgroundBrush() const;
105 QBrush backgroundBrush() const;
106
106
107 void setBackgroundPen(const QPen &pen);
107 void setBackgroundPen(const QPen &pen);
108 QPen backgroundPen() const;
108 QPen backgroundPen() const;
109
109
110 void setBackgroundRoundness(qreal diameter);
110 void setBackgroundRoundness(qreal diameter);
111 qreal backgroundRoundness() const;
111 qreal backgroundRoundness() const;
112
112
113 void setPlotAreaBackgroundBrush(const QBrush &brush);
113 void setPlotAreaBackgroundBrush(const QBrush &brush);
114 QBrush plotAreaBackgroundBrush() const;
114 QBrush plotAreaBackgroundBrush() const;
115
115
116 void setPlotAreaBackgroundPen(const QPen &pen);
116 void setPlotAreaBackgroundPen(const QPen &pen);
117 QPen plotAreaBackgroundPen() const;
117 QPen plotAreaBackgroundPen() const;
118
118
119 void setTitle(const QString &title);
119 void setTitle(const QString &title);
120 QString title() const;
120 QString title() const;
121
121
122 void setTitleFont(const QFont &font);
122 void setTitleFont(const QFont &font);
123 QFont titleFont() const;
123 QFont titleFont() const;
124
124
125 void setTitleBrush(const QBrush &brush);
125 void setTitleBrush(const QBrush &brush);
126 QBrush titleBrush() const;
126 QBrush titleBrush() const;
127
127
128 void setBackgroundVisible(bool visible);
128 void setBackgroundVisible(bool visible);
129 bool isBackgroundVisible() const;
129 bool isBackgroundVisible() const;
130
130
131 void setPlotAreaBackgroundVisible(bool visible);
131 void setPlotAreaBackgroundVisible(bool visible);
132 bool isPlotAreaBackgroundVisible() const;
132 bool isPlotAreaBackgroundVisible() const;
133
133
134 void setBackgroundDropShadowEnabled(bool enabled);
134 void setBackgroundDropShadowEnabled(bool enabled);
135 bool isBackgroundDropShadowEnabled() const;
135 bool isBackgroundDropShadowEnabled() const;
136
136
137 void setLocalizeNumbers(bool localize);
137 void setLocalizeNumbers(bool localize);
138 inline bool localizeNumbers() const { return m_localizeNumbers; }
138 inline bool localizeNumbers() const { return m_localizeNumbers; }
139 void setLocale(const QLocale &locale);
139 void setLocale(const QLocale &locale);
140 inline const QLocale &locale() const { return m_locale; }
140 inline const QLocale &locale() const { return m_locale; }
141
141
142 void setVisible(bool visible);
142 void setVisible(bool visible);
143
143
144 void setAnimationOptions(QChart::AnimationOptions options);
144 void setAnimationOptions(QChart::AnimationOptions options);
145 QChart::AnimationOptions animationOptions() const;
145 QChart::AnimationOptions animationOptions() const;
146 void setAnimationDuration(int msecs);
146 void setAnimationDuration(int msecs);
147 int animationDuration() const { return m_animationDuration; }
147 int animationDuration() const { return m_animationDuration; }
148 void setAnimationEasingCurve(const QEasingCurve &curve);
148 void setAnimationEasingCurve(const QEasingCurve &curve);
149 QEasingCurve animationEasingCurve() const { return m_animationCurve; }
149 QEasingCurve animationEasingCurve() const { return m_animationCurve; }
150
150
151 void startAnimation(ChartAnimation *animation);
151 void startAnimation(ChartAnimation *animation);
152
152
153 void setState(State state,QPointF point);
153 void setState(State state,QPointF point);
154 State state() const { return m_state; }
154 State state() const { return m_state; }
155 QPointF statePoint() const { return m_statePoint; }
155 QPointF statePoint() const { return m_statePoint; }
156 AbstractChartLayout *layout();
156 AbstractChartLayout *layout();
157
157
158 QChart::ChartType chartType() const { return m_chart->chartType(); }
158 QChart::ChartType chartType() const { return m_chart->chartType(); }
159 QChart *chart() { return m_chart; }
159 QChart *chart() { return m_chart; }
160
160
161 static QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0);
161 static QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0);
162 static QString truncatedText(const QFont &font, const QString &text, qreal angle,
162 static QString truncatedText(const QFont &font, const QString &text, qreal angle,
163 qreal maxWidth, qreal maxHeight, QRectF &boundingRect);
163 qreal maxWidth, qreal maxHeight, QRectF &boundingRect);
164 inline static qreal textMargin() { return qreal(0.5); }
164 inline static qreal textMargin() { return qreal(0.5); }
165
165
166 QString numberToString(double value, char f = 'g', int prec = 6);
166 QString numberToString(double value, char f = 'g', int prec = 6);
167 QString numberToString(int value);
167 QString numberToString(int value);
168
168
169 void ensureGLWidget();
169 void updateGLWidget();
170 void glSetUseWidget(bool enable) { m_glUseWidget = enable; }
170 void glSetUseWidget(bool enable) { m_glUseWidget = enable; }
171
171
172 private:
172 private:
173 void createBackgroundItem();
173 void createBackgroundItem();
174 void createPlotAreaBackgroundItem();
174 void createPlotAreaBackgroundItem();
175 void createTitleItem();
175 void createTitleItem();
176
176
177 public Q_SLOTS:
177 public Q_SLOTS:
178 void handleSeriesAdded(QAbstractSeries *series);
178 void handleSeriesAdded(QAbstractSeries *series);
179 void handleSeriesRemoved(QAbstractSeries *series);
179 void handleSeriesRemoved(QAbstractSeries *series);
180 void handleAxisAdded(QAbstractAxis *axis);
180 void handleAxisAdded(QAbstractAxis *axis);
181 void handleAxisRemoved(QAbstractAxis *axis);
181 void handleAxisRemoved(QAbstractAxis *axis);
182
182
183 Q_SIGNALS:
183 Q_SIGNALS:
184 void plotAreaChanged(const QRectF &plotArea);
184 void plotAreaChanged(const QRectF &plotArea);
185
185
186 private:
186 private:
187 QChart *m_chart;
187 QChart *m_chart;
188 QList<ChartItem *> m_chartItems;
188 QList<ChartItem *> m_chartItems;
189 QList<ChartAxisElement *> m_axisItems;
189 QList<ChartAxisElement *> m_axisItems;
190 QList<QAbstractSeries *> m_series;
190 QList<QAbstractSeries *> m_series;
191 QList<QAbstractAxis *> m_axes;
191 QList<QAbstractAxis *> m_axes;
192 QChart::AnimationOptions m_options;
192 QChart::AnimationOptions m_options;
193 int m_animationDuration;
193 int m_animationDuration;
194 QEasingCurve m_animationCurve;
194 QEasingCurve m_animationCurve;
195 State m_state;
195 State m_state;
196 QPointF m_statePoint;
196 QPointF m_statePoint;
197 AbstractChartLayout *m_layout;
197 AbstractChartLayout *m_layout;
198 ChartBackground *m_background;
198 ChartBackground *m_background;
199 QAbstractGraphicsShapeItem *m_plotAreaBackground;
199 QAbstractGraphicsShapeItem *m_plotAreaBackground;
200 ChartTitle *m_title;
200 ChartTitle *m_title;
201 QRectF m_rect;
201 QRectF m_rect;
202 bool m_localizeNumbers;
202 bool m_localizeNumbers;
203 QLocale m_locale;
203 QLocale m_locale;
204 #ifndef QT_NO_OPENGL
204 #ifndef QT_NO_OPENGL
205 QPointer<GLWidget> m_glWidget;
205 QPointer<GLWidget> m_glWidget;
206 #endif
206 #endif
207 bool m_glUseWidget;
207 bool m_glUseWidget;
208 };
208 };
209
209
210 QT_CHARTS_END_NAMESPACE
210 QT_CHARTS_END_NAMESPACE
211
211
212 #endif /* CHARTPRESENTER_H */
212 #endif /* CHARTPRESENTER_H */
@@ -1,238 +1,238
1 /******************************************************************************
1 /******************************************************************************
2 **
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
4 ** Contact: http://www.qt.io/licensing/
5 **
5 **
6 ** This file is part of the Qt Charts module.
6 ** This file is part of the Qt Charts module.
7 **
7 **
8 ** $QT_BEGIN_LICENSE:COMM$
8 ** $QT_BEGIN_LICENSE:COMM$
9 **
9 **
10 ** Commercial License Usage
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** and conditions see http://www.qt.io/terms-conditions. For further
16 ** information use the contact form at http://www.qt.io/contact-us.
16 ** information use the contact form at http://www.qt.io/contact-us.
17 **
17 **
18 ** $QT_END_LICENSE$
18 ** $QT_END_LICENSE$
19 **
19 **
20 ******************************************************************************/
20 ******************************************************************************/
21
21
22 #include <private/xychart_p.h>
22 #include <private/xychart_p.h>
23 #include <QtCharts/QXYSeries>
23 #include <QtCharts/QXYSeries>
24 #include <private/qxyseries_p.h>
24 #include <private/qxyseries_p.h>
25 #include <private/chartpresenter_p.h>
25 #include <private/chartpresenter_p.h>
26 #include <private/abstractdomain_p.h>
26 #include <private/abstractdomain_p.h>
27 #include <private/chartdataset_p.h>
27 #include <private/chartdataset_p.h>
28 #include <private/glxyseriesdata_p.h>
28 #include <private/glxyseriesdata_p.h>
29 #include <QtCharts/QXYModelMapper>
29 #include <QtCharts/QXYModelMapper>
30 #include <private/qabstractaxis_p.h>
30 #include <private/qabstractaxis_p.h>
31 #include <QtGui/QPainter>
31 #include <QtGui/QPainter>
32 #include <QtCore/QAbstractItemModel>
32 #include <QtCore/QAbstractItemModel>
33
33
34
34
35 QT_CHARTS_BEGIN_NAMESPACE
35 QT_CHARTS_BEGIN_NAMESPACE
36
36
37 XYChart::XYChart(QXYSeries *series, QGraphicsItem *item):
37 XYChart::XYChart(QXYSeries *series, QGraphicsItem *item):
38 ChartItem(series->d_func(),item),
38 ChartItem(series->d_func(),item),
39 m_series(series),
39 m_series(series),
40 m_animation(0),
40 m_animation(0),
41 m_dirty(true)
41 m_dirty(true)
42 {
42 {
43 QObject::connect(series, SIGNAL(pointReplaced(int)), this, SLOT(handlePointReplaced(int)));
43 QObject::connect(series, SIGNAL(pointReplaced(int)), this, SLOT(handlePointReplaced(int)));
44 QObject::connect(series, SIGNAL(pointsReplaced()), this, SLOT(handlePointsReplaced()));
44 QObject::connect(series, SIGNAL(pointsReplaced()), this, SLOT(handlePointsReplaced()));
45 QObject::connect(series, SIGNAL(pointAdded(int)), this, SLOT(handlePointAdded(int)));
45 QObject::connect(series, SIGNAL(pointAdded(int)), this, SLOT(handlePointAdded(int)));
46 QObject::connect(series, SIGNAL(pointRemoved(int)), this, SLOT(handlePointRemoved(int)));
46 QObject::connect(series, SIGNAL(pointRemoved(int)), this, SLOT(handlePointRemoved(int)));
47 QObject::connect(series, SIGNAL(pointsRemoved(int, int)), this, SLOT(handlePointsRemoved(int, int)));
47 QObject::connect(series, SIGNAL(pointsRemoved(int, int)), this, SLOT(handlePointsRemoved(int, int)));
48 QObject::connect(this, SIGNAL(clicked(QPointF)), series, SIGNAL(clicked(QPointF)));
48 QObject::connect(this, SIGNAL(clicked(QPointF)), series, SIGNAL(clicked(QPointF)));
49 QObject::connect(this, SIGNAL(hovered(QPointF,bool)), series, SIGNAL(hovered(QPointF,bool)));
49 QObject::connect(this, SIGNAL(hovered(QPointF,bool)), series, SIGNAL(hovered(QPointF,bool)));
50 QObject::connect(this, SIGNAL(pressed(QPointF)), series, SIGNAL(pressed(QPointF)));
50 QObject::connect(this, SIGNAL(pressed(QPointF)), series, SIGNAL(pressed(QPointF)));
51 QObject::connect(this, SIGNAL(released(QPointF)), series, SIGNAL(released(QPointF)));
51 QObject::connect(this, SIGNAL(released(QPointF)), series, SIGNAL(released(QPointF)));
52 QObject::connect(this, SIGNAL(doubleClicked(QPointF)), series, SIGNAL(doubleClicked(QPointF)));
52 QObject::connect(this, SIGNAL(doubleClicked(QPointF)), series, SIGNAL(doubleClicked(QPointF)));
53 }
53 }
54
54
55 void XYChart::setGeometryPoints(const QVector<QPointF> &points)
55 void XYChart::setGeometryPoints(const QVector<QPointF> &points)
56 {
56 {
57 m_points = points;
57 m_points = points;
58 }
58 }
59
59
60 void XYChart::setAnimation(XYAnimation *animation)
60 void XYChart::setAnimation(XYAnimation *animation)
61 {
61 {
62 m_animation = animation;
62 m_animation = animation;
63 }
63 }
64
64
65 void XYChart::setDirty(bool dirty)
65 void XYChart::setDirty(bool dirty)
66 {
66 {
67 m_dirty = dirty;
67 m_dirty = dirty;
68 }
68 }
69
69
70 // Returns a vector with same size as geometryPoints vector, indicating
70 // Returns a vector with same size as geometryPoints vector, indicating
71 // the off grid status of points.
71 // the off grid status of points.
72 QVector<bool> XYChart::offGridStatusVector()
72 QVector<bool> XYChart::offGridStatusVector()
73 {
73 {
74 qreal minX = domain()->minX();
74 qreal minX = domain()->minX();
75 qreal maxX = domain()->maxX();
75 qreal maxX = domain()->maxX();
76 qreal minY = domain()->minY();
76 qreal minY = domain()->minY();
77 qreal maxY = domain()->maxY();
77 qreal maxY = domain()->maxY();
78
78
79 QVector<bool> returnVector;
79 QVector<bool> returnVector;
80 returnVector.resize(m_points.size());
80 returnVector.resize(m_points.size());
81 // During remove animation series may have different number of points,
81 // During remove animation series may have different number of points,
82 // so ensure we don't go over the index. No need to check for zero points, this
82 // so ensure we don't go over the index. No need to check for zero points, this
83 // will not be called in such a situation.
83 // will not be called in such a situation.
84 const int seriesLastIndex = m_series->count() - 1;
84 const int seriesLastIndex = m_series->count() - 1;
85
85
86 for (int i = 0; i < m_points.size(); i++) {
86 for (int i = 0; i < m_points.size(); i++) {
87 const QPointF &seriesPoint = m_series->at(qMin(seriesLastIndex, i));
87 const QPointF &seriesPoint = m_series->at(qMin(seriesLastIndex, i));
88 if (seriesPoint.x() < minX
88 if (seriesPoint.x() < minX
89 || seriesPoint.x() > maxX
89 || seriesPoint.x() > maxX
90 || seriesPoint.y() < minY
90 || seriesPoint.y() < minY
91 || seriesPoint.y() > maxY) {
91 || seriesPoint.y() > maxY) {
92 returnVector[i] = true;
92 returnVector[i] = true;
93 } else {
93 } else {
94 returnVector[i] = false;
94 returnVector[i] = false;
95 }
95 }
96 }
96 }
97 return returnVector;
97 return returnVector;
98 }
98 }
99
99
100 void XYChart::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
100 void XYChart::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
101 {
101 {
102
102
103 if (m_animation) {
103 if (m_animation) {
104 m_animation->setup(oldPoints, newPoints, index);
104 m_animation->setup(oldPoints, newPoints, index);
105 m_points = newPoints;
105 m_points = newPoints;
106 setDirty(false);
106 setDirty(false);
107 presenter()->startAnimation(m_animation);
107 presenter()->startAnimation(m_animation);
108 } else {
108 } else {
109 m_points = newPoints;
109 m_points = newPoints;
110 updateGeometry();
110 updateGeometry();
111 }
111 }
112 }
112 }
113
113
114 void XYChart::updateGlChart()
114 void XYChart::updateGlChart()
115 {
115 {
116 presenter()->ensureGLWidget();
117 dataSet()->glXYSeriesDataManager()->setPoints(m_series, domain());
116 dataSet()->glXYSeriesDataManager()->setPoints(m_series, domain());
117 presenter()->updateGLWidget();
118 updateGeometry();
118 updateGeometry();
119 }
119 }
120
120
121 //handlers
121 //handlers
122
122
123 void XYChart::handlePointAdded(int index)
123 void XYChart::handlePointAdded(int index)
124 {
124 {
125 Q_ASSERT(index < m_series->count());
125 Q_ASSERT(index < m_series->count());
126 Q_ASSERT(index >= 0);
126 Q_ASSERT(index >= 0);
127
127
128 if (m_series->useOpenGL()) {
128 if (m_series->useOpenGL()) {
129 updateGlChart();
129 updateGlChart();
130 } else {
130 } else {
131 QVector<QPointF> points;
131 QVector<QPointF> points;
132 if (m_dirty || m_points.isEmpty()) {
132 if (m_dirty || m_points.isEmpty()) {
133 points = domain()->calculateGeometryPoints(m_series->pointsVector());
133 points = domain()->calculateGeometryPoints(m_series->pointsVector());
134 } else {
134 } else {
135 points = m_points;
135 points = m_points;
136 QPointF point = domain()->calculateGeometryPoint(m_series->pointsVector().at(index),
136 QPointF point = domain()->calculateGeometryPoint(m_series->pointsVector().at(index),
137 m_validData);
137 m_validData);
138 if (!m_validData)
138 if (!m_validData)
139 m_points.clear();
139 m_points.clear();
140 else
140 else
141 points.insert(index, point);
141 points.insert(index, point);
142 }
142 }
143 updateChart(m_points, points, index);
143 updateChart(m_points, points, index);
144 }
144 }
145 }
145 }
146
146
147 void XYChart::handlePointRemoved(int index)
147 void XYChart::handlePointRemoved(int index)
148 {
148 {
149 Q_ASSERT(index <= m_series->count());
149 Q_ASSERT(index <= m_series->count());
150 Q_ASSERT(index >= 0);
150 Q_ASSERT(index >= 0);
151
151
152 if (m_series->useOpenGL()) {
152 if (m_series->useOpenGL()) {
153 updateGlChart();
153 updateGlChart();
154 } else {
154 } else {
155 QVector<QPointF> points;
155 QVector<QPointF> points;
156 if (m_dirty || m_points.isEmpty()) {
156 if (m_dirty || m_points.isEmpty()) {
157 points = domain()->calculateGeometryPoints(m_series->pointsVector());
157 points = domain()->calculateGeometryPoints(m_series->pointsVector());
158 } else {
158 } else {
159 points = m_points;
159 points = m_points;
160 points.remove(index);
160 points.remove(index);
161 }
161 }
162 updateChart(m_points, points, index);
162 updateChart(m_points, points, index);
163 }
163 }
164 }
164 }
165
165
166 void XYChart::handlePointsRemoved(int index, int count)
166 void XYChart::handlePointsRemoved(int index, int count)
167 {
167 {
168 Q_ASSERT(index <= m_series->count());
168 Q_ASSERT(index <= m_series->count());
169 Q_ASSERT(index >= 0);
169 Q_ASSERT(index >= 0);
170
170
171 if (m_series->useOpenGL()) {
171 if (m_series->useOpenGL()) {
172 updateGlChart();
172 updateGlChart();
173 } else {
173 } else {
174 QVector<QPointF> points;
174 QVector<QPointF> points;
175 if (m_dirty || m_points.isEmpty()) {
175 if (m_dirty || m_points.isEmpty()) {
176 points = domain()->calculateGeometryPoints(m_series->pointsVector());
176 points = domain()->calculateGeometryPoints(m_series->pointsVector());
177 } else {
177 } else {
178 points = m_points;
178 points = m_points;
179 points.remove(index, count);
179 points.remove(index, count);
180 }
180 }
181 updateChart(m_points, points, index);
181 updateChart(m_points, points, index);
182 }
182 }
183 }
183 }
184
184
185 void XYChart::handlePointReplaced(int index)
185 void XYChart::handlePointReplaced(int index)
186 {
186 {
187 Q_ASSERT(index < m_series->count());
187 Q_ASSERT(index < m_series->count());
188 Q_ASSERT(index >= 0);
188 Q_ASSERT(index >= 0);
189
189
190 if (m_series->useOpenGL()) {
190 if (m_series->useOpenGL()) {
191 updateGlChart();
191 updateGlChart();
192 } else {
192 } else {
193 QVector<QPointF> points;
193 QVector<QPointF> points;
194 if (m_dirty || m_points.isEmpty()) {
194 if (m_dirty || m_points.isEmpty()) {
195 points = domain()->calculateGeometryPoints(m_series->pointsVector());
195 points = domain()->calculateGeometryPoints(m_series->pointsVector());
196 } else {
196 } else {
197 QPointF point = domain()->calculateGeometryPoint(m_series->pointsVector().at(index),
197 QPointF point = domain()->calculateGeometryPoint(m_series->pointsVector().at(index),
198 m_validData);
198 m_validData);
199 if (!m_validData)
199 if (!m_validData)
200 m_points.clear();
200 m_points.clear();
201 points = m_points;
201 points = m_points;
202 if (m_validData)
202 if (m_validData)
203 points.replace(index, point);
203 points.replace(index, point);
204 }
204 }
205 updateChart(m_points, points, index);
205 updateChart(m_points, points, index);
206 }
206 }
207 }
207 }
208
208
209 void XYChart::handlePointsReplaced()
209 void XYChart::handlePointsReplaced()
210 {
210 {
211 if (m_series->useOpenGL()) {
211 if (m_series->useOpenGL()) {
212 updateGlChart();
212 updateGlChart();
213 } else {
213 } else {
214 // All the points were replaced -> recalculate
214 // All the points were replaced -> recalculate
215 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->pointsVector());
215 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->pointsVector());
216 updateChart(m_points, points, -1);
216 updateChart(m_points, points, -1);
217 }
217 }
218 }
218 }
219
219
220 void XYChart::handleDomainUpdated()
220 void XYChart::handleDomainUpdated()
221 {
221 {
222 if (m_series->useOpenGL()) {
222 if (m_series->useOpenGL()) {
223 updateGlChart();
223 updateGlChart();
224 } else {
224 } else {
225 if (isEmpty()) return;
225 if (isEmpty()) return;
226 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->pointsVector());
226 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->pointsVector());
227 updateChart(m_points, points);
227 updateChart(m_points, points);
228 }
228 }
229 }
229 }
230
230
231 bool XYChart::isEmpty()
231 bool XYChart::isEmpty()
232 {
232 {
233 return domain()->isEmpty() || m_series->points().isEmpty();
233 return domain()->isEmpty() || m_series->points().isEmpty();
234 }
234 }
235
235
236 #include "moc_xychart_p.cpp"
236 #include "moc_xychart_p.cpp"
237
237
238 QT_CHARTS_END_NAMESPACE
238 QT_CHARTS_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now