##// END OF EJS Templates
Bugfix resize event during zoomin
Michal Klocek -
r2289:d4cb0061d8bc
parent child
Show More
@@ -1,482 +1,481
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 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 Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and 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 "xlogydomain_p.h"
36 #include "xlogydomain_p.h"
37 #include "logxydomain_p.h"
37 #include "logxydomain_p.h"
38 #include "logxlogydomain_p.h"
38 #include "logxlogydomain_p.h"
39
39
40 #ifndef QT_ON_ARM
40 #ifndef QT_ON_ARM
41 #include "qdatetimeaxis.h"
41 #include "qdatetimeaxis.h"
42 #endif
42 #endif
43
43
44 QTCOMMERCIALCHART_BEGIN_NAMESPACE
44 QTCOMMERCIALCHART_BEGIN_NAMESPACE
45
45
46 ChartDataSet::ChartDataSet(QChart *chart)
46 ChartDataSet::ChartDataSet(QChart *chart)
47 : QObject(chart),
47 : QObject(chart),
48 m_chart(chart)
48 m_chart(chart)
49 {
49 {
50
50
51 }
51 }
52
52
53 ChartDataSet::~ChartDataSet()
53 ChartDataSet::~ChartDataSet()
54 {
54 {
55 deleteAllSeries();
55 deleteAllSeries();
56 deleteAllAxes();
56 deleteAllAxes();
57 }
57 }
58
58
59 /*
59 /*
60 * This method adds series to chartdataset, series ownership is taken from caller.
60 * This method adds series to chartdataset, series ownership is taken from caller.
61 */
61 */
62 void ChartDataSet::addSeries(QAbstractSeries *series)
62 void ChartDataSet::addSeries(QAbstractSeries *series)
63 {
63 {
64 if (m_seriesList.contains(series)) {
64 if (m_seriesList.contains(series)) {
65 qWarning() << QObject::tr("Can not add series. Series already on the chart.");
65 qWarning() << QObject::tr("Can not add series. Series already on the chart.");
66 return;
66 return;
67 }
67 }
68
68
69 series->d_ptr->initializeDomain();
69 series->d_ptr->initializeDomain();
70 m_seriesList.append(series);
70 m_seriesList.append(series);
71
71
72 series->setParent(this); // take ownership
72 series->setParent(this); // take ownership
73 series->d_ptr->m_chart = m_chart;
73 series->d_ptr->m_chart = m_chart;
74
74
75 emit seriesAdded(series);
75 emit seriesAdded(series);
76 }
76 }
77
77
78 /*
78 /*
79 * This method adds axis to chartdataset, axis ownership is taken from caller.
79 * This method adds axis to chartdataset, axis ownership is taken from caller.
80 */
80 */
81 void ChartDataSet::addAxis(QAbstractAxis *axis,Qt::Alignment aligment)
81 void ChartDataSet::addAxis(QAbstractAxis *axis,Qt::Alignment aligment)
82 {
82 {
83 if (m_axisList.contains(axis)) {
83 if (m_axisList.contains(axis)) {
84 qWarning() << QObject::tr("Can not add axis. Axis already on the chart.");
84 qWarning() << QObject::tr("Can not add axis. Axis already on the chart.");
85 return;
85 return;
86 }
86 }
87
87
88 axis->d_ptr->setAlignment(aligment);
88 axis->d_ptr->setAlignment(aligment);
89
89
90 if(!axis->alignment()) {
90 if(!axis->alignment()) {
91 qWarning()<< QObject::tr("No alignment specified !");
91 qWarning()<< QObject::tr("No alignment specified !");
92 return;
92 return;
93 };
93 };
94
94
95 QSharedPointer<AbstractDomain> domain(new XYDomain());
95 QSharedPointer<AbstractDomain> domain(new XYDomain());
96 axis->d_ptr->initializeDomain(domain.data());
96 axis->d_ptr->initializeDomain(domain.data());
97
97
98 axis->setParent(this);
98 axis->setParent(this);
99 axis->d_ptr->m_chart = m_chart;
99 axis->d_ptr->m_chart = m_chart;
100 m_axisList.append(axis);
100 m_axisList.append(axis);
101
101
102 emit axisAdded(axis);
102 emit axisAdded(axis);
103 }
103 }
104
104
105 /*
105 /*
106 * This method removes series form chartdataset, series ownership is passed back to caller.
106 * This method removes series form chartdataset, series ownership is passed back to caller.
107 */
107 */
108 void ChartDataSet::removeSeries(QAbstractSeries *series)
108 void ChartDataSet::removeSeries(QAbstractSeries *series)
109 {
109 {
110
110
111 if (! m_seriesList.contains(series)) {
111 if (! m_seriesList.contains(series)) {
112 qWarning() << QObject::tr("Can not remove series. Series not found on the chart.");
112 qWarning() << QObject::tr("Can not remove series. Series not found on the chart.");
113 return;
113 return;
114 }
114 }
115
115
116 emit seriesRemoved(series);
116 emit seriesRemoved(series);
117 m_seriesList.removeAll(series);
117 m_seriesList.removeAll(series);
118
118
119 series->setParent(0);
119 series->setParent(0);
120 series->d_ptr->m_chart = 0;
120 series->d_ptr->m_chart = 0;
121 series->d_ptr->m_domain.reset(0);
121 series->d_ptr->m_domain.reset(0);
122
122
123 QList<QAbstractAxis*> axes = series->d_ptr->m_axes;
123 QList<QAbstractAxis*> axes = series->d_ptr->m_axes;
124
124
125 foreach(QAbstractAxis* axis, axes) {
125 foreach(QAbstractAxis* axis, axes) {
126 axis->d_ptr->m_series.removeAll(series);
126 axis->d_ptr->m_series.removeAll(series);
127 series->d_ptr->m_axes.removeAll(axis);
127 series->d_ptr->m_axes.removeAll(axis);
128 }
128 }
129
129
130 }
130 }
131
131
132 /*
132 /*
133 * This method removes axis form chartdataset, series ownership is passed back to caller.
133 * This method removes axis form chartdataset, series ownership is passed back to caller.
134 */
134 */
135 void ChartDataSet::removeAxis(QAbstractAxis *axis)
135 void ChartDataSet::removeAxis(QAbstractAxis *axis)
136 {
136 {
137 if (! m_axisList.contains(axis)) {
137 if (! m_axisList.contains(axis)) {
138 qWarning() << QObject::tr("Can not remove axis. Axis not found on the chart.");
138 qWarning() << QObject::tr("Can not remove axis. Axis not found on the chart.");
139 return;
139 return;
140 }
140 }
141
141
142 emit axisRemoved(axis);
142 emit axisRemoved(axis);
143 m_axisList.removeAll(axis);
143 m_axisList.removeAll(axis);
144
144
145 axis->setParent(0);
145 axis->setParent(0);
146 axis->d_ptr->m_chart = 0;
146 axis->d_ptr->m_chart = 0;
147
147
148 QList<QAbstractSeries*> series = axis->d_ptr->m_series;
148 QList<QAbstractSeries*> series = axis->d_ptr->m_series;
149
149
150 foreach(QAbstractSeries* s, series) {
150 foreach(QAbstractSeries* s, series) {
151 s->d_ptr->m_axes.removeAll(axis);
151 s->d_ptr->m_axes.removeAll(axis);
152 axis->d_ptr->m_series.removeAll(s);
152 axis->d_ptr->m_series.removeAll(s);
153 }
153 }
154 }
154 }
155
155
156 /*
156 /*
157 * This method attaches axis to series, return true if success.
157 * This method attaches axis to series, return true if success.
158 */
158 */
159 bool ChartDataSet::attachAxis(QAbstractSeries* series,QAbstractAxis *axis)
159 bool ChartDataSet::attachAxis(QAbstractSeries* series,QAbstractAxis *axis)
160 {
160 {
161 Q_ASSERT(series);
161 Q_ASSERT(series);
162 Q_ASSERT(axis);
162 Q_ASSERT(axis);
163
163
164 QList<QAbstractSeries* > attachedSeriesList = axis->d_ptr->m_series;
164 QList<QAbstractSeries* > attachedSeriesList = axis->d_ptr->m_series;
165 QList<QAbstractAxis* > attachedAxisList = series->d_ptr->m_axes;
165 QList<QAbstractAxis* > attachedAxisList = series->d_ptr->m_axes;
166
166
167 if (!m_seriesList.contains(series)) {
167 if (!m_seriesList.contains(series)) {
168 qWarning() << QObject::tr("Can not find series on the chart.");
168 qWarning() << QObject::tr("Can not find series on the chart.");
169 return false;
169 return false;
170 }
170 }
171
171
172 if (axis && !m_axisList.contains(axis)) {
172 if (axis && !m_axisList.contains(axis)) {
173 qWarning() << QObject::tr("Can not find axis on the chart.");
173 qWarning() << QObject::tr("Can not find axis on the chart.");
174 return false;
174 return false;
175 }
175 }
176
176
177 if (attachedAxisList.contains(axis)) {
177 if (attachedAxisList.contains(axis)) {
178 qWarning() << QObject::tr("Axis already attached to series.");
178 qWarning() << QObject::tr("Axis already attached to series.");
179 return false;
179 return false;
180 }
180 }
181
181
182 if (attachedSeriesList.contains(series)) {
182 if (attachedSeriesList.contains(series)) {
183 qWarning() << QObject::tr("Axis already attached to series.");
183 qWarning() << QObject::tr("Axis already attached to series.");
184 return false;
184 return false;
185 }
185 }
186
186
187 AbstractDomain* domain = series->d_ptr->domain();
187 AbstractDomain* domain = series->d_ptr->domain();
188 AbstractDomain::DomainType type = selectDomain(attachedAxisList<<axis);
188 AbstractDomain::DomainType type = selectDomain(attachedAxisList<<axis);
189
189
190 if(type == AbstractDomain::UndefinedDomain) return false;
190 if(type == AbstractDomain::UndefinedDomain) return false;
191
191
192 if(domain->type()!=type){
192 if(domain->type()!=type){
193 domain = createDomain(type);
193 domain = createDomain(type);
194 }
194 }
195
195
196 if(!domain) return false;
196 if(!domain) return false;
197
197
198 if(!domain->attachAxis(axis)) return false;
198 if(!domain->attachAxis(axis)) return false;
199
199
200 series->d_ptr->m_axes<<axis;
200 series->d_ptr->m_axes<<axis;
201 axis->d_ptr->m_series<<series;
201 axis->d_ptr->m_series<<series;
202
202
203 if(domain!=series->d_ptr->domain()){
203 if(domain!=series->d_ptr->domain()){
204 series->d_ptr->setDomain(domain);
204 series->d_ptr->setDomain(domain);
205 series->d_ptr->initializeDomain();
205 series->d_ptr->initializeDomain();
206 }
206 }
207 series->d_ptr->initializeAxes();
207 series->d_ptr->initializeAxes();
208 axis->d_ptr->initializeDomain(domain);
208 axis->d_ptr->initializeDomain(domain);
209
209
210 return true;
210 return true;
211 }
211 }
212
212
213 /*
213 /*
214 * This method detaches axis to series, return true if success.
214 * This method detaches axis to series, return true if success.
215 */
215 */
216 bool ChartDataSet::detachAxis(QAbstractSeries* series,QAbstractAxis *axis)
216 bool ChartDataSet::detachAxis(QAbstractSeries* series,QAbstractAxis *axis)
217 {
217 {
218 Q_ASSERT(series);
218 Q_ASSERT(series);
219 Q_ASSERT(axis);
219 Q_ASSERT(axis);
220
220
221 QList<QAbstractSeries* > attachedSeriesList = axis->d_ptr->m_series;
221 QList<QAbstractSeries* > attachedSeriesList = axis->d_ptr->m_series;
222 QList<QAbstractAxis* > attachedAxisList = series->d_ptr->m_axes;
222 QList<QAbstractAxis* > attachedAxisList = series->d_ptr->m_axes;
223 AbstractDomain* domain = series->d_ptr->domain();
223 AbstractDomain* domain = series->d_ptr->domain();
224
224
225 if (!m_seriesList.contains(series)) {
225 if (!m_seriesList.contains(series)) {
226 qWarning() << QObject::tr("Can not find series on the chart.");
226 qWarning() << QObject::tr("Can not find series on the chart.");
227 return false;
227 return false;
228 }
228 }
229
229
230 if (axis && !m_axisList.contains(axis)) {
230 if (axis && !m_axisList.contains(axis)) {
231 qWarning() << QObject::tr("Can not find axis on the chart.");
231 qWarning() << QObject::tr("Can not find axis on the chart.");
232 return false;
232 return false;
233 }
233 }
234
234
235 if (!attachedAxisList.contains(axis)) {
235 if (!attachedAxisList.contains(axis)) {
236 qWarning() << QObject::tr("Axis not attached to series.");
236 qWarning() << QObject::tr("Axis not attached to series.");
237 return false;
237 return false;
238 }
238 }
239
239
240 Q_ASSERT(axis->d_ptr->m_series.contains(series));
240 Q_ASSERT(axis->d_ptr->m_series.contains(series));
241
241
242 domain->detachAxis(axis);
242 domain->detachAxis(axis);
243 series->d_ptr->m_axes.removeAll(axis);
243 series->d_ptr->m_axes.removeAll(axis);
244 axis->d_ptr->m_series.removeAll(series);
244 axis->d_ptr->m_series.removeAll(series);
245
245
246 return true;
246 return true;
247 }
247 }
248
248
249 void ChartDataSet::createDefaultAxes()
249 void ChartDataSet::createDefaultAxes()
250 {
250 {
251 if (m_seriesList.isEmpty())
251 if (m_seriesList.isEmpty())
252 return;
252 return;
253
253
254 QAbstractAxis::AxisTypes typeX(0);
254 QAbstractAxis::AxisTypes typeX(0);
255 QAbstractAxis::AxisTypes typeY(0);
255 QAbstractAxis::AxisTypes typeY(0);
256
256
257 // Remove possibly existing axes
257 // Remove possibly existing axes
258 deleteAllAxes();
258 deleteAllAxes();
259
259
260 Q_ASSERT(m_axisList.isEmpty());
260 Q_ASSERT(m_axisList.isEmpty());
261
261
262 // Select the required axis x and axis y types based on the types of the current series
262 // Select the required axis x and axis y types based on the types of the current series
263 foreach(QAbstractSeries* s, m_seriesList) {
263 foreach(QAbstractSeries* s, m_seriesList) {
264 typeX |= s->d_ptr->defaultAxisType(Qt::Horizontal);
264 typeX |= s->d_ptr->defaultAxisType(Qt::Horizontal);
265 typeY |= s->d_ptr->defaultAxisType(Qt::Vertical);
265 typeY |= s->d_ptr->defaultAxisType(Qt::Vertical);
266 }
266 }
267
267
268 // Create the axes of the types selected
268 // Create the axes of the types selected
269 createAxes(typeX, Qt::Horizontal);
269 createAxes(typeX, Qt::Horizontal);
270 createAxes(typeY, Qt::Vertical);
270 createAxes(typeY, Qt::Vertical);
271
271
272 }
272 }
273
273
274 void ChartDataSet::createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation)
274 void ChartDataSet::createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation)
275 {
275 {
276 QAbstractAxis *axis = 0;
276 QAbstractAxis *axis = 0;
277 //decide what axis should be created
277 //decide what axis should be created
278
278
279 switch (type) {
279 switch (type) {
280 case QAbstractAxis::AxisTypeValue:
280 case QAbstractAxis::AxisTypeValue:
281 axis = new QValueAxis(this);
281 axis = new QValueAxis(this);
282 break;
282 break;
283 case QAbstractAxis::AxisTypeBarCategory:
283 case QAbstractAxis::AxisTypeBarCategory:
284 axis = new QBarCategoryAxis(this);
284 axis = new QBarCategoryAxis(this);
285 break;
285 break;
286 case QAbstractAxis::AxisTypeCategory:
286 case QAbstractAxis::AxisTypeCategory:
287 axis = new QCategoryAxis(this);
287 axis = new QCategoryAxis(this);
288 break;
288 break;
289 #ifndef Q_WS_QWS
289 #ifndef Q_WS_QWS
290 case QAbstractAxis::AxisTypeDateTime:
290 case QAbstractAxis::AxisTypeDateTime:
291 axis = new QDateTimeAxis(this);
291 axis = new QDateTimeAxis(this);
292 break;
292 break;
293 #endif
293 #endif
294 default:
294 default:
295 axis = 0;
295 axis = 0;
296 break;
296 break;
297 }
297 }
298
298
299 if (axis) {
299 if (axis) {
300 //create one axis for all
300 //create one axis for all
301
301
302 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
302 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
303
303
304 foreach(QAbstractSeries *s, m_seriesList) {
304 foreach(QAbstractSeries *s, m_seriesList) {
305 attachAxis(s,axis);
305 attachAxis(s,axis);
306 }
306 }
307
307
308 }
308 }
309 else if (!type.testFlag(QAbstractAxis::AxisTypeNoAxis)) {
309 else if (!type.testFlag(QAbstractAxis::AxisTypeNoAxis)) {
310 //create separate axis
310 //create separate axis
311 foreach(QAbstractSeries *s, m_seriesList) {
311 foreach(QAbstractSeries *s, m_seriesList) {
312 QAbstractAxis *axis = s->d_ptr->createDefaultAxis(orientation);
312 QAbstractAxis *axis = s->d_ptr->createDefaultAxis(orientation);
313 if(axis) {
313 if(axis) {
314 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
314 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
315 attachAxis(s,axis);
315 attachAxis(s,axis);
316 }
316 }
317 }
317 }
318 }
318 }
319 }
319 }
320
320
321 void ChartDataSet::deleteAllSeries()
321 void ChartDataSet::deleteAllSeries()
322 {
322 {
323 foreach (QAbstractSeries *s , m_seriesList){
323 foreach (QAbstractSeries *s , m_seriesList){
324 removeSeries(s);
324 removeSeries(s);
325 delete s;
325 delete s;
326 }
326 }
327 Q_ASSERT(m_seriesList.count() == 0);
327 Q_ASSERT(m_seriesList.count() == 0);
328 }
328 }
329
329
330 void ChartDataSet::deleteAllAxes()
330 void ChartDataSet::deleteAllAxes()
331 {
331 {
332 foreach (QAbstractAxis *a , m_axisList){
332 foreach (QAbstractAxis *a , m_axisList){
333 removeAxis(a);
333 removeAxis(a);
334 delete a;
334 delete a;
335 }
335 }
336 Q_ASSERT(m_axisList.count() == 0);
336 Q_ASSERT(m_axisList.count() == 0);
337 }
337 }
338
338
339 void ChartDataSet::zoomInDomain(const QRectF &rect)
339 void ChartDataSet::zoomInDomain(const QRectF &rect)
340 {
340 {
341 QList<AbstractDomain*> domains;
341 QList<AbstractDomain*> domains;
342 foreach(QAbstractSeries *s, m_seriesList) {
342 foreach(QAbstractSeries *s, m_seriesList) {
343 AbstractDomain* domain = s->d_ptr->domain();
343 AbstractDomain* domain = s->d_ptr->domain();
344 s->d_ptr->m_domain->blockAxisSignals(true);
344 s->d_ptr->m_domain->blockRangeSignals(true);
345 domains<<domain;
345 domains<<domain;
346 }
346 }
347
347
348 foreach(AbstractDomain *domain, domains)
348 foreach(AbstractDomain *domain, domains)
349 domain->zoomIn(rect);
349 domain->zoomIn(rect);
350
350
351 foreach(AbstractDomain *domain, domains)
351 foreach(AbstractDomain *domain, domains)
352 domain->blockAxisSignals(false);
352 domain->blockRangeSignals(false);
353 }
353 }
354
354
355 void ChartDataSet::zoomOutDomain(const QRectF &rect)
355 void ChartDataSet::zoomOutDomain(const QRectF &rect)
356 {
356 {
357 QList<AbstractDomain*> domains;
357 QList<AbstractDomain*> domains;
358 foreach(QAbstractSeries *s, m_seriesList) {
358 foreach(QAbstractSeries *s, m_seriesList) {
359 AbstractDomain* domain = s->d_ptr->domain();
359 AbstractDomain* domain = s->d_ptr->domain();
360 s->d_ptr->m_domain->blockAxisSignals(true);
360 s->d_ptr->m_domain->blockRangeSignals(true);
361 domains<<domain;
361 domains<<domain;
362 }
362 }
363
363
364 foreach(AbstractDomain *domain, domains)
364 foreach(AbstractDomain *domain, domains)
365 domain->zoomOut(rect);
365 domain->zoomOut(rect);
366
366
367 foreach(AbstractDomain *domain, domains)
367 foreach(AbstractDomain *domain, domains)
368 domain->blockAxisSignals(false);
368 domain->blockRangeSignals(false);
369 }
369 }
370
370
371 void ChartDataSet::scrollDomain(qreal dx, qreal dy)
371 void ChartDataSet::scrollDomain(qreal dx, qreal dy)
372 {
372 {
373 QList<AbstractDomain*> domains;
373 QList<AbstractDomain*> domains;
374 foreach(QAbstractSeries *s, m_seriesList) {
374 foreach(QAbstractSeries *s, m_seriesList) {
375 AbstractDomain* domain = s->d_ptr->m_domain.data();
375 AbstractDomain* domain = s->d_ptr->domain();
376 if(domains.contains(domain)) continue;
376 s->d_ptr->m_domain->blockRangeSignals(true);
377 s->d_ptr->m_domain->blockAxisSignals(true);
378 domains<<domain;
377 domains<<domain;
379 }
378 }
380
379
381 foreach(AbstractDomain *domain, domains)
380 foreach(AbstractDomain *domain, domains)
382 domain->move(dx, dy);
381 domain->move(dx, dy);
383
382
384 foreach(AbstractDomain *domain, domains)
383 foreach(AbstractDomain *domain, domains)
385 domain->blockAxisSignals(false);
384 domain->blockRangeSignals(false);
386 }
385 }
387
386
388 QList<QAbstractAxis*> ChartDataSet::axes() const
387 QList<QAbstractAxis*> ChartDataSet::axes() const
389 {
388 {
390 return m_axisList;
389 return m_axisList;
391 }
390 }
392
391
393 QList<QAbstractSeries *> ChartDataSet::series() const
392 QList<QAbstractSeries *> ChartDataSet::series() const
394 {
393 {
395 return m_seriesList;
394 return m_seriesList;
396 }
395 }
397
396
398 AbstractDomain::DomainType ChartDataSet::selectDomain(QList<QAbstractAxis*> axes)
397 AbstractDomain::DomainType ChartDataSet::selectDomain(QList<QAbstractAxis*> axes)
399 {
398 {
400 enum Type {
399 enum Type {
401 Undefined = 0,
400 Undefined = 0,
402 LogType = 0x1,
401 LogType = 0x1,
403 ValueType = 0x2
402 ValueType = 0x2
404 };
403 };
405
404
406 int horizontal(Undefined);
405 int horizontal(Undefined);
407 int vertical(Undefined);
406 int vertical(Undefined);
408
407
409 foreach(QAbstractAxis* axis, axes)
408 foreach(QAbstractAxis* axis, axes)
410 {
409 {
411 switch(axis->type()) {
410 switch(axis->type()) {
412 case QAbstractAxis::AxisTypeLogValue:
411 case QAbstractAxis::AxisTypeLogValue:
413
412
414 if(axis->orientation()==Qt::Horizontal) {
413 if(axis->orientation()==Qt::Horizontal) {
415 horizontal|=LogType;
414 horizontal|=LogType;
416 }
415 }
417 if(axis->orientation()==Qt::Vertical) {
416 if(axis->orientation()==Qt::Vertical) {
418 vertical|=LogType;
417 vertical|=LogType;
419 }
418 }
420
419
421 break;
420 break;
422 case QAbstractAxis::AxisTypeValue:
421 case QAbstractAxis::AxisTypeValue:
423 case QAbstractAxis::AxisTypeBarCategory:
422 case QAbstractAxis::AxisTypeBarCategory:
424 case QAbstractAxis::AxisTypeCategory:
423 case QAbstractAxis::AxisTypeCategory:
425 case QAbstractAxis::AxisTypeDateTime:
424 case QAbstractAxis::AxisTypeDateTime:
426 if(axis->orientation()==Qt::Horizontal) {
425 if(axis->orientation()==Qt::Horizontal) {
427 horizontal|=ValueType;
426 horizontal|=ValueType;
428 }
427 }
429 if(axis->orientation()==Qt::Vertical) {
428 if(axis->orientation()==Qt::Vertical) {
430 vertical|=ValueType;
429 vertical|=ValueType;
431 }
430 }
432 break;
431 break;
433 default:
432 default:
434 qWarning()<<"Undefined type";
433 qWarning()<<"Undefined type";
435 break;
434 break;
436 }
435 }
437 }
436 }
438
437
439 if(vertical==Undefined) vertical=ValueType;
438 if(vertical==Undefined) vertical=ValueType;
440 if(horizontal==Undefined) horizontal=ValueType;
439 if(horizontal==Undefined) horizontal=ValueType;
441
440
442 if(vertical==ValueType && horizontal== ValueType) {
441 if(vertical==ValueType && horizontal== ValueType) {
443 return AbstractDomain::XYDomain;
442 return AbstractDomain::XYDomain;
444 }
443 }
445
444
446 if(vertical==LogType && horizontal== ValueType) {
445 if(vertical==LogType && horizontal== ValueType) {
447 return AbstractDomain::XLogYDomain;
446 return AbstractDomain::XLogYDomain;
448 }
447 }
449
448
450 if(vertical==ValueType && horizontal== LogType) {
449 if(vertical==ValueType && horizontal== LogType) {
451 return AbstractDomain::LogXYDomain;
450 return AbstractDomain::LogXYDomain;
452 }
451 }
453
452
454 if(vertical==LogType && horizontal== LogType) {
453 if(vertical==LogType && horizontal== LogType) {
455 return AbstractDomain::LogXLogYDomain;
454 return AbstractDomain::LogXLogYDomain;
456 }
455 }
457
456
458 return AbstractDomain::UndefinedDomain;
457 return AbstractDomain::UndefinedDomain;
459 }
458 }
460
459
461
460
462 //refactor create factory
461 //refactor create factory
463 AbstractDomain* ChartDataSet::createDomain(AbstractDomain::DomainType type)
462 AbstractDomain* ChartDataSet::createDomain(AbstractDomain::DomainType type)
464 {
463 {
465 switch(type)
464 switch(type)
466 {
465 {
467 case AbstractDomain::LogXLogYDomain:
466 case AbstractDomain::LogXLogYDomain:
468 return new LogXLogYDomain();
467 return new LogXLogYDomain();
469 case AbstractDomain::XYDomain:
468 case AbstractDomain::XYDomain:
470 return new XYDomain();
469 return new XYDomain();
471 case AbstractDomain::XLogYDomain:
470 case AbstractDomain::XLogYDomain:
472 return new XLogYDomain();
471 return new XLogYDomain();
473 case AbstractDomain::LogXYDomain:
472 case AbstractDomain::LogXYDomain:
474 return new LogXYDomain();
473 return new LogXYDomain();
475 default:
474 default:
476 return 0;
475 return 0;
477 }
476 }
478 }
477 }
479
478
480 #include "moc_chartdataset_p.cpp"
479 #include "moc_chartdataset_p.cpp"
481
480
482 QTCOMMERCIALCHART_END_NAMESPACE
481 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,219 +1,223
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 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 Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and 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 "abstractdomain_p.h"
21 #include "abstractdomain_p.h"
22 #include "qabstractaxis_p.h"
22 #include "qabstractaxis_p.h"
23 #include <qmath.h>
23 #include <qmath.h>
24
24
25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26
26
27 AbstractDomain::AbstractDomain(QObject *parent)
27 AbstractDomain::AbstractDomain(QObject *parent)
28 : QObject(parent),
28 : QObject(parent),
29 m_minX(0),
29 m_minX(0),
30 m_maxX(0),
30 m_maxX(0),
31 m_minY(0),
31 m_minY(0),
32 m_maxY(0),
32 m_maxY(0),
33 m_axisSignalsBlocked(false)
33 m_signalsBlocked(false)
34 {
34 {
35 }
35 }
36
36
37 AbstractDomain::~AbstractDomain()
37 AbstractDomain::~AbstractDomain()
38 {
38 {
39 }
39 }
40
40
41 void AbstractDomain::setSize(const QSizeF& size)
41 void AbstractDomain::setSize(const QSizeF& size)
42 {
42 {
43 if(m_size!=size)
43 if(m_size!=size)
44 {
44 {
45 m_size=size;
45 m_size=size;
46 emit updated();
46 emit updated();
47 }
47 }
48 }
48 }
49
49
50 QSizeF AbstractDomain::size() const
50 QSizeF AbstractDomain::size() const
51 {
51 {
52 return m_size;
52 return m_size;
53 }
53 }
54
54
55 void AbstractDomain::setRangeX(qreal min, qreal max)
55 void AbstractDomain::setRangeX(qreal min, qreal max)
56 {
56 {
57 setRange(min, max, m_minY, m_maxY);
57 setRange(min, max, m_minY, m_maxY);
58 }
58 }
59
59
60 void AbstractDomain::setRangeY(qreal min, qreal max)
60 void AbstractDomain::setRangeY(qreal min, qreal max)
61 {
61 {
62 setRange(m_minX, m_maxX, min, max);
62 setRange(m_minX, m_maxX, min, max);
63 }
63 }
64
64
65 void AbstractDomain::setMinX(qreal min)
65 void AbstractDomain::setMinX(qreal min)
66 {
66 {
67 setRange(min, m_maxX, m_minY, m_maxY);
67 setRange(min, m_maxX, m_minY, m_maxY);
68 }
68 }
69
69
70 void AbstractDomain::setMaxX(qreal max)
70 void AbstractDomain::setMaxX(qreal max)
71 {
71 {
72 setRange(m_minX, max, m_minY, m_maxY);
72 setRange(m_minX, max, m_minY, m_maxY);
73 }
73 }
74
74
75 void AbstractDomain::setMinY(qreal min)
75 void AbstractDomain::setMinY(qreal min)
76 {
76 {
77 setRange(m_minX, m_maxX, min, m_maxY);
77 setRange(m_minX, m_maxX, min, m_maxY);
78 }
78 }
79
79
80 void AbstractDomain::setMaxY(qreal max)
80 void AbstractDomain::setMaxY(qreal max)
81 {
81 {
82 setRange(m_minX, m_maxX, m_minY, max);
82 setRange(m_minX, m_maxX, m_minY, max);
83 }
83 }
84
84
85 qreal AbstractDomain::spanX() const
85 qreal AbstractDomain::spanX() const
86 {
86 {
87 Q_ASSERT(m_maxX >= m_minX);
87 Q_ASSERT(m_maxX >= m_minX);
88 return m_maxX - m_minX;
88 return m_maxX - m_minX;
89 }
89 }
90
90
91 qreal AbstractDomain::spanY() const
91 qreal AbstractDomain::spanY() const
92 {
92 {
93 Q_ASSERT(m_maxY >= m_minY);
93 Q_ASSERT(m_maxY >= m_minY);
94 return m_maxY - m_minY;
94 return m_maxY - m_minY;
95 }
95 }
96
96
97 bool AbstractDomain::isEmpty() const
97 bool AbstractDomain::isEmpty() const
98 {
98 {
99 return qFuzzyIsNull(spanX()) || qFuzzyIsNull(spanY()) || m_size.isEmpty() ;
99 return qFuzzyIsNull(spanX()) || qFuzzyIsNull(spanY()) || m_size.isEmpty() ;
100 }
100 }
101
101
102 QPointF AbstractDomain::calculateDomainPoint(const QPointF &point) const
102 QPointF AbstractDomain::calculateDomainPoint(const QPointF &point) const
103 {
103 {
104 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
104 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
105 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
105 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
106 qreal x = point.x() / deltaX + m_minX;
106 qreal x = point.x() / deltaX + m_minX;
107 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
107 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
108 return QPointF(x, y);
108 return QPointF(x, y);
109 }
109 }
110
110
111 // handlers
111 // handlers
112
112
113 void AbstractDomain::handleVerticalAxisRangeChanged(qreal min, qreal max)
113 void AbstractDomain::handleVerticalAxisRangeChanged(qreal min, qreal max)
114 {
114 {
115 if(!m_axisSignalsBlocked)
116 setRangeY(min, max);
115 setRangeY(min, max);
117 }
116 }
118
117
119 void AbstractDomain::handleHorizontalAxisRangeChanged(qreal min, qreal max)
118 void AbstractDomain::handleHorizontalAxisRangeChanged(qreal min, qreal max)
120 {
119 {
121 if(!m_axisSignalsBlocked)
122 setRangeX(min, max);
120 setRangeX(min, max);
123 }
121 }
124
122
125 void AbstractDomain::blockAxisSignals(bool block)
123 void AbstractDomain::blockRangeSignals(bool block)
126 {
124 {
127 m_axisSignalsBlocked=block;
125 if(m_signalsBlocked!=block){
126 m_signalsBlocked=block;
127 if(!block) {
128 emit rangeHorizontalChanged(m_minX,m_maxX);
129 emit rangeVerticalChanged(m_minY,m_maxY);
130 }
131 }
128 }
132 }
129
133
130 //algorithm defined by Paul S.Heckbert GraphicalGems I
134 //algorithm defined by Paul S.Heckbert GraphicalGems I
131
135
132 void AbstractDomain::looseNiceNumbers(qreal &min, qreal &max, int &ticksCount)
136 void AbstractDomain::looseNiceNumbers(qreal &min, qreal &max, int &ticksCount)
133 {
137 {
134 qreal range = niceNumber(max - min, true); //range with ceiling
138 qreal range = niceNumber(max - min, true); //range with ceiling
135 qreal step = niceNumber(range / (ticksCount - 1), false);
139 qreal step = niceNumber(range / (ticksCount - 1), false);
136 min = qFloor(min / step);
140 min = qFloor(min / step);
137 max = qCeil(max / step);
141 max = qCeil(max / step);
138 ticksCount = int(max - min) + 1;
142 ticksCount = int(max - min) + 1;
139 min *= step;
143 min *= step;
140 max *= step;
144 max *= step;
141 }
145 }
142
146
143 //nice numbers can be expressed as form of 1*10^n, 2* 10^n or 5*10^n
147 //nice numbers can be expressed as form of 1*10^n, 2* 10^n or 5*10^n
144
148
145 qreal AbstractDomain::niceNumber(qreal x, bool ceiling)
149 qreal AbstractDomain::niceNumber(qreal x, bool ceiling)
146 {
150 {
147 qreal z = qPow(10, qFloor(log10(x))); //find corresponding number of the form of 10^n than is smaller than x
151 qreal z = qPow(10, qFloor(log10(x))); //find corresponding number of the form of 10^n than is smaller than x
148 qreal q = x / z; //q<10 && q>=1;
152 qreal q = x / z; //q<10 && q>=1;
149
153
150 if (ceiling) {
154 if (ceiling) {
151 if (q <= 1.0) q = 1;
155 if (q <= 1.0) q = 1;
152 else if (q <= 2.0) q = 2;
156 else if (q <= 2.0) q = 2;
153 else if (q <= 5.0) q = 5;
157 else if (q <= 5.0) q = 5;
154 else q = 10;
158 else q = 10;
155 } else {
159 } else {
156 if (q < 1.5) q = 1;
160 if (q < 1.5) q = 1;
157 else if (q < 3.0) q = 2;
161 else if (q < 3.0) q = 2;
158 else if (q < 7.0) q = 5;
162 else if (q < 7.0) q = 5;
159 else q = 10;
163 else q = 10;
160 }
164 }
161 return q * z;
165 return q * z;
162 }
166 }
163
167
164 bool AbstractDomain::attachAxis(QAbstractAxis* axis)
168 bool AbstractDomain::attachAxis(QAbstractAxis* axis)
165 {
169 {
166 if(axis->orientation()==Qt::Vertical) {
170 if(axis->orientation()==Qt::Vertical) {
167 QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
171 QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
168 QObject::connect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
172 QObject::connect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
169 }
173 }
170
174
171 if(axis->orientation()==Qt::Horizontal) {
175 if(axis->orientation()==Qt::Horizontal) {
172 QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
176 QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
173 QObject::connect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
177 QObject::connect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
174 }
178 }
175
179
176 return true;
180 return true;
177 }
181 }
178
182
179 bool AbstractDomain::detachAxis(QAbstractAxis* axis)
183 bool AbstractDomain::detachAxis(QAbstractAxis* axis)
180 {
184 {
181 if(axis->orientation()==Qt::Vertical) {
185 if(axis->orientation()==Qt::Vertical) {
182 QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
186 QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
183 QObject::disconnect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
187 QObject::disconnect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
184 }
188 }
185
189
186 if(axis->orientation()==Qt::Horizontal) {
190 if(axis->orientation()==Qt::Horizontal) {
187 QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
191 QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
188 QObject::disconnect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
192 QObject::disconnect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
189 }
193 }
190
194
191 return true;
195 return true;
192 }
196 }
193
197
194 // operators
198 // operators
195
199
196 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2)
200 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2)
197 {
201 {
198 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX) &&
202 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX) &&
199 qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY) &&
203 qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY) &&
200 qFuzzyIsNull(domain1.m_minX - domain2.m_minX) &&
204 qFuzzyIsNull(domain1.m_minX - domain2.m_minX) &&
201 qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
205 qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
202 }
206 }
203
207
204
208
205 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2)
209 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2)
206 {
210 {
207 return !(domain1 == domain2);
211 return !(domain1 == domain2);
208 }
212 }
209
213
210
214
211 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain)
215 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain)
212 {
216 {
213 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
217 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
214 return dbg.maybeSpace();
218 return dbg.maybeSpace();
215 }
219 }
216
220
217 #include "moc_abstractdomain_p.cpp"
221 #include "moc_abstractdomain_p.cpp"
218
222
219 QTCOMMERCIALCHART_END_NAMESPACE
223 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,113 +1,113
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 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 Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and 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 // W A R N I N G
21 // W A R N I N G
22 // -------------
22 // -------------
23 //
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 // implementation detail. This header file may change from version to
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
26 // version without notice, or even be removed.
27 //
27 //
28 // We mean it.
28 // We mean it.
29
29
30 #ifndef ABSTRACTDOMAIN_H
30 #ifndef ABSTRACTDOMAIN_H
31 #define ABSTRACTDOMAIN_H
31 #define ABSTRACTDOMAIN_H
32 #include "qchartglobal.h"
32 #include "qchartglobal.h"
33 #include <QRectF>
33 #include <QRectF>
34 #include <QSizeF>
34 #include <QSizeF>
35 #include <QDebug>
35 #include <QDebug>
36
36
37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38
38
39 class QAbstractAxis;
39 class QAbstractAxis;
40
40
41 class QTCOMMERCIALCHART_AUTOTEST_EXPORT AbstractDomain: public QObject
41 class QTCOMMERCIALCHART_AUTOTEST_EXPORT AbstractDomain: public QObject
42 {
42 {
43 Q_OBJECT
43 Q_OBJECT
44 public:
44 public:
45 enum DomainType { UndefinedDomain, XYDomain, XLogYDomain, LogXYDomain, LogXLogYDomain };
45 enum DomainType { UndefinedDomain, XYDomain, XLogYDomain, LogXYDomain, LogXLogYDomain };
46 public:
46 public:
47 explicit AbstractDomain(QObject *object = 0);
47 explicit AbstractDomain(QObject *object = 0);
48 virtual ~AbstractDomain();
48 virtual ~AbstractDomain();
49
49
50 void setSize(const QSizeF& size);
50 void setSize(const QSizeF& size);
51 QSizeF size() const;
51 QSizeF size() const;
52
52
53 virtual DomainType type() = 0;
53 virtual DomainType type() = 0;
54
54
55 virtual void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) = 0;
55 virtual void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) = 0;
56 void setRangeX(qreal min, qreal max);
56 void setRangeX(qreal min, qreal max);
57 void setRangeY(qreal min, qreal max);
57 void setRangeY(qreal min, qreal max);
58 void setMinX(qreal min);
58 void setMinX(qreal min);
59 void setMaxX(qreal max);
59 void setMaxX(qreal max);
60 void setMinY(qreal min);
60 void setMinY(qreal min);
61 void setMaxY(qreal max);
61 void setMaxY(qreal max);
62
62
63 qreal minX() const { return m_minX; }
63 qreal minX() const { return m_minX; }
64 qreal maxX() const { return m_maxX; }
64 qreal maxX() const { return m_maxX; }
65 qreal minY() const { return m_minY; }
65 qreal minY() const { return m_minY; }
66 qreal maxY() const { return m_maxY; }
66 qreal maxY() const { return m_maxY; }
67
67
68 qreal spanX() const;
68 qreal spanX() const;
69 qreal spanY() const;
69 qreal spanY() const;
70 bool isEmpty() const;
70 bool isEmpty() const;
71
71
72 void blockAxisSignals(bool block);
72 void blockRangeSignals(bool block);
73 bool axisSignalsBlocked() const { return m_axisSignalsBlocked; }
73 bool rangeSignalsBlocked() const { return m_signalsBlocked; }
74
74
75 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2);
75 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2);
76 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2);
76 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2);
77 friend QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain);
77 friend QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain);
78
78
79 virtual void zoomIn(const QRectF &rect) = 0;
79 virtual void zoomIn(const QRectF &rect) = 0;
80 virtual void zoomOut(const QRectF &rect) = 0;
80 virtual void zoomOut(const QRectF &rect) = 0;
81 virtual void move(qreal dx, qreal dy) = 0;
81 virtual void move(qreal dx, qreal dy) = 0;
82
82
83 virtual QPointF calculateGeometryPoint(const QPointF &point) const = 0;
83 virtual QPointF calculateGeometryPoint(const QPointF &point) const = 0;
84 virtual QPointF calculateDomainPoint(const QPointF &point) const = 0;
84 virtual QPointF calculateDomainPoint(const QPointF &point) const = 0;
85 virtual QVector<QPointF> calculateGeometryPoints(const QList<QPointF>& vector) const = 0;
85 virtual QVector<QPointF> calculateGeometryPoints(const QList<QPointF>& vector) const = 0;
86
86
87 virtual bool attachAxis(QAbstractAxis* axis);
87 virtual bool attachAxis(QAbstractAxis* axis);
88 virtual bool detachAxis(QAbstractAxis* axis);
88 virtual bool detachAxis(QAbstractAxis* axis);
89
89
90 static void looseNiceNumbers(qreal &min, qreal &max, int &ticksCount);
90 static void looseNiceNumbers(qreal &min, qreal &max, int &ticksCount);
91 static qreal niceNumber(qreal x, bool ceiling);
91 static qreal niceNumber(qreal x, bool ceiling);
92
92
93 Q_SIGNALS:
93 Q_SIGNALS:
94 void updated();
94 void updated();
95 void rangeHorizontalChanged(qreal min, qreal max);
95 void rangeHorizontalChanged(qreal min, qreal max);
96 void rangeVerticalChanged(qreal min, qreal max);
96 void rangeVerticalChanged(qreal min, qreal max);
97
97
98 public Q_SLOTS:
98 public Q_SLOTS:
99 void handleVerticalAxisRangeChanged(qreal min,qreal max);
99 void handleVerticalAxisRangeChanged(qreal min,qreal max);
100 void handleHorizontalAxisRangeChanged(qreal min,qreal max);
100 void handleHorizontalAxisRangeChanged(qreal min,qreal max);
101
101
102 protected:
102 protected:
103 qreal m_minX;
103 qreal m_minX;
104 qreal m_maxX;
104 qreal m_maxX;
105 qreal m_minY;
105 qreal m_minY;
106 qreal m_maxY;
106 qreal m_maxY;
107 QSizeF m_size;
107 QSizeF m_size;
108 bool m_axisSignalsBlocked;
108 bool m_signalsBlocked;
109 };
109 };
110
110
111 QTCOMMERCIALCHART_END_NAMESPACE
111 QTCOMMERCIALCHART_END_NAMESPACE
112
112
113 #endif // ABSTRACTDOMAIN_H
113 #endif // ABSTRACTDOMAIN_H
@@ -1,177 +1,179
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 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 Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and 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 "xydomain_p.h"
21 #include "xydomain_p.h"
22 #include "qabstractaxis_p.h"
22 #include "qabstractaxis_p.h"
23 #include <qmath.h>
23 #include <qmath.h>
24
24
25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26
26
27 XYDomain::XYDomain(QObject *parent)
27 XYDomain::XYDomain(QObject *parent)
28 : AbstractDomain(parent)
28 : AbstractDomain(parent)
29 {
29 {
30 }
30 }
31
31
32 XYDomain::~XYDomain()
32 XYDomain::~XYDomain()
33 {
33 {
34 }
34 }
35
35
36 void XYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
36 void XYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
37 {
37 {
38 bool axisXChanged = false;
38 bool axisXChanged = false;
39 bool axisYChanged = false;
39 bool axisYChanged = false;
40
40
41 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
41 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
42 m_minX = minX;
42 m_minX = minX;
43 m_maxX = maxX;
43 m_maxX = maxX;
44 axisXChanged = true;
44 axisXChanged = true;
45 if(!m_signalsBlocked)
45 emit rangeHorizontalChanged(m_minX, m_maxX);
46 emit rangeHorizontalChanged(m_minX, m_maxX);
46 }
47 }
47
48
48 if (!qFuzzyCompare(m_minY, minY) || !qFuzzyCompare(m_maxY, maxY)) {
49 if (!qFuzzyCompare(m_minY, minY) || !qFuzzyCompare(m_maxY, maxY)) {
49 m_minY = minY;
50 m_minY = minY;
50 m_maxY = maxY;
51 m_maxY = maxY;
51 axisYChanged = true;
52 axisYChanged = true;
53 if(!m_signalsBlocked)
52 emit rangeVerticalChanged(m_minY, m_maxY);
54 emit rangeVerticalChanged(m_minY, m_maxY);
53 }
55 }
54
56
55 if (axisXChanged || axisYChanged)
57 if (axisXChanged || axisYChanged)
56 emit updated();
58 emit updated();
57 }
59 }
58
60
59
61
60 void XYDomain::zoomIn(const QRectF &rect)
62 void XYDomain::zoomIn(const QRectF &rect)
61 {
63 {
62 qreal dx = spanX() / m_size.width();
64 qreal dx = spanX() / m_size.width();
63 qreal dy = spanY() / m_size.height();
65 qreal dy = spanY() / m_size.height();
64
66
65 qreal maxX = m_maxX;
67 qreal maxX = m_maxX;
66 qreal minX = m_minX;
68 qreal minX = m_minX;
67 qreal minY = m_minY;
69 qreal minY = m_minY;
68 qreal maxY = m_maxY;
70 qreal maxY = m_maxY;
69
71
70 maxX = minX + dx * rect.right();
72 maxX = minX + dx * rect.right();
71 minX = minX + dx * rect.left();
73 minX = minX + dx * rect.left();
72 minY = maxY - dy * rect.bottom();
74 minY = maxY - dy * rect.bottom();
73 maxY = maxY - dy * rect.top();
75 maxY = maxY - dy * rect.top();
74
76
75 setRange(minX, maxX, minY, maxY);
77 setRange(minX, maxX, minY, maxY);
76 }
78 }
77
79
78 void XYDomain::zoomOut(const QRectF &rect)
80 void XYDomain::zoomOut(const QRectF &rect)
79 {
81 {
80 qreal dx = spanX() / rect.width();
82 qreal dx = spanX() / rect.width();
81 qreal dy = spanY() / rect.height();
83 qreal dy = spanY() / rect.height();
82
84
83 qreal maxX = m_maxX;
85 qreal maxX = m_maxX;
84 qreal minX = m_minX;
86 qreal minX = m_minX;
85 qreal minY = m_minY;
87 qreal minY = m_minY;
86 qreal maxY = m_maxY;
88 qreal maxY = m_maxY;
87
89
88 minX = maxX - dx * rect.right();
90 minX = maxX - dx * rect.right();
89 maxX = minX + dx * m_size.width();
91 maxX = minX + dx * m_size.width();
90 maxY = minY + dy * rect.bottom();
92 maxY = minY + dy * rect.bottom();
91 minY = maxY - dy * m_size.height();
93 minY = maxY - dy * m_size.height();
92
94
93 setRange(minX, maxX, minY, maxY);
95 setRange(minX, maxX, minY, maxY);
94 }
96 }
95
97
96 void XYDomain::move(qreal dx, qreal dy)
98 void XYDomain::move(qreal dx, qreal dy)
97 {
99 {
98 qreal x = spanX() / m_size.width();
100 qreal x = spanX() / m_size.width();
99 qreal y = spanY() / m_size.height();
101 qreal y = spanY() / m_size.height();
100
102
101 qreal maxX = m_maxX;
103 qreal maxX = m_maxX;
102 qreal minX = m_minX;
104 qreal minX = m_minX;
103 qreal minY = m_minY;
105 qreal minY = m_minY;
104 qreal maxY = m_maxY;
106 qreal maxY = m_maxY;
105
107
106 if (dx != 0) {
108 if (dx != 0) {
107 minX = minX + x * dx;
109 minX = minX + x * dx;
108 maxX = maxX + x * dx;
110 maxX = maxX + x * dx;
109 }
111 }
110 if (dy != 0) {
112 if (dy != 0) {
111 minY = minY + y * dy;
113 minY = minY + y * dy;
112 maxY = maxY + y * dy;
114 maxY = maxY + y * dy;
113 }
115 }
114 setRange(minX, maxX, minY, maxY);
116 setRange(minX, maxX, minY, maxY);
115 }
117 }
116
118
117 QPointF XYDomain::calculateGeometryPoint(const QPointF &point) const
119 QPointF XYDomain::calculateGeometryPoint(const QPointF &point) const
118 {
120 {
119 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
121 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
120 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
122 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
121 qreal x = (point.x() - m_minX) * deltaX;
123 qreal x = (point.x() - m_minX) * deltaX;
122 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
124 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
123 return QPointF(x, y);
125 return QPointF(x, y);
124 }
126 }
125
127
126 QVector<QPointF> XYDomain::calculateGeometryPoints(const QList<QPointF>& vector) const
128 QVector<QPointF> XYDomain::calculateGeometryPoints(const QList<QPointF>& vector) const
127 {
129 {
128 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
130 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
129 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
131 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
130
132
131 QVector<QPointF> result;
133 QVector<QPointF> result;
132 result.resize(vector.count());
134 result.resize(vector.count());
133
135
134 for (int i = 0; i < vector.count(); ++i) {
136 for (int i = 0; i < vector.count(); ++i) {
135 qreal x = (vector[i].x() - m_minX) * deltaX;
137 qreal x = (vector[i].x() - m_minX) * deltaX;
136 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
138 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
137 result[i].setX(x);
139 result[i].setX(x);
138 result[i].setY(y);
140 result[i].setY(y);
139 }
141 }
140 return result;
142 return result;
141 }
143 }
142
144
143 QPointF XYDomain::calculateDomainPoint(const QPointF &point) const
145 QPointF XYDomain::calculateDomainPoint(const QPointF &point) const
144 {
146 {
145 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
147 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
146 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
148 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
147 qreal x = point.x() / deltaX + m_minX;
149 qreal x = point.x() / deltaX + m_minX;
148 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
150 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
149 return QPointF(x, y);
151 return QPointF(x, y);
150 }
152 }
151
153
152 // operators
154 // operators
153
155
154 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const XYDomain &domain1, const XYDomain &domain2)
156 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const XYDomain &domain1, const XYDomain &domain2)
155 {
157 {
156 return (qFuzzyCompare(domain1.m_maxX, domain2.m_maxX) &&
158 return (qFuzzyCompare(domain1.m_maxX, domain2.m_maxX) &&
157 qFuzzyCompare(domain1.m_maxY, domain2.m_maxY) &&
159 qFuzzyCompare(domain1.m_maxY, domain2.m_maxY) &&
158 qFuzzyCompare(domain1.m_minX, domain2.m_minX) &&
160 qFuzzyCompare(domain1.m_minX, domain2.m_minX) &&
159 qFuzzyCompare(domain1.m_minY, domain2.m_minY));
161 qFuzzyCompare(domain1.m_minY, domain2.m_minY));
160 }
162 }
161
163
162
164
163 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XYDomain &domain1, const XYDomain &domain2)
165 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XYDomain &domain1, const XYDomain &domain2)
164 {
166 {
165 return !(domain1 == domain2);
167 return !(domain1 == domain2);
166 }
168 }
167
169
168
170
169 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYDomain &domain)
171 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYDomain &domain)
170 {
172 {
171 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
173 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
172 return dbg.maybeSpace();
174 return dbg.maybeSpace();
173 }
175 }
174
176
175 #include "moc_xydomain_p.cpp"
177 #include "moc_xydomain_p.cpp"
176
178
177 QTCOMMERCIALCHART_END_NAMESPACE
179 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now