##// END OF EJS Templates
Fix crash in ChartDataSet::attachAxis()...
Kimmo Leppälä -
r2669:0a9f98e61ba3
parent child
Show More
@@ -1,637 +1,639
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Enterprise Charts Add-on.
7 ** This file is part of the Qt Enterprise Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
11 ** accordance with the Qt Enterprise License Agreement provided with the
11 ** accordance with the Qt Enterprise License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartdataset_p.h"
21 #include "chartdataset_p.h"
22 #include "chartpresenter_p.h"
22 #include "chartpresenter_p.h"
23 #include "qchart.h"
23 #include "qchart.h"
24 #include "qchart_p.h"
24 #include "qchart_p.h"
25 #include "qvalueaxis.h"
25 #include "qvalueaxis.h"
26 #include "qbarcategoryaxis.h"
26 #include "qbarcategoryaxis.h"
27 #include "qvalueaxis_p.h"
27 #include "qvalueaxis_p.h"
28 #include "qcategoryaxis.h"
28 #include "qcategoryaxis.h"
29 #include "qabstractseries_p.h"
29 #include "qabstractseries_p.h"
30 #include "qabstractbarseries.h"
30 #include "qabstractbarseries.h"
31 #include "qstackedbarseries.h"
31 #include "qstackedbarseries.h"
32 #include "qpercentbarseries.h"
32 #include "qpercentbarseries.h"
33 #include "qpieseries.h"
33 #include "qpieseries.h"
34 #include "chartitem_p.h"
34 #include "chartitem_p.h"
35 #include "xydomain_p.h"
35 #include "xydomain_p.h"
36 #include "xypolardomain_p.h"
36 #include "xypolardomain_p.h"
37 #include "xlogydomain_p.h"
37 #include "xlogydomain_p.h"
38 #include "logxydomain_p.h"
38 #include "logxydomain_p.h"
39 #include "logxlogydomain_p.h"
39 #include "logxlogydomain_p.h"
40 #include "xlogypolardomain_p.h"
40 #include "xlogypolardomain_p.h"
41 #include "logxypolardomain_p.h"
41 #include "logxypolardomain_p.h"
42 #include "logxlogypolardomain_p.h"
42 #include "logxlogypolardomain_p.h"
43
43
44 #ifndef QT_ON_ARM
44 #ifndef QT_ON_ARM
45 #include "qdatetimeaxis.h"
45 #include "qdatetimeaxis.h"
46 #endif
46 #endif
47
47
48 QTCOMMERCIALCHART_BEGIN_NAMESPACE
48 QTCOMMERCIALCHART_BEGIN_NAMESPACE
49
49
50 ChartDataSet::ChartDataSet(QChart *chart)
50 ChartDataSet::ChartDataSet(QChart *chart)
51 : QObject(chart),
51 : QObject(chart),
52 m_chart(chart)
52 m_chart(chart)
53 {
53 {
54
54
55 }
55 }
56
56
57 ChartDataSet::~ChartDataSet()
57 ChartDataSet::~ChartDataSet()
58 {
58 {
59 deleteAllSeries();
59 deleteAllSeries();
60 deleteAllAxes();
60 deleteAllAxes();
61 }
61 }
62
62
63 /*
63 /*
64 * This method adds series to chartdataset, series ownership is taken from caller.
64 * This method adds series to chartdataset, series ownership is taken from caller.
65 */
65 */
66 void ChartDataSet::addSeries(QAbstractSeries *series)
66 void ChartDataSet::addSeries(QAbstractSeries *series)
67 {
67 {
68 if (m_seriesList.contains(series)) {
68 if (m_seriesList.contains(series)) {
69 qWarning() << QObject::tr("Can not add series. Series already on the chart.");
69 qWarning() << QObject::tr("Can not add series. Series already on the chart.");
70 return;
70 return;
71 }
71 }
72
72
73 // Ignore unsupported series added to polar chart
73 // Ignore unsupported series added to polar chart
74 if (m_chart && m_chart->chartType() == QChart::ChartTypePolar) {
74 if (m_chart && m_chart->chartType() == QChart::ChartTypePolar) {
75 if (!(series->type() == QAbstractSeries::SeriesTypeArea
75 if (!(series->type() == QAbstractSeries::SeriesTypeArea
76 || series->type() == QAbstractSeries::SeriesTypeLine
76 || series->type() == QAbstractSeries::SeriesTypeLine
77 || series->type() == QAbstractSeries::SeriesTypeScatter
77 || series->type() == QAbstractSeries::SeriesTypeScatter
78 || series->type() == QAbstractSeries::SeriesTypeSpline)) {
78 || series->type() == QAbstractSeries::SeriesTypeSpline)) {
79 qWarning() << QObject::tr("Can not add series. Series type is not supported by a polar chart.");
79 qWarning() << QObject::tr("Can not add series. Series type is not supported by a polar chart.");
80 return;
80 return;
81 }
81 }
82 series->d_ptr->setDomain(new XYPolarDomain());
82 series->d_ptr->setDomain(new XYPolarDomain());
83 } else {
83 } else {
84 series->d_ptr->setDomain(new XYDomain());
84 series->d_ptr->setDomain(new XYDomain());
85 }
85 }
86
86
87 series->d_ptr->initializeDomain();
87 series->d_ptr->initializeDomain();
88 m_seriesList.append(series);
88 m_seriesList.append(series);
89
89
90 series->setParent(this); // take ownership
90 series->setParent(this); // take ownership
91 series->d_ptr->m_chart = m_chart;
91 series->d_ptr->m_chart = m_chart;
92
92
93 emit seriesAdded(series);
93 emit seriesAdded(series);
94 }
94 }
95
95
96 /*
96 /*
97 * This method adds axis to chartdataset, axis ownership is taken from caller.
97 * This method adds axis to chartdataset, axis ownership is taken from caller.
98 */
98 */
99 void ChartDataSet::addAxis(QAbstractAxis *axis, Qt::Alignment aligment)
99 void ChartDataSet::addAxis(QAbstractAxis *axis, Qt::Alignment aligment)
100 {
100 {
101 if (m_axisList.contains(axis)) {
101 if (m_axisList.contains(axis)) {
102 qWarning() << QObject::tr("Can not add axis. Axis already on the chart.");
102 qWarning() << QObject::tr("Can not add axis. Axis already on the chart.");
103 return;
103 return;
104 }
104 }
105
105
106 axis->d_ptr->setAlignment(aligment);
106 axis->d_ptr->setAlignment(aligment);
107
107
108 if (!axis->alignment()) {
108 if (!axis->alignment()) {
109 qWarning() << QObject::tr("No alignment specified !");
109 qWarning() << QObject::tr("No alignment specified !");
110 return;
110 return;
111 };
111 };
112
112
113 AbstractDomain *newDomain;
113 AbstractDomain *newDomain;
114 if (m_chart && m_chart->chartType() == QChart::ChartTypePolar)
114 if (m_chart && m_chart->chartType() == QChart::ChartTypePolar)
115 newDomain = new XYPolarDomain();
115 newDomain = new XYPolarDomain();
116 else
116 else
117 newDomain = new XYDomain();
117 newDomain = new XYDomain();
118
118
119 QSharedPointer<AbstractDomain> domain(newDomain);
119 QSharedPointer<AbstractDomain> domain(newDomain);
120 axis->d_ptr->initializeDomain(domain.data());
120 axis->d_ptr->initializeDomain(domain.data());
121
121
122 axis->setParent(this);
122 axis->setParent(this);
123 axis->d_ptr->m_chart = m_chart;
123 axis->d_ptr->m_chart = m_chart;
124 m_axisList.append(axis);
124 m_axisList.append(axis);
125
125
126 emit axisAdded(axis);
126 emit axisAdded(axis);
127 }
127 }
128
128
129 /*
129 /*
130 * This method removes series form chartdataset, series ownership is passed back to caller.
130 * This method removes series form chartdataset, series ownership is passed back to caller.
131 */
131 */
132 void ChartDataSet::removeSeries(QAbstractSeries *series)
132 void ChartDataSet::removeSeries(QAbstractSeries *series)
133 {
133 {
134
134
135 if (! m_seriesList.contains(series)) {
135 if (! m_seriesList.contains(series)) {
136 qWarning() << QObject::tr("Can not remove series. Series not found on the chart.");
136 qWarning() << QObject::tr("Can not remove series. Series not found on the chart.");
137 return;
137 return;
138 }
138 }
139
139
140 QList<QAbstractAxis*> axes = series->d_ptr->m_axes;
140 QList<QAbstractAxis*> axes = series->d_ptr->m_axes;
141
141
142 foreach(QAbstractAxis* axis, axes) {
142 foreach(QAbstractAxis* axis, axes) {
143 detachAxis(series,axis);
143 detachAxis(series,axis);
144 }
144 }
145
145
146 emit seriesRemoved(series);
146 emit seriesRemoved(series);
147 m_seriesList.removeAll(series);
147 m_seriesList.removeAll(series);
148
148
149 // Reset domain to default
149 // Reset domain to default
150 series->d_ptr->setDomain(new XYDomain());
150 series->d_ptr->setDomain(new XYDomain());
151 series->setParent(0);
151 series->setParent(0);
152 series->d_ptr->m_chart = 0;
152 series->d_ptr->m_chart = 0;
153 }
153 }
154
154
155 /*
155 /*
156 * This method removes axis form chartdataset, series ownership is passed back to caller.
156 * This method removes axis form chartdataset, series ownership is passed back to caller.
157 */
157 */
158 void ChartDataSet::removeAxis(QAbstractAxis *axis)
158 void ChartDataSet::removeAxis(QAbstractAxis *axis)
159 {
159 {
160 if (! m_axisList.contains(axis)) {
160 if (! m_axisList.contains(axis)) {
161 qWarning() << QObject::tr("Can not remove axis. Axis not found on the chart.");
161 qWarning() << QObject::tr("Can not remove axis. Axis not found on the chart.");
162 return;
162 return;
163 }
163 }
164
164
165 QList<QAbstractSeries*> series = axis->d_ptr->m_series;
165 QList<QAbstractSeries*> series = axis->d_ptr->m_series;
166
166
167 foreach(QAbstractSeries* s, series) {
167 foreach(QAbstractSeries* s, series) {
168 detachAxis(s,axis);
168 detachAxis(s,axis);
169 }
169 }
170
170
171 emit axisRemoved(axis);
171 emit axisRemoved(axis);
172 m_axisList.removeAll(axis);
172 m_axisList.removeAll(axis);
173
173
174 axis->setParent(0);
174 axis->setParent(0);
175 axis->d_ptr->m_chart = 0;
175 axis->d_ptr->m_chart = 0;
176 }
176 }
177
177
178 /*
178 /*
179 * This method attaches axis to series, return true if success.
179 * This method attaches axis to series, return true if success.
180 */
180 */
181 bool ChartDataSet::attachAxis(QAbstractSeries *series,QAbstractAxis *axis)
181 bool ChartDataSet::attachAxis(QAbstractSeries *series,QAbstractAxis *axis)
182 {
182 {
183 Q_ASSERT(series);
184 Q_ASSERT(axis);
183 Q_ASSERT(axis);
185
184
185 if (!series)
186 return false;
187
186 QList<QAbstractSeries *> attachedSeriesList = axis->d_ptr->m_series;
188 QList<QAbstractSeries *> attachedSeriesList = axis->d_ptr->m_series;
187 QList<QAbstractAxis *> attachedAxisList = series->d_ptr->m_axes;
189 QList<QAbstractAxis *> attachedAxisList = series->d_ptr->m_axes;
188
190
189 if (!m_seriesList.contains(series)) {
191 if (!m_seriesList.contains(series)) {
190 qWarning() << QObject::tr("Can not find series on the chart.");
192 qWarning() << QObject::tr("Can not find series on the chart.");
191 return false;
193 return false;
192 }
194 }
193
195
194 if (axis && !m_axisList.contains(axis)) {
196 if (axis && !m_axisList.contains(axis)) {
195 qWarning() << QObject::tr("Can not find axis on the chart.");
197 qWarning() << QObject::tr("Can not find axis on the chart.");
196 return false;
198 return false;
197 }
199 }
198
200
199 if (attachedAxisList.contains(axis)) {
201 if (attachedAxisList.contains(axis)) {
200 qWarning() << QObject::tr("Axis already attached to series.");
202 qWarning() << QObject::tr("Axis already attached to series.");
201 return false;
203 return false;
202 }
204 }
203
205
204 if (attachedSeriesList.contains(series)) {
206 if (attachedSeriesList.contains(series)) {
205 qWarning() << QObject::tr("Axis already attached to series.");
207 qWarning() << QObject::tr("Axis already attached to series.");
206 return false;
208 return false;
207 }
209 }
208
210
209 AbstractDomain *domain = series->d_ptr->domain();
211 AbstractDomain *domain = series->d_ptr->domain();
210 AbstractDomain::DomainType type = selectDomain(attachedAxisList<<axis);
212 AbstractDomain::DomainType type = selectDomain(attachedAxisList<<axis);
211
213
212 if (type == AbstractDomain::UndefinedDomain) return false;
214 if (type == AbstractDomain::UndefinedDomain) return false;
213
215
214 if (domain->type() != type) {
216 if (domain->type() != type) {
215 AbstractDomain *old = domain;
217 AbstractDomain *old = domain;
216 domain = createDomain(type);
218 domain = createDomain(type);
217 domain->setRange(old->minX(), old->maxX(), old->minY(), old->maxY());
219 domain->setRange(old->minX(), old->maxX(), old->minY(), old->maxY());
218 // Initialize domain size to old domain size, as it won't get updated
220 // Initialize domain size to old domain size, as it won't get updated
219 // unless geometry changes.
221 // unless geometry changes.
220 domain->setSize(old->size());
222 domain->setSize(old->size());
221 }
223 }
222
224
223 if (!domain)
225 if (!domain)
224 return false;
226 return false;
225
227
226 if (!domain->attachAxis(axis))
228 if (!domain->attachAxis(axis))
227 return false;
229 return false;
228
230
229 QList<AbstractDomain *> blockedDomains;
231 QList<AbstractDomain *> blockedDomains;
230 domain->blockRangeSignals(true);
232 domain->blockRangeSignals(true);
231 blockedDomains << domain;
233 blockedDomains << domain;
232
234
233 if (domain != series->d_ptr->domain()) {
235 if (domain != series->d_ptr->domain()) {
234 foreach (QAbstractAxis *axis, series->d_ptr->m_axes) {
236 foreach (QAbstractAxis *axis, series->d_ptr->m_axes) {
235 series->d_ptr->domain()->detachAxis(axis);
237 series->d_ptr->domain()->detachAxis(axis);
236 domain->attachAxis(axis);
238 domain->attachAxis(axis);
237 foreach (QAbstractSeries *otherSeries, axis->d_ptr->m_series) {
239 foreach (QAbstractSeries *otherSeries, axis->d_ptr->m_series) {
238 if (otherSeries != series && otherSeries->d_ptr->domain()) {
240 if (otherSeries != series && otherSeries->d_ptr->domain()) {
239 if (!otherSeries->d_ptr->domain()->rangeSignalsBlocked()) {
241 if (!otherSeries->d_ptr->domain()->rangeSignalsBlocked()) {
240 otherSeries->d_ptr->domain()->blockRangeSignals(true);
242 otherSeries->d_ptr->domain()->blockRangeSignals(true);
241 blockedDomains << otherSeries->d_ptr->domain();
243 blockedDomains << otherSeries->d_ptr->domain();
242 }
244 }
243 }
245 }
244 }
246 }
245 }
247 }
246 series->d_ptr->setDomain(domain);
248 series->d_ptr->setDomain(domain);
247 series->d_ptr->initializeDomain();
249 series->d_ptr->initializeDomain();
248 }
250 }
249
251
250 series->d_ptr->m_axes<<axis;
252 series->d_ptr->m_axes<<axis;
251 axis->d_ptr->m_series<<series;
253 axis->d_ptr->m_series<<series;
252
254
253 series->d_ptr->initializeAxes();
255 series->d_ptr->initializeAxes();
254 axis->d_ptr->initializeDomain(domain);
256 axis->d_ptr->initializeDomain(domain);
255
257
256 foreach (AbstractDomain *blockedDomain, blockedDomains)
258 foreach (AbstractDomain *blockedDomain, blockedDomains)
257 blockedDomain->blockRangeSignals(false);
259 blockedDomain->blockRangeSignals(false);
258
260
259 return true;
261 return true;
260 }
262 }
261
263
262 /*
264 /*
263 * This method detaches axis to series, return true if success.
265 * This method detaches axis to series, return true if success.
264 */
266 */
265 bool ChartDataSet::detachAxis(QAbstractSeries* series,QAbstractAxis *axis)
267 bool ChartDataSet::detachAxis(QAbstractSeries* series,QAbstractAxis *axis)
266 {
268 {
267 Q_ASSERT(series);
269 Q_ASSERT(series);
268 Q_ASSERT(axis);
270 Q_ASSERT(axis);
269
271
270 QList<QAbstractSeries* > attachedSeriesList = axis->d_ptr->m_series;
272 QList<QAbstractSeries* > attachedSeriesList = axis->d_ptr->m_series;
271 QList<QAbstractAxis* > attachedAxisList = series->d_ptr->m_axes;
273 QList<QAbstractAxis* > attachedAxisList = series->d_ptr->m_axes;
272 AbstractDomain* domain = series->d_ptr->domain();
274 AbstractDomain* domain = series->d_ptr->domain();
273
275
274 if (!m_seriesList.contains(series)) {
276 if (!m_seriesList.contains(series)) {
275 qWarning() << QObject::tr("Can not find series on the chart.");
277 qWarning() << QObject::tr("Can not find series on the chart.");
276 return false;
278 return false;
277 }
279 }
278
280
279 if (axis && !m_axisList.contains(axis)) {
281 if (axis && !m_axisList.contains(axis)) {
280 qWarning() << QObject::tr("Can not find axis on the chart.");
282 qWarning() << QObject::tr("Can not find axis on the chart.");
281 return false;
283 return false;
282 }
284 }
283
285
284 if (!attachedAxisList.contains(axis)) {
286 if (!attachedAxisList.contains(axis)) {
285 qWarning() << QObject::tr("Axis not attached to series.");
287 qWarning() << QObject::tr("Axis not attached to series.");
286 return false;
288 return false;
287 }
289 }
288
290
289 Q_ASSERT(axis->d_ptr->m_series.contains(series));
291 Q_ASSERT(axis->d_ptr->m_series.contains(series));
290
292
291 domain->detachAxis(axis);
293 domain->detachAxis(axis);
292 series->d_ptr->m_axes.removeAll(axis);
294 series->d_ptr->m_axes.removeAll(axis);
293 axis->d_ptr->m_series.removeAll(series);
295 axis->d_ptr->m_series.removeAll(series);
294
296
295 return true;
297 return true;
296 }
298 }
297
299
298 void ChartDataSet::createDefaultAxes()
300 void ChartDataSet::createDefaultAxes()
299 {
301 {
300 if (m_seriesList.isEmpty())
302 if (m_seriesList.isEmpty())
301 return;
303 return;
302
304
303 QAbstractAxis::AxisTypes typeX(0);
305 QAbstractAxis::AxisTypes typeX(0);
304 QAbstractAxis::AxisTypes typeY(0);
306 QAbstractAxis::AxisTypes typeY(0);
305
307
306 // Remove possibly existing axes
308 // Remove possibly existing axes
307 deleteAllAxes();
309 deleteAllAxes();
308
310
309 Q_ASSERT(m_axisList.isEmpty());
311 Q_ASSERT(m_axisList.isEmpty());
310
312
311 // Select the required axis x and axis y types based on the types of the current series
313 // Select the required axis x and axis y types based on the types of the current series
312 foreach(QAbstractSeries* s, m_seriesList) {
314 foreach(QAbstractSeries* s, m_seriesList) {
313 typeX |= s->d_ptr->defaultAxisType(Qt::Horizontal);
315 typeX |= s->d_ptr->defaultAxisType(Qt::Horizontal);
314 typeY |= s->d_ptr->defaultAxisType(Qt::Vertical);
316 typeY |= s->d_ptr->defaultAxisType(Qt::Vertical);
315 }
317 }
316
318
317 // Create the axes of the types selected
319 // Create the axes of the types selected
318 // As long as AxisType enum balues are sequential a check to see if there are series of
320 // As long as AxisType enum balues are sequential a check to see if there are series of
319 // different types is needed. In such cases AxisTypeNoAxis is used to create separate axes
321 // different types is needed. In such cases AxisTypeNoAxis is used to create separate axes
320 // for the types.
322 // for the types.
321 if (typeX != QAbstractAxis::AxisTypeNoAxis) {
323 if (typeX != QAbstractAxis::AxisTypeNoAxis) {
322 if (typeX != m_seriesList.first()->d_ptr->defaultAxisType(Qt::Horizontal))
324 if (typeX != m_seriesList.first()->d_ptr->defaultAxisType(Qt::Horizontal))
323 typeX = QAbstractAxis::AxisTypeNoAxis;
325 typeX = QAbstractAxis::AxisTypeNoAxis;
324 createAxes(typeX, Qt::Horizontal);
326 createAxes(typeX, Qt::Horizontal);
325 }
327 }
326
328
327 if (typeY != QAbstractAxis::AxisTypeNoAxis) {
329 if (typeY != QAbstractAxis::AxisTypeNoAxis) {
328 if (typeY != m_seriesList.first()->d_ptr->defaultAxisType(Qt::Vertical))
330 if (typeY != m_seriesList.first()->d_ptr->defaultAxisType(Qt::Vertical))
329 typeY = QAbstractAxis::AxisTypeNoAxis;
331 typeY = QAbstractAxis::AxisTypeNoAxis;
330 createAxes(typeY, Qt::Vertical);
332 createAxes(typeY, Qt::Vertical);
331 }
333 }
332
334
333 }
335 }
334
336
335 void ChartDataSet::createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation)
337 void ChartDataSet::createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation)
336 {
338 {
337 QAbstractAxis *axis = 0;
339 QAbstractAxis *axis = 0;
338 //decide what axis should be created
340 //decide what axis should be created
339
341
340 switch (type) {
342 switch (type) {
341 case QAbstractAxis::AxisTypeValue:
343 case QAbstractAxis::AxisTypeValue:
342 axis = new QValueAxis(this);
344 axis = new QValueAxis(this);
343 break;
345 break;
344 case QAbstractAxis::AxisTypeBarCategory:
346 case QAbstractAxis::AxisTypeBarCategory:
345 axis = new QBarCategoryAxis(this);
347 axis = new QBarCategoryAxis(this);
346 break;
348 break;
347 case QAbstractAxis::AxisTypeCategory:
349 case QAbstractAxis::AxisTypeCategory:
348 axis = new QCategoryAxis(this);
350 axis = new QCategoryAxis(this);
349 break;
351 break;
350 #ifndef Q_WS_QWS
352 #ifndef Q_WS_QWS
351 case QAbstractAxis::AxisTypeDateTime:
353 case QAbstractAxis::AxisTypeDateTime:
352 axis = new QDateTimeAxis(this);
354 axis = new QDateTimeAxis(this);
353 break;
355 break;
354 #endif
356 #endif
355 default:
357 default:
356 axis = 0;
358 axis = 0;
357 break;
359 break;
358 }
360 }
359
361
360 if (axis) {
362 if (axis) {
361 //create one axis for all
363 //create one axis for all
362
364
363 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
365 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
364 qreal min = 0;
366 qreal min = 0;
365 qreal max = 0;
367 qreal max = 0;
366 findMinMaxForSeries(m_seriesList,orientation,min,max);
368 findMinMaxForSeries(m_seriesList,orientation,min,max);
367 foreach(QAbstractSeries *s, m_seriesList) {
369 foreach(QAbstractSeries *s, m_seriesList) {
368 attachAxis(s,axis);
370 attachAxis(s,axis);
369 }
371 }
370 axis->setRange(min,max);
372 axis->setRange(min,max);
371 }
373 }
372 else if (type.testFlag(QAbstractAxis::AxisTypeNoAxis)) {
374 else if (type.testFlag(QAbstractAxis::AxisTypeNoAxis)) {
373 //create separate axis
375 //create separate axis
374 foreach(QAbstractSeries *s, m_seriesList) {
376 foreach(QAbstractSeries *s, m_seriesList) {
375 QAbstractAxis *axis = s->d_ptr->createDefaultAxis(orientation);
377 QAbstractAxis *axis = s->d_ptr->createDefaultAxis(orientation);
376 if(axis) {
378 if(axis) {
377 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
379 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
378 attachAxis(s,axis);
380 attachAxis(s,axis);
379 }
381 }
380 }
382 }
381 }
383 }
382 }
384 }
383
385
384 void ChartDataSet::findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orientations orientation, qreal &min, qreal &max)
386 void ChartDataSet::findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orientations orientation, qreal &min, qreal &max)
385 {
387 {
386 Q_ASSERT(!series.isEmpty());
388 Q_ASSERT(!series.isEmpty());
387
389
388 AbstractDomain *domain = series.first()->d_ptr->domain();
390 AbstractDomain *domain = series.first()->d_ptr->domain();
389 min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
391 min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
390 max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
392 max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
391
393
392 for (int i = 1; i< series.size(); i++) {
394 for (int i = 1; i< series.size(); i++) {
393 AbstractDomain *domain = series[i]->d_ptr->domain();
395 AbstractDomain *domain = series[i]->d_ptr->domain();
394 min = qMin((orientation == Qt::Vertical) ? domain->minY() : domain->minX(), min);
396 min = qMin((orientation == Qt::Vertical) ? domain->minY() : domain->minX(), min);
395 max = qMax((orientation == Qt::Vertical) ? domain->maxY() : domain->maxX(), max);
397 max = qMax((orientation == Qt::Vertical) ? domain->maxY() : domain->maxX(), max);
396 }
398 }
397 if (min == max) {
399 if (min == max) {
398 min -= 0.5;
400 min -= 0.5;
399 max += 0.5;
401 max += 0.5;
400 }
402 }
401 }
403 }
402
404
403 void ChartDataSet::deleteAllSeries()
405 void ChartDataSet::deleteAllSeries()
404 {
406 {
405 foreach (QAbstractSeries *s , m_seriesList){
407 foreach (QAbstractSeries *s , m_seriesList){
406 removeSeries(s);
408 removeSeries(s);
407 s->deleteLater();
409 s->deleteLater();
408 }
410 }
409 Q_ASSERT(m_seriesList.count() == 0);
411 Q_ASSERT(m_seriesList.count() == 0);
410 }
412 }
411
413
412 void ChartDataSet::deleteAllAxes()
414 void ChartDataSet::deleteAllAxes()
413 {
415 {
414 foreach (QAbstractAxis *a , m_axisList){
416 foreach (QAbstractAxis *a , m_axisList){
415 removeAxis(a);
417 removeAxis(a);
416 a->deleteLater();
418 a->deleteLater();
417 }
419 }
418 Q_ASSERT(m_axisList.count() == 0);
420 Q_ASSERT(m_axisList.count() == 0);
419 }
421 }
420
422
421 void ChartDataSet::zoomInDomain(const QRectF &rect)
423 void ChartDataSet::zoomInDomain(const QRectF &rect)
422 {
424 {
423 QList<AbstractDomain*> domains;
425 QList<AbstractDomain*> domains;
424 foreach(QAbstractSeries *s, m_seriesList) {
426 foreach(QAbstractSeries *s, m_seriesList) {
425 AbstractDomain* domain = s->d_ptr->domain();
427 AbstractDomain* domain = s->d_ptr->domain();
426 s->d_ptr->m_domain->blockRangeSignals(true);
428 s->d_ptr->m_domain->blockRangeSignals(true);
427 domains<<domain;
429 domains<<domain;
428 }
430 }
429
431
430 foreach(AbstractDomain *domain, domains)
432 foreach(AbstractDomain *domain, domains)
431 domain->zoomIn(rect);
433 domain->zoomIn(rect);
432
434
433 foreach(AbstractDomain *domain, domains)
435 foreach(AbstractDomain *domain, domains)
434 domain->blockRangeSignals(false);
436 domain->blockRangeSignals(false);
435 }
437 }
436
438
437 void ChartDataSet::zoomOutDomain(const QRectF &rect)
439 void ChartDataSet::zoomOutDomain(const QRectF &rect)
438 {
440 {
439 QList<AbstractDomain*> domains;
441 QList<AbstractDomain*> domains;
440 foreach(QAbstractSeries *s, m_seriesList) {
442 foreach(QAbstractSeries *s, m_seriesList) {
441 AbstractDomain* domain = s->d_ptr->domain();
443 AbstractDomain* domain = s->d_ptr->domain();
442 s->d_ptr->m_domain->blockRangeSignals(true);
444 s->d_ptr->m_domain->blockRangeSignals(true);
443 domains<<domain;
445 domains<<domain;
444 }
446 }
445
447
446 foreach(AbstractDomain *domain, domains)
448 foreach(AbstractDomain *domain, domains)
447 domain->zoomOut(rect);
449 domain->zoomOut(rect);
448
450
449 foreach(AbstractDomain *domain, domains)
451 foreach(AbstractDomain *domain, domains)
450 domain->blockRangeSignals(false);
452 domain->blockRangeSignals(false);
451 }
453 }
452
454
453 void ChartDataSet::zoomResetDomain()
455 void ChartDataSet::zoomResetDomain()
454 {
456 {
455 QList<AbstractDomain*> domains;
457 QList<AbstractDomain*> domains;
456 foreach (QAbstractSeries *s, m_seriesList) {
458 foreach (QAbstractSeries *s, m_seriesList) {
457 AbstractDomain *domain = s->d_ptr->domain();
459 AbstractDomain *domain = s->d_ptr->domain();
458 s->d_ptr->m_domain->blockRangeSignals(true);
460 s->d_ptr->m_domain->blockRangeSignals(true);
459 domains << domain;
461 domains << domain;
460 }
462 }
461
463
462 foreach (AbstractDomain *domain, domains)
464 foreach (AbstractDomain *domain, domains)
463 domain->zoomReset();
465 domain->zoomReset();
464
466
465 foreach (AbstractDomain *domain, domains)
467 foreach (AbstractDomain *domain, domains)
466 domain->blockRangeSignals(false);
468 domain->blockRangeSignals(false);
467 }
469 }
468
470
469 bool ChartDataSet::isZoomedDomain()
471 bool ChartDataSet::isZoomedDomain()
470 {
472 {
471 foreach (QAbstractSeries *s, m_seriesList) {
473 foreach (QAbstractSeries *s, m_seriesList) {
472 if (s->d_ptr->domain()->isZoomed())
474 if (s->d_ptr->domain()->isZoomed())
473 return true;
475 return true;
474 }
476 }
475 return false;
477 return false;
476 }
478 }
477
479
478 void ChartDataSet::scrollDomain(qreal dx, qreal dy)
480 void ChartDataSet::scrollDomain(qreal dx, qreal dy)
479 {
481 {
480 QList<AbstractDomain*> domains;
482 QList<AbstractDomain*> domains;
481 foreach(QAbstractSeries *s, m_seriesList) {
483 foreach(QAbstractSeries *s, m_seriesList) {
482 AbstractDomain* domain = s->d_ptr->domain();
484 AbstractDomain* domain = s->d_ptr->domain();
483 s->d_ptr->m_domain->blockRangeSignals(true);
485 s->d_ptr->m_domain->blockRangeSignals(true);
484 domains<<domain;
486 domains<<domain;
485 }
487 }
486
488
487 foreach(AbstractDomain *domain, domains)
489 foreach(AbstractDomain *domain, domains)
488 domain->move(dx, dy);
490 domain->move(dx, dy);
489
491
490 foreach(AbstractDomain *domain, domains)
492 foreach(AbstractDomain *domain, domains)
491 domain->blockRangeSignals(false);
493 domain->blockRangeSignals(false);
492 }
494 }
493
495
494 QPointF ChartDataSet::mapToValue(const QPointF &position, QAbstractSeries *series)
496 QPointF ChartDataSet::mapToValue(const QPointF &position, QAbstractSeries *series)
495 {
497 {
496 QPointF point;
498 QPointF point;
497 if (series == 0 && !m_seriesList.isEmpty())
499 if (series == 0 && !m_seriesList.isEmpty())
498 series = m_seriesList.first();
500 series = m_seriesList.first();
499
501
500 if (series && series->type() == QAbstractSeries::SeriesTypePie)
502 if (series && series->type() == QAbstractSeries::SeriesTypePie)
501 return point;
503 return point;
502
504
503 if (series && m_seriesList.contains(series))
505 if (series && m_seriesList.contains(series))
504 point = series->d_ptr->m_domain->calculateDomainPoint(position - m_chart->plotArea().topLeft());
506 point = series->d_ptr->m_domain->calculateDomainPoint(position - m_chart->plotArea().topLeft());
505 return point;
507 return point;
506 }
508 }
507
509
508 QPointF ChartDataSet::mapToPosition(const QPointF &value, QAbstractSeries *series)
510 QPointF ChartDataSet::mapToPosition(const QPointF &value, QAbstractSeries *series)
509 {
511 {
510 QPointF point = m_chart->plotArea().topLeft();
512 QPointF point = m_chart->plotArea().topLeft();
511 if (series == 0 && !m_seriesList.isEmpty())
513 if (series == 0 && !m_seriesList.isEmpty())
512 series = m_seriesList.first();
514 series = m_seriesList.first();
513
515
514 if (series && series->type() == QAbstractSeries::SeriesTypePie)
516 if (series && series->type() == QAbstractSeries::SeriesTypePie)
515 return QPoint(0, 0);
517 return QPoint(0, 0);
516
518
517 bool ok;
519 bool ok;
518 if (series && m_seriesList.contains(series))
520 if (series && m_seriesList.contains(series))
519 point += series->d_ptr->m_domain->calculateGeometryPoint(value, ok);
521 point += series->d_ptr->m_domain->calculateGeometryPoint(value, ok);
520 return point;
522 return point;
521 }
523 }
522
524
523 QList<QAbstractAxis *> ChartDataSet::axes() const
525 QList<QAbstractAxis *> ChartDataSet::axes() const
524 {
526 {
525 return m_axisList;
527 return m_axisList;
526 }
528 }
527
529
528 QList<QAbstractSeries *> ChartDataSet::series() const
530 QList<QAbstractSeries *> ChartDataSet::series() const
529 {
531 {
530 return m_seriesList;
532 return m_seriesList;
531 }
533 }
532
534
533 AbstractDomain::DomainType ChartDataSet::selectDomain(QList<QAbstractAxis *> axes)
535 AbstractDomain::DomainType ChartDataSet::selectDomain(QList<QAbstractAxis *> axes)
534 {
536 {
535 enum Type {
537 enum Type {
536 Undefined = 0,
538 Undefined = 0,
537 LogType = 0x1,
539 LogType = 0x1,
538 ValueType = 0x2
540 ValueType = 0x2
539 };
541 };
540
542
541 int horizontal(Undefined);
543 int horizontal(Undefined);
542 int vertical(Undefined);
544 int vertical(Undefined);
543
545
544 // Assume cartesian chart type, unless chart is set
546 // Assume cartesian chart type, unless chart is set
545 QChart::ChartType chartType(QChart::ChartTypeCartesian);
547 QChart::ChartType chartType(QChart::ChartTypeCartesian);
546 if (m_chart)
548 if (m_chart)
547 chartType = m_chart->chartType();
549 chartType = m_chart->chartType();
548
550
549 foreach (QAbstractAxis *axis, axes)
551 foreach (QAbstractAxis *axis, axes)
550 {
552 {
551 switch (axis->type()) {
553 switch (axis->type()) {
552 case QAbstractAxis::AxisTypeLogValue:
554 case QAbstractAxis::AxisTypeLogValue:
553 if (axis->orientation() == Qt::Horizontal)
555 if (axis->orientation() == Qt::Horizontal)
554 horizontal |= LogType;
556 horizontal |= LogType;
555 if (axis->orientation() == Qt::Vertical)
557 if (axis->orientation() == Qt::Vertical)
556 vertical |= LogType;
558 vertical |= LogType;
557 break;
559 break;
558 case QAbstractAxis::AxisTypeValue:
560 case QAbstractAxis::AxisTypeValue:
559 case QAbstractAxis::AxisTypeBarCategory:
561 case QAbstractAxis::AxisTypeBarCategory:
560 case QAbstractAxis::AxisTypeCategory:
562 case QAbstractAxis::AxisTypeCategory:
561 case QAbstractAxis::AxisTypeDateTime:
563 case QAbstractAxis::AxisTypeDateTime:
562 if (axis->orientation() == Qt::Horizontal)
564 if (axis->orientation() == Qt::Horizontal)
563 horizontal |= ValueType;
565 horizontal |= ValueType;
564 if (axis->orientation() == Qt::Vertical)
566 if (axis->orientation() == Qt::Vertical)
565 vertical |= ValueType;
567 vertical |= ValueType;
566 break;
568 break;
567 default:
569 default:
568 qWarning() << "Undefined type";
570 qWarning() << "Undefined type";
569 break;
571 break;
570 }
572 }
571 }
573 }
572
574
573 if (vertical == Undefined)
575 if (vertical == Undefined)
574 vertical = ValueType;
576 vertical = ValueType;
575 if (horizontal == Undefined)
577 if (horizontal == Undefined)
576 horizontal = ValueType;
578 horizontal = ValueType;
577
579
578 if (vertical == ValueType && horizontal == ValueType) {
580 if (vertical == ValueType && horizontal == ValueType) {
579 if (chartType == QChart::ChartTypeCartesian)
581 if (chartType == QChart::ChartTypeCartesian)
580 return AbstractDomain::XYDomain;
582 return AbstractDomain::XYDomain;
581 else if (chartType == QChart::ChartTypePolar)
583 else if (chartType == QChart::ChartTypePolar)
582 return AbstractDomain::XYPolarDomain;
584 return AbstractDomain::XYPolarDomain;
583 }
585 }
584
586
585 if (vertical == LogType && horizontal == ValueType) {
587 if (vertical == LogType && horizontal == ValueType) {
586 if (chartType == QChart::ChartTypeCartesian)
588 if (chartType == QChart::ChartTypeCartesian)
587 return AbstractDomain::XLogYDomain;
589 return AbstractDomain::XLogYDomain;
588 if (chartType == QChart::ChartTypePolar)
590 if (chartType == QChart::ChartTypePolar)
589 return AbstractDomain::XLogYPolarDomain;
591 return AbstractDomain::XLogYPolarDomain;
590 }
592 }
591
593
592 if (vertical == ValueType && horizontal == LogType) {
594 if (vertical == ValueType && horizontal == LogType) {
593 if (chartType == QChart::ChartTypeCartesian)
595 if (chartType == QChart::ChartTypeCartesian)
594 return AbstractDomain::LogXYDomain;
596 return AbstractDomain::LogXYDomain;
595 else if (chartType == QChart::ChartTypePolar)
597 else if (chartType == QChart::ChartTypePolar)
596 return AbstractDomain::LogXYPolarDomain;
598 return AbstractDomain::LogXYPolarDomain;
597 }
599 }
598
600
599 if (vertical == LogType && horizontal == LogType) {
601 if (vertical == LogType && horizontal == LogType) {
600 if (chartType == QChart::ChartTypeCartesian)
602 if (chartType == QChart::ChartTypeCartesian)
601 return AbstractDomain::LogXLogYDomain;
603 return AbstractDomain::LogXLogYDomain;
602 else if (chartType == QChart::ChartTypePolar)
604 else if (chartType == QChart::ChartTypePolar)
603 return AbstractDomain::LogXLogYPolarDomain;
605 return AbstractDomain::LogXLogYPolarDomain;
604 }
606 }
605
607
606 return AbstractDomain::UndefinedDomain;
608 return AbstractDomain::UndefinedDomain;
607 }
609 }
608
610
609 //refactor create factory
611 //refactor create factory
610 AbstractDomain* ChartDataSet::createDomain(AbstractDomain::DomainType type)
612 AbstractDomain* ChartDataSet::createDomain(AbstractDomain::DomainType type)
611 {
613 {
612 switch (type)
614 switch (type)
613 {
615 {
614 case AbstractDomain::LogXLogYDomain:
616 case AbstractDomain::LogXLogYDomain:
615 return new LogXLogYDomain();
617 return new LogXLogYDomain();
616 case AbstractDomain::XYDomain:
618 case AbstractDomain::XYDomain:
617 return new XYDomain();
619 return new XYDomain();
618 case AbstractDomain::XLogYDomain:
620 case AbstractDomain::XLogYDomain:
619 return new XLogYDomain();
621 return new XLogYDomain();
620 case AbstractDomain::LogXYDomain:
622 case AbstractDomain::LogXYDomain:
621 return new LogXYDomain();
623 return new LogXYDomain();
622 case AbstractDomain::XYPolarDomain:
624 case AbstractDomain::XYPolarDomain:
623 return new XYPolarDomain();
625 return new XYPolarDomain();
624 case AbstractDomain::XLogYPolarDomain:
626 case AbstractDomain::XLogYPolarDomain:
625 return new XLogYPolarDomain();
627 return new XLogYPolarDomain();
626 case AbstractDomain::LogXYPolarDomain:
628 case AbstractDomain::LogXYPolarDomain:
627 return new LogXYPolarDomain();
629 return new LogXYPolarDomain();
628 case AbstractDomain::LogXLogYPolarDomain:
630 case AbstractDomain::LogXLogYPolarDomain:
629 return new LogXLogYPolarDomain();
631 return new LogXLogYPolarDomain();
630 default:
632 default:
631 return 0;
633 return 0;
632 }
634 }
633 }
635 }
634
636
635 #include "moc_chartdataset_p.cpp"
637 #include "moc_chartdataset_p.cpp"
636
638
637 QTCOMMERCIALCHART_END_NAMESPACE
639 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now