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