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