##// END OF EJS Templates
Added QChart::zoomReset() and QChart::isZoomed()...
Miikka Heikkinen -
r2545:d1d46096c185
parent child
Show More
@@ -1,607 +1,632
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "chartdataset_p.h"
22 22 #include "chartpresenter_p.h"
23 23 #include "qchart.h"
24 24 #include "qchart_p.h"
25 25 #include "qvalueaxis.h"
26 26 #include "qbarcategoryaxis.h"
27 27 #include "qvalueaxis_p.h"
28 28 #include "qcategoryaxis.h"
29 29 #include "qabstractseries_p.h"
30 30 #include "qabstractbarseries.h"
31 31 #include "qstackedbarseries.h"
32 32 #include "qpercentbarseries.h"
33 33 #include "qpieseries.h"
34 34 #include "chartitem_p.h"
35 35 #include "xydomain_p.h"
36 36 #include "xypolardomain_p.h"
37 37 #include "xlogydomain_p.h"
38 38 #include "logxydomain_p.h"
39 39 #include "logxlogydomain_p.h"
40 40 #include "xlogypolardomain_p.h"
41 41 #include "logxypolardomain_p.h"
42 42 #include "logxlogypolardomain_p.h"
43 43
44 44 #ifndef QT_ON_ARM
45 45 #include "qdatetimeaxis.h"
46 46 #endif
47 47
48 48 QTCOMMERCIALCHART_BEGIN_NAMESPACE
49 49
50 50 ChartDataSet::ChartDataSet(QChart *chart)
51 51 : QObject(chart),
52 52 m_chart(chart)
53 53 {
54 54
55 55 }
56 56
57 57 ChartDataSet::~ChartDataSet()
58 58 {
59 59 deleteAllSeries();
60 60 deleteAllAxes();
61 61 }
62 62
63 63 /*
64 64 * This method adds series to chartdataset, series ownership is taken from caller.
65 65 */
66 66 void ChartDataSet::addSeries(QAbstractSeries *series)
67 67 {
68 68 if (m_seriesList.contains(series)) {
69 69 qWarning() << QObject::tr("Can not add series. Series already on the chart.");
70 70 return;
71 71 }
72 72
73 73 // Ignore unsupported series added to polar chart
74 74 if (m_chart && m_chart->chartType() == QChart::ChartTypePolar) {
75 75 if (!(series->type() == QAbstractSeries::SeriesTypeArea
76 76 || series->type() == QAbstractSeries::SeriesTypeLine
77 77 || series->type() == QAbstractSeries::SeriesTypeScatter
78 78 || series->type() == QAbstractSeries::SeriesTypeSpline)) {
79 79 qWarning() << QObject::tr("Can not add series. Series type is not supported by a polar chart.");
80 80 return;
81 81 }
82 82 series->d_ptr->setDomain(new XYPolarDomain());
83 83 } else {
84 84 series->d_ptr->setDomain(new XYDomain());
85 85 }
86 86
87 87 series->d_ptr->initializeDomain();
88 88 m_seriesList.append(series);
89 89
90 90 series->setParent(this); // take ownership
91 91 series->d_ptr->m_chart = m_chart;
92 92
93 93 emit seriesAdded(series);
94 94 }
95 95
96 96 /*
97 97 * This method adds axis to chartdataset, axis ownership is taken from caller.
98 98 */
99 99 void ChartDataSet::addAxis(QAbstractAxis *axis, Qt::Alignment aligment)
100 100 {
101 101 if (m_axisList.contains(axis)) {
102 102 qWarning() << QObject::tr("Can not add axis. Axis already on the chart.");
103 103 return;
104 104 }
105 105
106 106 axis->d_ptr->setAlignment(aligment);
107 107
108 108 if (!axis->alignment()) {
109 109 qWarning() << QObject::tr("No alignment specified !");
110 110 return;
111 111 };
112 112
113 113 AbstractDomain *newDomain;
114 114 if (m_chart && m_chart->chartType() == QChart::ChartTypePolar) {
115 115 foreach (QAbstractAxis *existingAxis, axes()) {
116 116 if (existingAxis->orientation() == axis->orientation()) {
117 117 qWarning() << QObject::tr("Cannot add multiple axes of same orientation to a polar chart!");
118 118 return;
119 119 }
120 120 }
121 121 newDomain = new XYPolarDomain();
122 122 } else {
123 123 newDomain = new XYDomain();
124 124 }
125 125
126 126 QSharedPointer<AbstractDomain> domain(newDomain);
127 127 axis->d_ptr->initializeDomain(domain.data());
128 128
129 129 axis->setParent(this);
130 130 axis->d_ptr->m_chart = m_chart;
131 131 m_axisList.append(axis);
132 132
133 133 emit axisAdded(axis);
134 134 }
135 135
136 136 /*
137 137 * This method removes series form chartdataset, series ownership is passed back to caller.
138 138 */
139 139 void ChartDataSet::removeSeries(QAbstractSeries *series)
140 140 {
141 141
142 142 if (! m_seriesList.contains(series)) {
143 143 qWarning() << QObject::tr("Can not remove series. Series not found on the chart.");
144 144 return;
145 145 }
146 146
147 147 QList<QAbstractAxis*> axes = series->d_ptr->m_axes;
148 148
149 149 foreach(QAbstractAxis* axis, axes) {
150 150 detachAxis(series,axis);
151 151 }
152 152
153 153 emit seriesRemoved(series);
154 154 m_seriesList.removeAll(series);
155 155
156 156 // Reset domain to default
157 157 series->d_ptr->setDomain(new XYDomain());
158 158 series->setParent(0);
159 159 series->d_ptr->m_chart = 0;
160 160 }
161 161
162 162 /*
163 163 * This method removes axis form chartdataset, series ownership is passed back to caller.
164 164 */
165 165 void ChartDataSet::removeAxis(QAbstractAxis *axis)
166 166 {
167 167 if (! m_axisList.contains(axis)) {
168 168 qWarning() << QObject::tr("Can not remove axis. Axis not found on the chart.");
169 169 return;
170 170 }
171 171
172 172 QList<QAbstractSeries*> series = axis->d_ptr->m_series;
173 173
174 174 foreach(QAbstractSeries* s, series) {
175 175 detachAxis(s,axis);
176 176 }
177 177
178 178 emit axisRemoved(axis);
179 179 m_axisList.removeAll(axis);
180 180
181 181 axis->setParent(0);
182 182 axis->d_ptr->m_chart = 0;
183 183 }
184 184
185 185 /*
186 186 * This method attaches axis to series, return true if success.
187 187 */
188 188 bool ChartDataSet::attachAxis(QAbstractSeries *series,QAbstractAxis *axis)
189 189 {
190 190 Q_ASSERT(series);
191 191 Q_ASSERT(axis);
192 192
193 193 QList<QAbstractSeries *> attachedSeriesList = axis->d_ptr->m_series;
194 194 QList<QAbstractAxis *> attachedAxisList = series->d_ptr->m_axes;
195 195
196 196 if (!m_seriesList.contains(series)) {
197 197 qWarning() << QObject::tr("Can not find series on the chart.");
198 198 return false;
199 199 }
200 200
201 201 if (axis && !m_axisList.contains(axis)) {
202 202 qWarning() << QObject::tr("Can not find axis on the chart.");
203 203 return false;
204 204 }
205 205
206 206 if (attachedAxisList.contains(axis)) {
207 207 qWarning() << QObject::tr("Axis already attached to series.");
208 208 return false;
209 209 }
210 210
211 211 if (attachedSeriesList.contains(series)) {
212 212 qWarning() << QObject::tr("Axis already attached to series.");
213 213 return false;
214 214 }
215 215
216 216 AbstractDomain *domain = series->d_ptr->domain();
217 217 AbstractDomain::DomainType type = selectDomain(attachedAxisList<<axis);
218 218
219 219 if (type == AbstractDomain::UndefinedDomain) return false;
220 220
221 221 if (domain->type() != type) {
222 222 AbstractDomain *old = domain;
223 223 domain = createDomain(type);
224 224 domain->setRange(old->minX(), old->maxX(), old->minY(), old->maxY());
225 225 // Initialize domain size to old domain size, as it won't get updated
226 226 // unless geometry changes.
227 227 domain->setSize(old->size());
228 228 }
229 229
230 230 if (!domain)
231 231 return false;
232 232
233 233 if (!domain->attachAxis(axis))
234 234 return false;
235 235
236 236 QList<AbstractDomain *> blockedDomains;
237 237 domain->blockRangeSignals(true);
238 238 blockedDomains << domain;
239 239
240 240 if (domain != series->d_ptr->domain()) {
241 241 foreach (QAbstractAxis *axis, series->d_ptr->m_axes) {
242 242 series->d_ptr->domain()->detachAxis(axis);
243 243 domain->attachAxis(axis);
244 244 foreach (QAbstractSeries *otherSeries, axis->d_ptr->m_series) {
245 245 if (otherSeries != series && otherSeries->d_ptr->domain()) {
246 246 if (!otherSeries->d_ptr->domain()->rangeSignalsBlocked()) {
247 247 otherSeries->d_ptr->domain()->blockRangeSignals(true);
248 248 blockedDomains << otherSeries->d_ptr->domain();
249 249 }
250 250 }
251 251 }
252 252 }
253 253 series->d_ptr->setDomain(domain);
254 254 series->d_ptr->initializeDomain();
255 255 }
256 256
257 257 series->d_ptr->m_axes<<axis;
258 258 axis->d_ptr->m_series<<series;
259 259
260 260 series->d_ptr->initializeAxes();
261 261 axis->d_ptr->initializeDomain(domain);
262 262
263 263 foreach (AbstractDomain *blockedDomain, blockedDomains)
264 264 blockedDomain->blockRangeSignals(false);
265 265
266 266 return true;
267 267 }
268 268
269 269 /*
270 270 * This method detaches axis to series, return true if success.
271 271 */
272 272 bool ChartDataSet::detachAxis(QAbstractSeries* series,QAbstractAxis *axis)
273 273 {
274 274 Q_ASSERT(series);
275 275 Q_ASSERT(axis);
276 276
277 277 QList<QAbstractSeries* > attachedSeriesList = axis->d_ptr->m_series;
278 278 QList<QAbstractAxis* > attachedAxisList = series->d_ptr->m_axes;
279 279 AbstractDomain* domain = series->d_ptr->domain();
280 280
281 281 if (!m_seriesList.contains(series)) {
282 282 qWarning() << QObject::tr("Can not find series on the chart.");
283 283 return false;
284 284 }
285 285
286 286 if (axis && !m_axisList.contains(axis)) {
287 287 qWarning() << QObject::tr("Can not find axis on the chart.");
288 288 return false;
289 289 }
290 290
291 291 if (!attachedAxisList.contains(axis)) {
292 292 qWarning() << QObject::tr("Axis not attached to series.");
293 293 return false;
294 294 }
295 295
296 296 Q_ASSERT(axis->d_ptr->m_series.contains(series));
297 297
298 298 domain->detachAxis(axis);
299 299 series->d_ptr->m_axes.removeAll(axis);
300 300 axis->d_ptr->m_series.removeAll(series);
301 301
302 302 return true;
303 303 }
304 304
305 305 void ChartDataSet::createDefaultAxes()
306 306 {
307 307 if (m_seriesList.isEmpty())
308 308 return;
309 309
310 310 QAbstractAxis::AxisTypes typeX(0);
311 311 QAbstractAxis::AxisTypes typeY(0);
312 312
313 313 // Remove possibly existing axes
314 314 deleteAllAxes();
315 315
316 316 Q_ASSERT(m_axisList.isEmpty());
317 317
318 318 // Select the required axis x and axis y types based on the types of the current series
319 319 foreach(QAbstractSeries* s, m_seriesList) {
320 320 typeX |= s->d_ptr->defaultAxisType(Qt::Horizontal);
321 321 typeY |= s->d_ptr->defaultAxisType(Qt::Vertical);
322 322 }
323 323
324 324 // Create the axes of the types selected
325 325 createAxes(typeX, Qt::Horizontal);
326 326 createAxes(typeY, Qt::Vertical);
327 327
328 328 }
329 329
330 330 void ChartDataSet::createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation)
331 331 {
332 332 QAbstractAxis *axis = 0;
333 333 //decide what axis should be created
334 334
335 335 switch (type) {
336 336 case QAbstractAxis::AxisTypeValue:
337 337 axis = new QValueAxis(this);
338 338 break;
339 339 case QAbstractAxis::AxisTypeBarCategory:
340 340 axis = new QBarCategoryAxis(this);
341 341 break;
342 342 case QAbstractAxis::AxisTypeCategory:
343 343 axis = new QCategoryAxis(this);
344 344 break;
345 345 #ifndef Q_WS_QWS
346 346 case QAbstractAxis::AxisTypeDateTime:
347 347 axis = new QDateTimeAxis(this);
348 348 break;
349 349 #endif
350 350 default:
351 351 axis = 0;
352 352 break;
353 353 }
354 354
355 355 if (axis) {
356 356 //create one axis for all
357 357
358 358 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
359 359 qreal min = 0;
360 360 qreal max = 0;
361 361 findMinMaxForSeries(m_seriesList,orientation,min,max);
362 362 foreach(QAbstractSeries *s, m_seriesList) {
363 363 attachAxis(s,axis);
364 364 }
365 365 axis->setRange(min,max);
366 366 }
367 367 else if (!type.testFlag(QAbstractAxis::AxisTypeNoAxis)) {
368 368 //create separate axis
369 369 foreach(QAbstractSeries *s, m_seriesList) {
370 370 QAbstractAxis *axis = s->d_ptr->createDefaultAxis(orientation);
371 371 if(axis) {
372 372 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
373 373 attachAxis(s,axis);
374 374 }
375 375 }
376 376 }
377 377 }
378 378
379 379 void ChartDataSet::findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orientations orientation, qreal &min, qreal &max)
380 380 {
381 381 Q_ASSERT(!series.isEmpty());
382 382
383 383 AbstractDomain *domain = series.first()->d_ptr->domain();
384 384 min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
385 385 max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
386 386
387 387 for (int i = 1; i< series.size(); i++) {
388 388 AbstractDomain *domain = series[i]->d_ptr->domain();
389 389 min = qMin((orientation == Qt::Vertical) ? domain->minY() : domain->minX(), min);
390 390 max = qMax((orientation == Qt::Vertical) ? domain->maxY() : domain->maxX(), max);
391 391 }
392 392 if (min == max) {
393 393 min -= 0.5;
394 394 max += 0.5;
395 395 }
396 396 }
397 397
398 398 void ChartDataSet::deleteAllSeries()
399 399 {
400 400 foreach (QAbstractSeries *s , m_seriesList){
401 401 removeSeries(s);
402 402 s->deleteLater();
403 403 }
404 404 Q_ASSERT(m_seriesList.count() == 0);
405 405 }
406 406
407 407 void ChartDataSet::deleteAllAxes()
408 408 {
409 409 foreach (QAbstractAxis *a , m_axisList){
410 410 removeAxis(a);
411 411 a->deleteLater();
412 412 }
413 413 Q_ASSERT(m_axisList.count() == 0);
414 414 }
415 415
416 416 void ChartDataSet::zoomInDomain(const QRectF &rect)
417 417 {
418 418 QList<AbstractDomain*> domains;
419 419 foreach(QAbstractSeries *s, m_seriesList) {
420 420 AbstractDomain* domain = s->d_ptr->domain();
421 421 s->d_ptr->m_domain->blockRangeSignals(true);
422 422 domains<<domain;
423 423 }
424 424
425 425 foreach(AbstractDomain *domain, domains)
426 426 domain->zoomIn(rect);
427 427
428 428 foreach(AbstractDomain *domain, domains)
429 429 domain->blockRangeSignals(false);
430 430 }
431 431
432 432 void ChartDataSet::zoomOutDomain(const QRectF &rect)
433 433 {
434 434 QList<AbstractDomain*> domains;
435 435 foreach(QAbstractSeries *s, m_seriesList) {
436 436 AbstractDomain* domain = s->d_ptr->domain();
437 437 s->d_ptr->m_domain->blockRangeSignals(true);
438 438 domains<<domain;
439 439 }
440 440
441 441 foreach(AbstractDomain *domain, domains)
442 442 domain->zoomOut(rect);
443 443
444 444 foreach(AbstractDomain *domain, domains)
445 445 domain->blockRangeSignals(false);
446 446 }
447 447
448 void ChartDataSet::zoomResetDomain()
449 {
450 QList<AbstractDomain*> domains;
451 foreach (QAbstractSeries *s, m_seriesList) {
452 AbstractDomain *domain = s->d_ptr->domain();
453 s->d_ptr->m_domain->blockRangeSignals(true);
454 domains << domain;
455 }
456
457 foreach (AbstractDomain *domain, domains)
458 domain->zoomReset();
459
460 foreach (AbstractDomain *domain, domains)
461 domain->blockRangeSignals(false);
462 }
463
464 bool ChartDataSet::isZoomedDomain()
465 {
466 foreach (QAbstractSeries *s, m_seriesList) {
467 if (s->d_ptr->domain()->isZoomed())
468 return true;
469 }
470 return false;
471 }
472
448 473 void ChartDataSet::scrollDomain(qreal dx, qreal dy)
449 474 {
450 475 QList<AbstractDomain*> domains;
451 476 foreach(QAbstractSeries *s, m_seriesList) {
452 477 AbstractDomain* domain = s->d_ptr->domain();
453 478 s->d_ptr->m_domain->blockRangeSignals(true);
454 479 domains<<domain;
455 480 }
456 481
457 482 foreach(AbstractDomain *domain, domains)
458 483 domain->move(dx, dy);
459 484
460 485 foreach(AbstractDomain *domain, domains)
461 486 domain->blockRangeSignals(false);
462 487 }
463 488
464 489 QPointF ChartDataSet::mapToValue(const QPointF &position, QAbstractSeries *series)
465 490 {
466 491 QPointF point;
467 492 if (series == 0 && !m_seriesList.isEmpty())
468 493 series = m_seriesList.first();
469 494
470 495 if (series && series->type() == QAbstractSeries::SeriesTypePie)
471 496 return point;
472 497
473 498 if (series && m_seriesList.contains(series))
474 499 point = series->d_ptr->m_domain->calculateDomainPoint(position - m_chart->plotArea().topLeft());
475 500 return point;
476 501 }
477 502
478 503 QPointF ChartDataSet::mapToPosition(const QPointF &value, QAbstractSeries *series)
479 504 {
480 505 QPointF point = m_chart->plotArea().topLeft();
481 506 if (series == 0 && !m_seriesList.isEmpty())
482 507 series = m_seriesList.first();
483 508
484 509 if (series && series->type() == QAbstractSeries::SeriesTypePie)
485 510 return QPoint(0, 0);
486 511
487 512 bool ok;
488 513 if (series && m_seriesList.contains(series))
489 514 point += series->d_ptr->m_domain->calculateGeometryPoint(value, ok);
490 515 return point;
491 516 }
492 517
493 518 QList<QAbstractAxis *> ChartDataSet::axes() const
494 519 {
495 520 return m_axisList;
496 521 }
497 522
498 523 QList<QAbstractSeries *> ChartDataSet::series() const
499 524 {
500 525 return m_seriesList;
501 526 }
502 527
503 528 AbstractDomain::DomainType ChartDataSet::selectDomain(QList<QAbstractAxis *> axes)
504 529 {
505 530 enum Type {
506 531 Undefined = 0,
507 532 LogType = 0x1,
508 533 ValueType = 0x2
509 534 };
510 535
511 536 int horizontal(Undefined);
512 537 int vertical(Undefined);
513 538
514 539 // Assume cartesian chart type, unless chart is set
515 540 QChart::ChartType chartType(QChart::ChartTypeCartesian);
516 541 if (m_chart)
517 542 chartType = m_chart->chartType();
518 543
519 544 foreach (QAbstractAxis *axis, axes)
520 545 {
521 546 switch (axis->type()) {
522 547 case QAbstractAxis::AxisTypeLogValue:
523 548 if (axis->orientation() == Qt::Horizontal)
524 549 horizontal |= LogType;
525 550 if (axis->orientation() == Qt::Vertical)
526 551 vertical |= LogType;
527 552 break;
528 553 case QAbstractAxis::AxisTypeValue:
529 554 case QAbstractAxis::AxisTypeBarCategory:
530 555 case QAbstractAxis::AxisTypeCategory:
531 556 case QAbstractAxis::AxisTypeDateTime:
532 557 if (axis->orientation() == Qt::Horizontal)
533 558 horizontal |= ValueType;
534 559 if (axis->orientation() == Qt::Vertical)
535 560 vertical |= ValueType;
536 561 break;
537 562 default:
538 563 qWarning() << "Undefined type";
539 564 break;
540 565 }
541 566 }
542 567
543 568 if (vertical == Undefined)
544 569 vertical = ValueType;
545 570 if (horizontal == Undefined)
546 571 horizontal = ValueType;
547 572
548 573 if (vertical == ValueType && horizontal == ValueType) {
549 574 if (chartType == QChart::ChartTypeCartesian)
550 575 return AbstractDomain::XYDomain;
551 576 else if (chartType == QChart::ChartTypePolar)
552 577 return AbstractDomain::XYPolarDomain;
553 578 }
554 579
555 580 if (vertical == LogType && horizontal == ValueType) {
556 581 if (chartType == QChart::ChartTypeCartesian)
557 582 return AbstractDomain::XLogYDomain;
558 583 if (chartType == QChart::ChartTypePolar)
559 584 return AbstractDomain::XLogYPolarDomain;
560 585 }
561 586
562 587 if (vertical == ValueType && horizontal == LogType) {
563 588 if (chartType == QChart::ChartTypeCartesian)
564 589 return AbstractDomain::LogXYDomain;
565 590 else if (chartType == QChart::ChartTypePolar)
566 591 return AbstractDomain::LogXYPolarDomain;
567 592 }
568 593
569 594 if (vertical == LogType && horizontal == LogType) {
570 595 if (chartType == QChart::ChartTypeCartesian)
571 596 return AbstractDomain::LogXLogYDomain;
572 597 else if (chartType == QChart::ChartTypePolar)
573 598 return AbstractDomain::LogXLogYPolarDomain;
574 599 }
575 600
576 601 return AbstractDomain::UndefinedDomain;
577 602 }
578 603
579 604 //refactor create factory
580 605 AbstractDomain* ChartDataSet::createDomain(AbstractDomain::DomainType type)
581 606 {
582 607 switch (type)
583 608 {
584 609 case AbstractDomain::LogXLogYDomain:
585 610 return new LogXLogYDomain();
586 611 case AbstractDomain::XYDomain:
587 612 return new XYDomain();
588 613 case AbstractDomain::XLogYDomain:
589 614 return new XLogYDomain();
590 615 case AbstractDomain::LogXYDomain:
591 616 return new LogXYDomain();
592 617 case AbstractDomain::XYPolarDomain:
593 618 return new XYPolarDomain();
594 619 case AbstractDomain::XLogYPolarDomain:
595 620 return new XLogYPolarDomain();
596 621 case AbstractDomain::LogXYPolarDomain:
597 622 return new LogXYPolarDomain();
598 623 case AbstractDomain::LogXLogYPolarDomain:
599 624 return new LogXLogYPolarDomain();
600 625 default:
601 626 return 0;
602 627 }
603 628 }
604 629
605 630 #include "moc_chartdataset_p.cpp"
606 631
607 632 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,92 +1,94
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef CHARTDATASET_P_H
31 31 #define CHARTDATASET_P_H
32 32
33 33 #include "qabstractseries.h"
34 34 #include "abstractdomain_p.h"
35 35 #include "qabstractaxis_p.h"
36 36 #include <QVector>
37 37
38 38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
39 39
40 40 class QAbstractAxis;
41 41 class ChartPresenter;
42 42
43 43 class QTCOMMERCIALCHART_AUTOTEST_EXPORT ChartDataSet : public QObject
44 44 {
45 45 Q_OBJECT
46 46 public:
47 47 ChartDataSet(QChart *chart);
48 48 virtual ~ChartDataSet();
49 49
50 50 void addSeries(QAbstractSeries *series);
51 51 void removeSeries(QAbstractSeries *series);
52 52 QList<QAbstractSeries *> series() const;
53 53
54 54 void addAxis(QAbstractAxis *axis,Qt::Alignment aligment);
55 55 void removeAxis(QAbstractAxis *axis);
56 56 QList<QAbstractAxis*> axes() const;
57 57
58 58 bool attachAxis(QAbstractSeries* series,QAbstractAxis *axis);
59 59 bool detachAxis(QAbstractSeries* series,QAbstractAxis *axis);
60 60
61 61 void createDefaultAxes();
62 62
63 63 void zoomInDomain(const QRectF &rect);
64 64 void zoomOutDomain(const QRectF &rect);
65 void zoomResetDomain();
66 bool isZoomedDomain();
65 67 void scrollDomain(qreal dx, qreal dy);
66 68
67 69 QPointF mapToValue(const QPointF &position, QAbstractSeries *series = 0);
68 70 QPointF mapToPosition(const QPointF &value, QAbstractSeries *series = 0);
69 71
70 72 Q_SIGNALS:
71 73 void axisAdded(QAbstractAxis* axis);
72 74 void axisRemoved(QAbstractAxis* axis);
73 75 void seriesAdded(QAbstractSeries* series);
74 76 void seriesRemoved(QAbstractSeries* series);
75 77
76 78 private:
77 79 void createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation);
78 80 QAbstractAxis *createAxis(QAbstractAxis::AxisType type, Qt::Orientation orientation);
79 81 AbstractDomain::DomainType selectDomain(QList<QAbstractAxis* > axes);
80 82 AbstractDomain* createDomain(AbstractDomain::DomainType type);
81 83 void deleteAllAxes();
82 84 void deleteAllSeries();
83 85 void findMinMaxForSeries(QList<QAbstractSeries *> series,Qt::Orientations orientation, qreal &min, qreal &max);
84 86 private:
85 87 QList<QAbstractSeries *> m_seriesList;
86 88 QList<QAbstractAxis *> m_axisList;
87 89 QChart* m_chart;
88 90 };
89 91
90 92 QTCOMMERCIALCHART_END_NAMESPACE
91 93
92 94 #endif /* CHARTENGINE_P_H */
@@ -1,234 +1,262
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "abstractdomain_p.h"
22 22 #include "qabstractaxis_p.h"
23 23 #include <qmath.h>
24 24
25 25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 26
27 27 AbstractDomain::AbstractDomain(QObject *parent)
28 28 : QObject(parent),
29 29 m_minX(0),
30 30 m_maxX(0),
31 31 m_minY(0),
32 32 m_maxY(0),
33 m_signalsBlocked(false)
33 m_signalsBlocked(false),
34 m_zoomed(false),
35 m_zoomResetMinX(0),
36 m_zoomResetMaxX(0),
37 m_zoomResetMinY(0),
38 m_zoomResetMaxY(0)
39
34 40 {
35 41 }
36 42
37 43 AbstractDomain::~AbstractDomain()
38 44 {
39 45 }
40 46
41 47 void AbstractDomain::setSize(const QSizeF &size)
42 48 {
43 49 if(m_size!=size)
44 50 {
45 51 m_size=size;
46 52 emit updated();
47 53 }
48 54 }
49 55
50 56 QSizeF AbstractDomain::size() const
51 57 {
52 58 return m_size;
53 59 }
54 60
55 61 void AbstractDomain::setRangeX(qreal min, qreal max)
56 62 {
57 63 setRange(min, max, m_minY, m_maxY);
58 64 }
59 65
60 66 void AbstractDomain::setRangeY(qreal min, qreal max)
61 67 {
62 68 setRange(m_minX, m_maxX, min, max);
63 69 }
64 70
65 71 void AbstractDomain::setMinX(qreal min)
66 72 {
67 73 setRange(min, m_maxX, m_minY, m_maxY);
68 74 }
69 75
70 76 void AbstractDomain::setMaxX(qreal max)
71 77 {
72 78 setRange(m_minX, max, m_minY, m_maxY);
73 79 }
74 80
75 81 void AbstractDomain::setMinY(qreal min)
76 82 {
77 83 setRange(m_minX, m_maxX, min, m_maxY);
78 84 }
79 85
80 86 void AbstractDomain::setMaxY(qreal max)
81 87 {
82 88 setRange(m_minX, m_maxX, m_minY, max);
83 89 }
84 90
85 91 qreal AbstractDomain::spanX() const
86 92 {
87 93 Q_ASSERT(m_maxX >= m_minX);
88 94 return m_maxX - m_minX;
89 95 }
90 96
91 97 qreal AbstractDomain::spanY() const
92 98 {
93 99 Q_ASSERT(m_maxY >= m_minY);
94 100 return m_maxY - m_minY;
95 101 }
96 102
97 103 bool AbstractDomain::isEmpty() const
98 104 {
99 105 return qFuzzyIsNull(spanX()) || qFuzzyIsNull(spanY()) || m_size.isEmpty() ;
100 106 }
101 107
102 108 QPointF AbstractDomain::calculateDomainPoint(const QPointF &point) const
103 109 {
104 110 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
105 111 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
106 112 qreal x = point.x() / deltaX + m_minX;
107 113 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
108 114 return QPointF(x, y);
109 115 }
110 116
111 117 // handlers
112 118
113 119 void AbstractDomain::handleVerticalAxisRangeChanged(qreal min, qreal max)
114 120 {
115 121 setRangeY(min, max);
116 122 }
117 123
118 124 void AbstractDomain::handleHorizontalAxisRangeChanged(qreal min, qreal max)
119 125 {
120 126 setRangeX(min, max);
121 127 }
122 128
123 129 void AbstractDomain::blockRangeSignals(bool block)
124 130 {
125 131 if (m_signalsBlocked!=block) {
126 132 m_signalsBlocked=block;
127 133 if (!block) {
128 134 emit rangeHorizontalChanged(m_minX,m_maxX);
129 135 emit rangeVerticalChanged(m_minY,m_maxY);
130 136 }
131 137 }
132 138 }
133 139
140 void AbstractDomain::zoomReset()
141 {
142 if (m_zoomed) {
143 setRange(m_zoomResetMinX,
144 m_zoomResetMaxX,
145 m_zoomResetMinY,
146 m_zoomResetMaxY);
147 m_zoomed = false;
148 }
149 }
150
151 void AbstractDomain::storeZoomReset()
152 {
153 if (!m_zoomed) {
154 m_zoomed = true;
155 m_zoomResetMinX = m_minX;
156 m_zoomResetMaxX = m_maxX;
157 m_zoomResetMinY = m_minY;
158 m_zoomResetMaxY = m_maxY;
159 }
160 }
161
134 162 //algorithm defined by Paul S.Heckbert GraphicalGems I
135 163
136 164 void AbstractDomain::looseNiceNumbers(qreal &min, qreal &max, int &ticksCount)
137 165 {
138 166 qreal range = niceNumber(max - min, true); //range with ceiling
139 167 qreal step = niceNumber(range / (ticksCount - 1), false);
140 168 min = qFloor(min / step);
141 169 max = qCeil(max / step);
142 170 ticksCount = int(max - min) + 1;
143 171 min *= step;
144 172 max *= step;
145 173 }
146 174
147 175 //nice numbers can be expressed as form of 1*10^n, 2* 10^n or 5*10^n
148 176
149 177 qreal AbstractDomain::niceNumber(qreal x, bool ceiling)
150 178 {
151 179 qreal z = qPow(10, qFloor(log10(x))); //find corresponding number of the form of 10^n than is smaller than x
152 180 qreal q = x / z; //q<10 && q>=1;
153 181
154 182 if (ceiling) {
155 183 if (q <= 1.0) q = 1;
156 184 else if (q <= 2.0) q = 2;
157 185 else if (q <= 5.0) q = 5;
158 186 else q = 10;
159 187 } else {
160 188 if (q < 1.5) q = 1;
161 189 else if (q < 3.0) q = 2;
162 190 else if (q < 7.0) q = 5;
163 191 else q = 10;
164 192 }
165 193 return q * z;
166 194 }
167 195
168 196 bool AbstractDomain::attachAxis(QAbstractAxis *axis)
169 197 {
170 198 if (axis->orientation() == Qt::Vertical) {
171 199 QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
172 200 QObject::connect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
173 201 }
174 202
175 203 if (axis->orientation() == Qt::Horizontal) {
176 204 QObject::connect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
177 205 QObject::connect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
178 206 }
179 207
180 208 return true;
181 209 }
182 210
183 211 bool AbstractDomain::detachAxis(QAbstractAxis *axis)
184 212 {
185 213 if (axis->orientation() == Qt::Vertical) {
186 214 QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleVerticalAxisRangeChanged(qreal,qreal)));
187 215 QObject::disconnect(this, SIGNAL(rangeVerticalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
188 216 }
189 217
190 218 if (axis->orientation() == Qt::Horizontal) {
191 219 QObject::disconnect(axis->d_ptr.data(), SIGNAL(rangeChanged(qreal,qreal)), this, SLOT(handleHorizontalAxisRangeChanged(qreal,qreal)));
192 220 QObject::disconnect(this, SIGNAL(rangeHorizontalChanged(qreal,qreal)), axis->d_ptr.data(), SLOT(handleRangeChanged(qreal,qreal)));
193 221 }
194 222
195 223 return true;
196 224 }
197 225
198 226 // operators
199 227
200 228 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2)
201 229 {
202 230 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
203 231 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
204 232 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
205 233 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
206 234 }
207 235
208 236
209 237 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2)
210 238 {
211 239 return !(domain1 == domain2);
212 240 }
213 241
214 242
215 243 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain)
216 244 {
217 245 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
218 246 return dbg.maybeSpace();
219 247 }
220 248
221 249 // This function adjusts min/max ranges to failsafe values if negative/zero values are attempted.
222 250 void AbstractDomain::adjustLogDomainRanges(qreal &min, qreal &max)
223 251 {
224 252 if (min <= 0) {
225 253 min = 1.0;
226 254 if (max <= min)
227 255 max = min + 1.0;
228 256 }
229 257 }
230 258
231 259
232 260 #include "moc_abstractdomain_p.cpp"
233 261
234 262 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,123 +1,132
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef ABSTRACTDOMAIN_H
31 31 #define ABSTRACTDOMAIN_H
32 32 #include "qchartglobal.h"
33 33 #include <QRectF>
34 34 #include <QSizeF>
35 35 #include <QDebug>
36 36
37 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 38
39 39 class QAbstractAxis;
40 40
41 41 class QTCOMMERCIALCHART_AUTOTEST_EXPORT AbstractDomain: public QObject
42 42 {
43 43 Q_OBJECT
44 44 public:
45 45 enum DomainType { UndefinedDomain,
46 46 XYDomain,
47 47 XLogYDomain,
48 48 LogXYDomain,
49 49 LogXLogYDomain,
50 50 XYPolarDomain,
51 51 XLogYPolarDomain,
52 52 LogXYPolarDomain,
53 53 LogXLogYPolarDomain };
54 54 public:
55 55 explicit AbstractDomain(QObject *object = 0);
56 56 virtual ~AbstractDomain();
57 57
58 58 virtual void setSize(const QSizeF &size);
59 59 QSizeF size() const;
60 60
61 61 virtual DomainType type() = 0;
62 62
63 63 virtual void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) = 0;
64 64 void setRangeX(qreal min, qreal max);
65 65 void setRangeY(qreal min, qreal max);
66 66 void setMinX(qreal min);
67 67 void setMaxX(qreal max);
68 68 void setMinY(qreal min);
69 69 void setMaxY(qreal max);
70 70
71 71 qreal minX() const { return m_minX; }
72 72 qreal maxX() const { return m_maxX; }
73 73 qreal minY() const { return m_minY; }
74 74 qreal maxY() const { return m_maxY; }
75 75
76 76 qreal spanX() const;
77 77 qreal spanY() const;
78 78 bool isEmpty() const;
79 79
80 80 void blockRangeSignals(bool block);
81 81 bool rangeSignalsBlocked() const { return m_signalsBlocked; }
82 82
83 void zoomReset();
84 void storeZoomReset();
85 bool isZoomed() { return m_zoomed; }
86
83 87 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2);
84 88 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2);
85 89 friend QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain);
86 90
87 91 virtual void zoomIn(const QRectF &rect) = 0;
88 92 virtual void zoomOut(const QRectF &rect) = 0;
89 93 virtual void move(qreal dx, qreal dy) = 0;
90 94
91 95 virtual QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const = 0;
92 96 virtual QPointF calculateDomainPoint(const QPointF &point) const = 0;
93 97 virtual QVector<QPointF> calculateGeometryPoints(const QList<QPointF> &vector) const = 0;
94 98
95 99 virtual bool attachAxis(QAbstractAxis *axis);
96 100 virtual bool detachAxis(QAbstractAxis *axis);
97 101
98 102 static void looseNiceNumbers(qreal &min, qreal &max, int &ticksCount);
99 103 static qreal niceNumber(qreal x, bool ceiling);
100 104
101 105 Q_SIGNALS:
102 106 void updated();
103 107 void rangeHorizontalChanged(qreal min, qreal max);
104 108 void rangeVerticalChanged(qreal min, qreal max);
105 109
106 110 public Q_SLOTS:
107 111 void handleVerticalAxisRangeChanged(qreal min,qreal max);
108 112 void handleHorizontalAxisRangeChanged(qreal min,qreal max);
109 113
110 114 protected:
111 115 void adjustLogDomainRanges(qreal &min, qreal &max);
112 116
113 117 qreal m_minX;
114 118 qreal m_maxX;
115 119 qreal m_minY;
116 120 qreal m_maxY;
117 121 QSizeF m_size;
118 122 bool m_signalsBlocked;
123 bool m_zoomed;
124 qreal m_zoomResetMinX;
125 qreal m_zoomResetMaxX;
126 qreal m_zoomResetMinY;
127 qreal m_zoomResetMaxY;
119 128 };
120 129
121 130 QTCOMMERCIALCHART_END_NAMESPACE
122 131
123 132 #endif // ABSTRACTDOMAIN_H
@@ -1,261 +1,263
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "logxlogydomain_p.h"
22 22 #include "qabstractaxis_p.h"
23 23 #include "qlogvalueaxis.h"
24 24 #include <qmath.h>
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 LogXLogYDomain::LogXLogYDomain(QObject *parent)
29 29 : AbstractDomain(parent),
30 30 m_logLeftX(0),
31 31 m_logRightX(1),
32 32 m_logBaseX(10),
33 33 m_logLeftY(0),
34 34 m_logRightY(1),
35 35 m_logBaseY(10)
36 36 {
37 37 }
38 38
39 39 LogXLogYDomain::~LogXLogYDomain()
40 40 {
41 41 }
42 42
43 43 void LogXLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
44 44 {
45 45 bool axisXChanged = false;
46 46 bool axisYChanged = false;
47 47
48 48 adjustLogDomainRanges(minX, maxX);
49 49 adjustLogDomainRanges(minY, maxY);
50 50
51 51 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
52 52 m_minX = minX;
53 53 m_maxX = maxX;
54 54 axisXChanged = true;
55 55 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
56 56 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
57 57 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
58 58 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
59 59 if(!m_signalsBlocked)
60 60 emit rangeHorizontalChanged(m_minX, m_maxX);
61 61 }
62 62
63 63 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
64 64 m_minY = minY;
65 65 m_maxY = maxY;
66 66 axisYChanged = true;
67 67 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
68 68 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
69 69 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
70 70 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
71 71 if (!m_signalsBlocked)
72 72 emit rangeVerticalChanged(m_minY, m_maxY);
73 73 }
74 74
75 75 if (axisXChanged || axisYChanged)
76 76 emit updated();
77 77 }
78 78
79 79 void LogXLogYDomain::zoomIn(const QRectF &rect)
80 80 {
81 storeZoomReset();
81 82 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
82 83 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
83 84 qreal leftX = qPow(m_logBaseX, logLeftX);
84 85 qreal rightX = qPow(m_logBaseX, logRightX);
85 86 qreal minX = leftX < rightX ? leftX : rightX;
86 87 qreal maxX = leftX > rightX ? leftX : rightX;
87 88
88 89 qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
89 90 qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
90 91 qreal leftY = qPow(m_logBaseY, logLeftY);
91 92 qreal rightY = qPow(m_logBaseY, logRightY);
92 93 qreal minY = leftY < rightY ? leftY : rightY;
93 94 qreal maxY = leftY > rightY ? leftY : rightY;
94 95
95 96 setRange(minX, maxX, minY, maxY);
96 97 }
97 98
98 99 void LogXLogYDomain::zoomOut(const QRectF &rect)
99 100 {
101 storeZoomReset();
100 102 const qreal factorX = m_size.width() / rect.width();
101 103 const qreal factorY = m_size.height() / rect.height();
102 104
103 105 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
104 106 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
105 107 qreal leftX = qPow(m_logBaseX, logLeftX);
106 108 qreal rightX = qPow(m_logBaseX, logRIghtX);
107 109 qreal minX = leftX < rightX ? leftX : rightX;
108 110 qreal maxX = leftX > rightX ? leftX : rightX;
109 111
110 112 qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
111 113 qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
112 114 qreal leftY = qPow(m_logBaseY, newLogMinY);
113 115 qreal rightY = qPow(m_logBaseY, newLogMaxY);
114 116 qreal minY = leftY < rightY ? leftY : rightY;
115 117 qreal maxY = leftY > rightY ? leftY : rightY;
116 118
117 119 setRange(minX, maxX, minY, maxY);
118 120 }
119 121
120 122 void LogXLogYDomain::move(qreal dx, qreal dy)
121 123 {
122 124 qreal stepX = dx * qAbs(m_logRightX - m_logLeftX) / m_size.width();
123 125 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
124 126 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
125 127 qreal minX = leftX < rightX ? leftX : rightX;
126 128 qreal maxX = leftX > rightX ? leftX : rightX;
127 129
128 130 qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
129 131 qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
130 132 qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
131 133 qreal minY = leftY < rightY ? leftY : rightY;
132 134 qreal maxY = leftY > rightY ? leftY : rightY;
133 135
134 136 setRange(minX, maxX, minY, maxY);
135 137 }
136 138
137 139 QPointF LogXLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
138 140 {
139 141 if (point.x() > 0 && point.y() > 0) {
140 142 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
141 143 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
142 144 qreal x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
143 145 qreal y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
144 146 ok = true;
145 147 return QPointF(x, y);
146 148 } else {
147 149 qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
148 150 ok = false;
149 151 return QPointF();
150 152 }
151 153 }
152 154
153 155 QVector<QPointF> LogXLogYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
154 156 {
155 157 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
156 158 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
157 159
158 160 QVector<QPointF> result;
159 161 result.resize(vector.count());
160 162
161 163 for (int i = 0; i < vector.count(); ++i) {
162 164 if (vector[i].x() > 0 && vector[i].y() > 0) {
163 165 qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
164 166 qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
165 167 result[i].setX(x);
166 168 result[i].setY(y);
167 169 } else {
168 170 qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
169 171 return QVector<QPointF>();
170 172 }
171 173 }
172 174 return result;
173 175 }
174 176
175 177 QPointF LogXLogYDomain::calculateDomainPoint(const QPointF &point) const
176 178 {
177 179 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
178 180 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
179 181 qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
180 182 qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
181 183 return QPointF(x, y);
182 184 }
183 185
184 186 bool LogXLogYDomain::attachAxis(QAbstractAxis *axis)
185 187 {
186 188 AbstractDomain::attachAxis(axis);
187 189 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
188 190
189 191 if (logAxis && logAxis->orientation() == Qt::Vertical) {
190 192 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
191 193 handleVerticalAxisBaseChanged(logAxis->base());
192 194 }
193 195
194 196 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
195 197 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
196 198 handleHorizontalAxisBaseChanged(logAxis->base());
197 199 }
198 200
199 201 return true;
200 202 }
201 203
202 204 bool LogXLogYDomain::detachAxis(QAbstractAxis *axis)
203 205 {
204 206 AbstractDomain::detachAxis(axis);
205 207 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
206 208
207 209 if (logAxis && logAxis->orientation() == Qt::Vertical)
208 210 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
209 211
210 212 if (logAxis && logAxis->orientation() == Qt::Horizontal)
211 213 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
212 214
213 215 return true;
214 216 }
215 217
216 218 void LogXLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
217 219 {
218 220 m_logBaseY = baseY;
219 221 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
220 222 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
221 223 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
222 224 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
223 225 emit updated();
224 226 }
225 227
226 228 void LogXLogYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
227 229 {
228 230 m_logBaseX = baseX;
229 231 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
230 232 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
231 233 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
232 234 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
233 235 emit updated();
234 236 }
235 237
236 238 // operators
237 239
238 240 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
239 241 {
240 242 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
241 243 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
242 244 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
243 245 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
244 246 }
245 247
246 248
247 249 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
248 250 {
249 251 return !(domain1 == domain2);
250 252 }
251 253
252 254
253 255 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYDomain &domain)
254 256 {
255 257 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
256 258 return dbg.maybeSpace();
257 259 }
258 260
259 261 #include "moc_logxlogydomain_p.cpp"
260 262
261 263 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,267 +1,269
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "logxlogypolardomain_p.h"
22 22 #include "qabstractaxis_p.h"
23 23 #include "qlogvalueaxis.h"
24 24 #include <qmath.h>
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 LogXLogYPolarDomain::LogXLogYPolarDomain(QObject *parent)
29 29 : PolarDomain(parent),
30 30 m_logLeftX(0),
31 31 m_logRightX(1),
32 32 m_logBaseX(10),
33 33 m_logInnerY(0),
34 34 m_logOuterY(1),
35 35 m_logBaseY(10)
36 36 {
37 37 }
38 38
39 39 LogXLogYPolarDomain::~LogXLogYPolarDomain()
40 40 {
41 41 }
42 42
43 43 void LogXLogYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
44 44 {
45 45 bool axisXChanged = false;
46 46 bool axisYChanged = false;
47 47
48 48 adjustLogDomainRanges(minX, maxX);
49 49 adjustLogDomainRanges(minY, maxY);
50 50
51 51 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
52 52 m_minX = minX;
53 53 m_maxX = maxX;
54 54 axisXChanged = true;
55 55 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
56 56 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
57 57 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
58 58 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
59 59 if (!m_signalsBlocked)
60 60 emit rangeHorizontalChanged(m_minX, m_maxX);
61 61 }
62 62
63 63 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
64 64 m_minY = minY;
65 65 m_maxY = maxY;
66 66 axisYChanged = true;
67 67 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
68 68 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
69 69 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
70 70 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
71 71 if (!m_signalsBlocked)
72 72 emit rangeVerticalChanged(m_minY, m_maxY);
73 73 }
74 74
75 75 if (axisXChanged || axisYChanged)
76 76 emit updated();
77 77 }
78 78
79 79 void LogXLogYPolarDomain::zoomIn(const QRectF &rect)
80 80 {
81 storeZoomReset();
81 82 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
82 83 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
83 84 qreal leftX = qPow(m_logBaseX, logLeftX);
84 85 qreal rightX = qPow(m_logBaseX, logRightX);
85 86 qreal minX = leftX < rightX ? leftX : rightX;
86 87 qreal maxX = leftX > rightX ? leftX : rightX;
87 88
88 89 qreal logLeftY = m_logOuterY - rect.bottom() * (m_logOuterY - m_logInnerY) / m_size.height();
89 90 qreal logRightY = m_logOuterY - rect.top() * (m_logOuterY - m_logInnerY) / m_size.height();
90 91 qreal leftY = qPow(m_logBaseY, logLeftY);
91 92 qreal rightY = qPow(m_logBaseY, logRightY);
92 93 qreal minY = leftY < rightY ? leftY : rightY;
93 94 qreal maxY = leftY > rightY ? leftY : rightY;
94 95
95 96 setRange(minX, maxX, minY, maxY);
96 97 }
97 98
98 99 void LogXLogYPolarDomain::zoomOut(const QRectF &rect)
99 100 {
101 storeZoomReset();
100 102 const qreal factorX = m_size.width() / rect.width();
101 103
102 104 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 - factorX);
103 105 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 + factorX);
104 106 qreal leftX = qPow(m_logBaseX, logLeftX);
105 107 qreal rightX = qPow(m_logBaseX, logRIghtX);
106 108 qreal minX = leftX < rightX ? leftX : rightX;
107 109 qreal maxX = leftX > rightX ? leftX : rightX;
108 110
109 111 const qreal factorY = m_size.height() / rect.height();
110 112 qreal newLogMinY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 - factorY);
111 113 qreal newLogMaxY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 + factorY);
112 114 qreal leftY = qPow(m_logBaseY, newLogMinY);
113 115 qreal rightY = qPow(m_logBaseY, newLogMaxY);
114 116 qreal minY = leftY < rightY ? leftY : rightY;
115 117 qreal maxY = leftY > rightY ? leftY : rightY;
116 118
117 119 setRange(minX, maxX, minY, maxY);
118 120 }
119 121
120 122 void LogXLogYPolarDomain::move(qreal dx, qreal dy)
121 123 {
122 124 qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
123 125 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
124 126 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
125 127 qreal minX = leftX < rightX ? leftX : rightX;
126 128 qreal maxX = leftX > rightX ? leftX : rightX;
127 129
128 130 qreal stepY = dy * (m_logOuterY - m_logInnerY) / m_radius;
129 131 qreal leftY = qPow(m_logBaseY, m_logInnerY + stepY);
130 132 qreal rightY = qPow(m_logBaseY, m_logOuterY + stepY);
131 133 qreal minY = leftY < rightY ? leftY : rightY;
132 134 qreal maxY = leftY > rightY ? leftY : rightY;
133 135
134 136 setRange(minX, maxX, minY, maxY);
135 137 }
136 138
137 139 qreal LogXLogYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
138 140 {
139 141 qreal retVal;
140 142 if (value <= 0) {
141 143 ok = false;
142 144 retVal = 0.0;
143 145 } else {
144 146 ok = true;
145 147 const qreal tickSpan = 360.0 / qAbs(m_logRightX - m_logLeftX);
146 148 const qreal logValue = log10(value) / log10(m_logBaseX);
147 149 const qreal valueDelta = logValue - m_logLeftX;
148 150
149 151 retVal = valueDelta * tickSpan;
150 152 }
151 153 return retVal;
152 154 }
153 155
154 156 qreal LogXLogYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
155 157 {
156 158 qreal retVal;
157 159 if (value <= 0) {
158 160 ok = false;
159 161 retVal = 0.0;
160 162 } else {
161 163 ok = true;
162 164 const qreal tickSpan = m_radius / qAbs(m_logOuterY - m_logInnerY);
163 165 const qreal logValue = log10(value) / log10(m_logBaseY);
164 166 const qreal valueDelta = logValue - m_logInnerY;
165 167
166 168 retVal = valueDelta * tickSpan;
167 169
168 170 if (retVal < 0.0)
169 171 retVal = 0.0;
170 172 }
171 173 return retVal;
172 174 }
173 175
174 176 QPointF LogXLogYPolarDomain::calculateDomainPoint(const QPointF &point) const
175 177 {
176 178 if (point == m_center)
177 179 return QPointF(0.0, m_minY);
178 180
179 181 QLineF line(m_center, point);
180 182 qreal a = 90.0 - line.angle();
181 183 if (a < 0.0)
182 184 a += 360.0;
183 185
184 186 const qreal deltaX = 360.0 / qAbs(m_logRightX - m_logLeftX);
185 187 a = qPow(m_logBaseX, m_logLeftX + (a / deltaX));
186 188
187 189 const qreal deltaY = m_radius / qAbs(m_logOuterY - m_logInnerY);
188 190 qreal r = qPow(m_logBaseY, m_logInnerY + (line.length() / deltaY));
189 191
190 192 return QPointF(a, r);
191 193 }
192 194
193 195 bool LogXLogYPolarDomain::attachAxis(QAbstractAxis *axis)
194 196 {
195 197 AbstractDomain::attachAxis(axis);
196 198 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
197 199
198 200 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
199 201 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
200 202 handleHorizontalAxisBaseChanged(logAxis->base());
201 203 } else if (logAxis && logAxis->orientation() == Qt::Vertical){
202 204 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
203 205 handleVerticalAxisBaseChanged(logAxis->base());
204 206 }
205 207
206 208 return true;
207 209 }
208 210
209 211 bool LogXLogYPolarDomain::detachAxis(QAbstractAxis *axis)
210 212 {
211 213 AbstractDomain::detachAxis(axis);
212 214 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
213 215
214 216 if (logAxis && logAxis->orientation() == Qt::Horizontal)
215 217 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
216 218 else if (logAxis && logAxis->orientation() == Qt::Vertical)
217 219 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
218 220
219 221 return true;
220 222 }
221 223
222 224 void LogXLogYPolarDomain::handleHorizontalAxisBaseChanged(qreal baseX)
223 225 {
224 226 m_logBaseX = baseX;
225 227 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
226 228 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
227 229 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
228 230 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
229 231 emit updated();
230 232 }
231 233
232 234 void LogXLogYPolarDomain::handleVerticalAxisBaseChanged(qreal baseY)
233 235 {
234 236 m_logBaseY = baseY;
235 237 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
236 238 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
237 239 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
238 240 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
239 241 emit updated();
240 242 }
241 243
242 244 // operators
243 245
244 246 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2)
245 247 {
246 248 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
247 249 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
248 250 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
249 251 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
250 252 }
251 253
252 254
253 255 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const LogXLogYPolarDomain &domain1, const LogXLogYPolarDomain &domain2)
254 256 {
255 257 return !(domain1 == domain2);
256 258 }
257 259
258 260
259 261 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYPolarDomain &domain)
260 262 {
261 263 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
262 264 return dbg.maybeSpace();
263 265 }
264 266
265 267 #include "moc_logxlogypolardomain_p.cpp"
266 268
267 269 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,238 +1,240
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "logxydomain_p.h"
22 22 #include "qabstractaxis_p.h"
23 23 #include "qlogvalueaxis.h"
24 24 #include <qmath.h>
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 LogXYDomain::LogXYDomain(QObject *parent)
29 29 : AbstractDomain(parent),
30 30 m_logLeftX(0),
31 31 m_logRightX(1),
32 32 m_logBaseX(10)
33 33 {
34 34 }
35 35
36 36 LogXYDomain::~LogXYDomain()
37 37 {
38 38 }
39 39
40 40 void LogXYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
41 41 {
42 42 bool axisXChanged = false;
43 43 bool axisYChanged = false;
44 44
45 45 adjustLogDomainRanges(minX, maxX);
46 46
47 47 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
48 48 m_minX = minX;
49 49 m_maxX = maxX;
50 50 axisXChanged = true;
51 51 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
52 52 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
53 53 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
54 54 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
55 55 if(!m_signalsBlocked)
56 56 emit rangeHorizontalChanged(m_minX, m_maxX);
57 57 }
58 58
59 59 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
60 60 m_minY = minY;
61 61 m_maxY = maxY;
62 62 axisYChanged = true;
63 63 if (!m_signalsBlocked)
64 64 emit rangeVerticalChanged(m_minY, m_maxY);
65 65 }
66 66
67 67 if (axisXChanged || axisYChanged)
68 68 emit updated();
69 69 }
70 70
71 71 void LogXYDomain::zoomIn(const QRectF &rect)
72 72 {
73 storeZoomReset();
73 74 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
74 75 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
75 76 qreal leftX = qPow(m_logBaseX, logLeftX);
76 77 qreal rightX = qPow(m_logBaseX, logRightX);
77 78 qreal minX = leftX < rightX ? leftX : rightX;
78 79 qreal maxX = leftX > rightX ? leftX : rightX;
79 80
80 81 qreal dy = spanY() / m_size.height();
81 82 qreal minY = m_minY;
82 83 qreal maxY = m_maxY;
83 84
84 85 minY = maxY - dy * rect.bottom();
85 86 maxY = maxY - dy * rect.top();
86 87
87 88 setRange(minX, maxX, minY, maxY);
88 89 }
89 90
90 91 void LogXYDomain::zoomOut(const QRectF &rect)
91 92 {
93 storeZoomReset();
92 94 const qreal factorX = m_size.width() / rect.width();
93 95
94 96 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
95 97 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
96 98 qreal leftX = qPow(m_logBaseX, logLeftX);
97 99 qreal rightX = qPow(m_logBaseX, logRIghtX);
98 100 qreal minX = leftX < rightX ? leftX : rightX;
99 101 qreal maxX = leftX > rightX ? leftX : rightX;
100 102
101 103 qreal dy = spanY() / rect.height();
102 104 qreal minY = m_minY;
103 105 qreal maxY = m_maxY;
104 106
105 107 maxY = minY + dy * rect.bottom();
106 108 minY = maxY - dy * m_size.height();
107 109
108 110 setRange(minX, maxX, minY, maxY);
109 111 }
110 112
111 113 void LogXYDomain::move(qreal dx, qreal dy)
112 114 {
113 115 qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
114 116 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
115 117 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
116 118 qreal minX = leftX < rightX ? leftX : rightX;
117 119 qreal maxX = leftX > rightX ? leftX : rightX;
118 120
119 121 qreal y = spanY() / m_size.height();
120 122 qreal minY = m_minY;
121 123 qreal maxY = m_maxY;
122 124
123 125 if (dy != 0) {
124 126 minY = minY + y * dy;
125 127 maxY = maxY + y * dy;
126 128 }
127 129 setRange(minX, maxX, minY, maxY);
128 130 }
129 131
130 132 QPointF LogXYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
131 133 {
132 134
133 135 if (point.x() > 0) {
134 136 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
135 137 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
136 138
137 139 qreal x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
138 140 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
139 141 ok = true;
140 142 return QPointF(x, y);
141 143 } else {
142 144 qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
143 145 ok = false;
144 146 return QPointF();
145 147 }
146 148 }
147 149
148 150 QVector<QPointF> LogXYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
149 151 {
150 152 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
151 153 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
152 154
153 155 QVector<QPointF> result;
154 156 result.resize(vector.count());
155 157
156 158 for (int i = 0; i < vector.count(); ++i) {
157 159 if (vector[i].x() > 0) {
158 160 qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
159 161 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
160 162 result[i].setX(x);
161 163 result[i].setY(y);
162 164 } else {
163 165 qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
164 166 return QVector<QPointF>();
165 167 }
166 168 }
167 169 return result;
168 170 }
169 171
170 172 QPointF LogXYDomain::calculateDomainPoint(const QPointF &point) const
171 173 {
172 174 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
173 175 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
174 176 qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
175 177 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
176 178 return QPointF(x, y);
177 179 }
178 180
179 181 bool LogXYDomain::attachAxis(QAbstractAxis *axis)
180 182 {
181 183 AbstractDomain::attachAxis(axis);
182 184 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
183 185
184 186 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
185 187 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
186 188 handleHorizontalAxisBaseChanged(logAxis->base());
187 189 }
188 190
189 191 return true;
190 192 }
191 193
192 194 bool LogXYDomain::detachAxis(QAbstractAxis *axis)
193 195 {
194 196 AbstractDomain::detachAxis(axis);
195 197 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
196 198
197 199 if (logAxis && logAxis->orientation() == Qt::Horizontal)
198 200 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
199 201
200 202 return true;
201 203 }
202 204
203 205 void LogXYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
204 206 {
205 207 m_logBaseX = baseX;
206 208 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
207 209 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
208 210 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
209 211 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
210 212 emit updated();
211 213 }
212 214
213 215 // operators
214 216
215 217 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const LogXYDomain &domain1, const LogXYDomain &domain2)
216 218 {
217 219 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
218 220 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
219 221 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
220 222 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
221 223 }
222 224
223 225
224 226 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const LogXYDomain &domain1, const LogXYDomain &domain2)
225 227 {
226 228 return !(domain1 == domain2);
227 229 }
228 230
229 231
230 232 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYDomain &domain)
231 233 {
232 234 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
233 235 return dbg.maybeSpace();
234 236 }
235 237
236 238 #include "moc_logxydomain_p.cpp"
237 239
238 240 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,236 +1,238
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "logxypolardomain_p.h"
22 22 #include "qabstractaxis_p.h"
23 23 #include "qlogvalueaxis.h"
24 24 #include <qmath.h>
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 LogXYPolarDomain::LogXYPolarDomain(QObject *parent)
29 29 : PolarDomain(parent),
30 30 m_logLeftX(0),
31 31 m_logRightX(1),
32 32 m_logBaseX(10)
33 33 {
34 34 }
35 35
36 36 LogXYPolarDomain::~LogXYPolarDomain()
37 37 {
38 38 }
39 39
40 40 void LogXYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
41 41 {
42 42 bool axisXChanged = false;
43 43 bool axisYChanged = false;
44 44
45 45 adjustLogDomainRanges(minX, maxX);
46 46
47 47 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
48 48 m_minX = minX;
49 49 m_maxX = maxX;
50 50 axisXChanged = true;
51 51 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
52 52 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
53 53 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
54 54 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
55 55 if (!m_signalsBlocked)
56 56 emit rangeHorizontalChanged(m_minX, m_maxX);
57 57 }
58 58
59 59 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
60 60 m_minY = minY;
61 61 m_maxY = maxY;
62 62 axisYChanged = true;
63 63 if (!m_signalsBlocked)
64 64 emit rangeVerticalChanged(m_minY, m_maxY);
65 65 }
66 66
67 67 if (axisXChanged || axisYChanged)
68 68 emit updated();
69 69 }
70 70
71 71 void LogXYPolarDomain::zoomIn(const QRectF &rect)
72 72 {
73 storeZoomReset();
73 74 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
74 75 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
75 76 qreal leftX = qPow(m_logBaseX, logLeftX);
76 77 qreal rightX = qPow(m_logBaseX, logRightX);
77 78 qreal minX = leftX < rightX ? leftX : rightX;
78 79 qreal maxX = leftX > rightX ? leftX : rightX;
79 80
80 81 qreal dy = spanY() / m_size.height();
81 82 qreal minY = m_minY;
82 83 qreal maxY = m_maxY;
83 84
84 85 minY = maxY - dy * rect.bottom();
85 86 maxY = maxY - dy * rect.top();
86 87
87 88 setRange(minX, maxX, minY, maxY);
88 89 }
89 90
90 91 void LogXYPolarDomain::zoomOut(const QRectF &rect)
91 92 {
93 storeZoomReset();
92 94 const qreal factorX = m_size.width() / rect.width();
93 95
94 96 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 - factorX);
95 97 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2.0 * (1.0 + factorX);
96 98 qreal leftX = qPow(m_logBaseX, logLeftX);
97 99 qreal rightX = qPow(m_logBaseX, logRIghtX);
98 100 qreal minX = leftX < rightX ? leftX : rightX;
99 101 qreal maxX = leftX > rightX ? leftX : rightX;
100 102
101 103 qreal dy = spanY() / rect.height();
102 104 qreal minY = m_minY;
103 105 qreal maxY = m_maxY;
104 106
105 107 maxY = minY + dy * rect.bottom();
106 108 minY = maxY - dy * m_size.height();
107 109
108 110 setRange(minX, maxX, minY, maxY);
109 111 }
110 112
111 113 void LogXYPolarDomain::move(qreal dx, qreal dy)
112 114 {
113 115 qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
114 116 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
115 117 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
116 118 qreal minX = leftX < rightX ? leftX : rightX;
117 119 qreal maxX = leftX > rightX ? leftX : rightX;
118 120
119 121 qreal y = spanY() / m_radius;
120 122 qreal minY = m_minY;
121 123 qreal maxY = m_maxY;
122 124
123 125 if (dy != 0) {
124 126 minY = minY + y * dy;
125 127 maxY = maxY + y * dy;
126 128 }
127 129 setRange(minX, maxX, minY, maxY);
128 130 }
129 131
130 132 qreal LogXYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
131 133 {
132 134 qreal retVal;
133 135 if (value <= 0) {
134 136 ok = false;
135 137 retVal = 0.0;
136 138 } else {
137 139 ok = true;
138 140 const qreal tickSpan = 360.0 / qAbs(m_logRightX - m_logLeftX);
139 141 const qreal logValue = log10(value) / log10(m_logBaseX);
140 142 const qreal valueDelta = logValue - m_logLeftX;
141 143
142 144 retVal = valueDelta * tickSpan;
143 145 }
144 146 return retVal;
145 147 }
146 148
147 149 qreal LogXYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
148 150 {
149 151 ok = true;
150 152 if (value < m_minY)
151 153 value = m_minY;
152 154
153 155 // Dont limit the max. The drawing should clip the stuff that goes out of the grid
154 156 qreal f = (value - m_minY) / (m_maxY - m_minY);
155 157
156 158 return f * m_radius;
157 159 }
158 160
159 161 QPointF LogXYPolarDomain::calculateDomainPoint(const QPointF &point) const
160 162 {
161 163 if (point == m_center)
162 164 return QPointF(0.0, m_minY);
163 165
164 166 QLineF line(m_center, point);
165 167 qreal a = 90.0 - line.angle();
166 168 if (a < 0.0)
167 169 a += 360.0;
168 170
169 171 const qreal deltaX = 360.0 / qAbs(m_logRightX - m_logLeftX);
170 172 a = qPow(m_logBaseX, m_logLeftX + (a / deltaX));
171 173
172 174 qreal r = m_minY + ((m_maxY - m_minY) * (line.length() / m_radius));
173 175
174 176 return QPointF(a, r);
175 177 }
176 178
177 179 bool LogXYPolarDomain::attachAxis(QAbstractAxis *axis)
178 180 {
179 181 AbstractDomain::attachAxis(axis);
180 182 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
181 183
182 184 if (logAxis && logAxis->orientation() == Qt::Horizontal) {
183 185 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
184 186 handleHorizontalAxisBaseChanged(logAxis->base());
185 187 }
186 188
187 189 return true;
188 190 }
189 191
190 192 bool LogXYPolarDomain::detachAxis(QAbstractAxis *axis)
191 193 {
192 194 AbstractDomain::detachAxis(axis);
193 195 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
194 196
195 197 if (logAxis && logAxis->orientation() == Qt::Horizontal)
196 198 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
197 199
198 200 return true;
199 201 }
200 202
201 203 void LogXYPolarDomain::handleHorizontalAxisBaseChanged(qreal baseX)
202 204 {
203 205 m_logBaseX = baseX;
204 206 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
205 207 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
206 208 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
207 209 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
208 210 emit updated();
209 211 }
210 212
211 213 // operators
212 214
213 215 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2)
214 216 {
215 217 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
216 218 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
217 219 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
218 220 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
219 221 }
220 222
221 223
222 224 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const LogXYPolarDomain &domain1, const LogXYPolarDomain &domain2)
223 225 {
224 226 return !(domain1 == domain2);
225 227 }
226 228
227 229
228 230 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYPolarDomain &domain)
229 231 {
230 232 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
231 233 return dbg.maybeSpace();
232 234 }
233 235
234 236 #include "moc_logxypolardomain_p.cpp"
235 237
236 238 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,234 +1,236
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "xlogydomain_p.h"
22 22 #include "qabstractaxis_p.h"
23 23 #include "qlogvalueaxis.h"
24 24 #include <qmath.h>
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 XLogYDomain::XLogYDomain(QObject *parent)
29 29 : AbstractDomain(parent),
30 30 m_logLeftY(0),
31 31 m_logRightY(1),
32 32 m_logBaseY(10)
33 33 {
34 34 }
35 35
36 36 XLogYDomain::~XLogYDomain()
37 37 {
38 38 }
39 39
40 40 void XLogYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
41 41 {
42 42 bool axisXChanged = false;
43 43 bool axisYChanged = false;
44 44
45 45 adjustLogDomainRanges(minY, maxY);
46 46
47 47 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
48 48 m_minX = minX;
49 49 m_maxX = maxX;
50 50 axisXChanged = true;
51 51 if(!m_signalsBlocked)
52 52 emit rangeHorizontalChanged(m_minX, m_maxX);
53 53 }
54 54
55 55 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
56 56 m_minY = minY;
57 57 m_maxY = maxY;
58 58 axisYChanged = true;
59 59 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
60 60 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
61 61 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
62 62 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
63 63 if (!m_signalsBlocked)
64 64 emit rangeVerticalChanged(m_minY, m_maxY);
65 65 }
66 66
67 67 if (axisXChanged || axisYChanged)
68 68 emit updated();
69 69 }
70 70
71 71 void XLogYDomain::zoomIn(const QRectF &rect)
72 72 {
73 storeZoomReset();
73 74 qreal dx = spanX() / m_size.width();
74 75 qreal maxX = m_maxX;
75 76 qreal minX = m_minX;
76 77
77 78 maxX = minX + dx * rect.right();
78 79 minX = minX + dx * rect.left();
79 80
80 81 qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
81 82 qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
82 83 qreal leftY = qPow(m_logBaseY, logLeftY);
83 84 qreal rightY = qPow(m_logBaseY, logRightY);
84 85 qreal minY = leftY < rightY ? leftY : rightY;
85 86 qreal maxY = leftY > rightY ? leftY : rightY;
86 87
87 88 setRange(minX, maxX, minY, maxY);
88 89 }
89 90
90 91 void XLogYDomain::zoomOut(const QRectF &rect)
91 92 {
93 storeZoomReset();
92 94 qreal dx = spanX() / rect.width();
93 95 qreal maxX = m_maxX;
94 96 qreal minX = m_minX;
95 97
96 98 minX = maxX - dx * rect.right();
97 99 maxX = minX + dx * m_size.width();
98 100
99 101 const qreal factorY = m_size.height() / rect.height();
100 102 qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
101 103 qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
102 104 qreal leftY = qPow(m_logBaseY, newLogMinY);
103 105 qreal rightY = qPow(m_logBaseY, newLogMaxY);
104 106 qreal minY = leftY < rightY ? leftY : rightY;
105 107 qreal maxY = leftY > rightY ? leftY : rightY;
106 108
107 109 setRange(minX, maxX, minY, maxY);
108 110 }
109 111
110 112 void XLogYDomain::move(qreal dx, qreal dy)
111 113 {
112 114 qreal x = spanX() / m_size.width();
113 115 qreal maxX = m_maxX;
114 116 qreal minX = m_minX;
115 117
116 118 if (dx != 0) {
117 119 minX = minX + x * dx;
118 120 maxX = maxX + x * dx;
119 121 }
120 122
121 123 qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
122 124 qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
123 125 qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
124 126 qreal minY = leftY < rightY ? leftY : rightY;
125 127 qreal maxY = leftY > rightY ? leftY : rightY;
126 128
127 129 setRange(minX, maxX, minY, maxY);
128 130 }
129 131
130 132 QPointF XLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
131 133 {
132 134 if (point.y() > 0) {
133 135 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
134 136 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
135 137
136 138 qreal x = (point.x() - m_minX) * deltaX;
137 139 qreal y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
138 140 ok = true;
139 141 return QPointF(x, y);
140 142 } else {
141 143 qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
142 144 ok = false;
143 145 return QPointF();
144 146 }
145 147 }
146 148
147 149 QVector<QPointF> XLogYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
148 150 {
149 151 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
150 152 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
151 153
152 154 QVector<QPointF> result;
153 155 result.resize(vector.count());
154 156
155 157 for (int i = 0; i < vector.count(); ++i) {
156 158 if (vector[i].y() > 0) {
157 159 qreal x = (vector[i].x() - m_minX) * deltaX;
158 160 qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
159 161 result[i].setX(x);
160 162 result[i].setY(y);
161 163 } else {
162 164 qWarning() << "Logarithm of negative value is undefined. Empty layout returned.";
163 165 return QVector<QPointF>();
164 166 }
165 167 }
166 168 return result;
167 169 }
168 170
169 171 QPointF XLogYDomain::calculateDomainPoint(const QPointF &point) const
170 172 {
171 173 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
172 174 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
173 175 qreal x = point.x() / deltaX + m_minX;
174 176 qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
175 177 return QPointF(x, y);
176 178 }
177 179
178 180 bool XLogYDomain::attachAxis(QAbstractAxis *axis)
179 181 {
180 182 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
181 183
182 184 if (logAxis && logAxis->orientation() == Qt::Vertical) {
183 185 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
184 186 handleVerticalAxisBaseChanged(logAxis->base());
185 187 }
186 188 return AbstractDomain::attachAxis(axis);
187 189 }
188 190
189 191 bool XLogYDomain::detachAxis(QAbstractAxis *axis)
190 192 {
191 193 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
192 194
193 195 if (logAxis && logAxis->orientation() == Qt::Vertical)
194 196 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
195 197
196 198 return AbstractDomain::detachAxis(axis);
197 199 }
198 200
199 201 void XLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
200 202 {
201 203 m_logBaseY = baseY;
202 204 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
203 205 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
204 206 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
205 207 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
206 208 emit updated();
207 209 }
208 210
209 211 // operators
210 212
211 213 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const XLogYDomain &domain1, const XLogYDomain &domain2)
212 214 {
213 215 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
214 216 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
215 217 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
216 218 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
217 219 }
218 220
219 221
220 222 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XLogYDomain &domain1, const XLogYDomain &domain2)
221 223 {
222 224 return !(domain1 == domain2);
223 225 }
224 226
225 227
226 228 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYDomain &domain)
227 229 {
228 230 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
229 231 return dbg.maybeSpace();
230 232 }
231 233
232 234 #include "moc_xlogydomain_p.cpp"
233 235
234 236 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,231 +1,233
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "xlogypolardomain_p.h"
22 22 #include "qabstractaxis_p.h"
23 23 #include "qlogvalueaxis.h"
24 24 #include <qmath.h>
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 XLogYPolarDomain::XLogYPolarDomain(QObject *parent)
29 29 : PolarDomain(parent),
30 30 m_logInnerY(0),
31 31 m_logOuterY(1),
32 32 m_logBaseY(10)
33 33 {
34 34 }
35 35
36 36 XLogYPolarDomain::~XLogYPolarDomain()
37 37 {
38 38 }
39 39
40 40 void XLogYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
41 41 {
42 42 bool axisXChanged = false;
43 43 bool axisYChanged = false;
44 44
45 45 adjustLogDomainRanges(minY, maxY);
46 46
47 47 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
48 48 m_minX = minX;
49 49 m_maxX = maxX;
50 50 axisXChanged = true;
51 51 if (!m_signalsBlocked)
52 52 emit rangeHorizontalChanged(m_minX, m_maxX);
53 53 }
54 54
55 55 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
56 56 m_minY = minY;
57 57 m_maxY = maxY;
58 58 axisYChanged = true;
59 59 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
60 60 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
61 61 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
62 62 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
63 63 if (!m_signalsBlocked)
64 64 emit rangeVerticalChanged(m_minY, m_maxY);
65 65 }
66 66
67 67 if (axisXChanged || axisYChanged)
68 68 emit updated();
69 69 }
70 70
71 71 void XLogYPolarDomain::zoomIn(const QRectF &rect)
72 72 {
73 storeZoomReset();
73 74 qreal dx = spanX() / m_size.width();
74 75 qreal maxX = m_maxX;
75 76 qreal minX = m_minX;
76 77
77 78 maxX = minX + dx * rect.right();
78 79 minX = minX + dx * rect.left();
79 80
80 81 qreal logLeftY = m_logOuterY - rect.bottom() * (m_logOuterY - m_logInnerY) / m_size.height();
81 82 qreal logRightY = m_logOuterY - rect.top() * (m_logOuterY - m_logInnerY) / m_size.height();
82 83 qreal leftY = qPow(m_logBaseY, logLeftY);
83 84 qreal rightY = qPow(m_logBaseY, logRightY);
84 85 qreal minY = leftY < rightY ? leftY : rightY;
85 86 qreal maxY = leftY > rightY ? leftY : rightY;
86 87
87 88 setRange(minX, maxX, minY, maxY);
88 89 }
89 90
90 91 void XLogYPolarDomain::zoomOut(const QRectF &rect)
91 92 {
93 storeZoomReset();
92 94 qreal dx = spanX() / rect.width();
93 95 qreal maxX = m_maxX;
94 96 qreal minX = m_minX;
95 97
96 98 minX = maxX - dx * rect.right();
97 99 maxX = minX + dx * m_size.width();
98 100
99 101 const qreal factorY = m_size.height() / rect.height();
100 102 qreal newLogMinY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 - factorY);
101 103 qreal newLogMaxY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 + factorY);
102 104 qreal leftY = qPow(m_logBaseY, newLogMinY);
103 105 qreal rightY = qPow(m_logBaseY, newLogMaxY);
104 106 qreal minY = leftY < rightY ? leftY : rightY;
105 107 qreal maxY = leftY > rightY ? leftY : rightY;
106 108
107 109 setRange(minX, maxX, minY, maxY);
108 110 }
109 111
110 112 void XLogYPolarDomain::move(qreal dx, qreal dy)
111 113 {
112 114 qreal x = spanX() / 360.0;
113 115
114 116 qreal maxX = m_maxX;
115 117 qreal minX = m_minX;
116 118
117 119 if (dx != 0) {
118 120 minX = minX + x * dx;
119 121 maxX = maxX + x * dx;
120 122 }
121 123
122 124 qreal stepY = dy * (m_logOuterY - m_logInnerY) / m_radius;
123 125 qreal leftY = qPow(m_logBaseY, m_logInnerY + stepY);
124 126 qreal rightY = qPow(m_logBaseY, m_logOuterY + stepY);
125 127 qreal minY = leftY < rightY ? leftY : rightY;
126 128 qreal maxY = leftY > rightY ? leftY : rightY;
127 129
128 130 setRange(minX, maxX, minY, maxY);
129 131 }
130 132
131 133 qreal XLogYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
132 134 {
133 135 ok = true;
134 136 qreal f = (value - m_minX) / (m_maxX - m_minX);
135 137 return f * 360.0;
136 138 }
137 139
138 140 qreal XLogYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
139 141 {
140 142 qreal retVal;
141 143 if (value <= 0) {
142 144 ok = false;
143 145 retVal = 0.0;
144 146 } else {
145 147 ok = true;
146 148 const qreal tickSpan = m_radius / qAbs(m_logOuterY - m_logInnerY);
147 149 const qreal logValue = log10(value) / log10(m_logBaseY);
148 150 const qreal valueDelta = logValue - m_logInnerY;
149 151
150 152 retVal = valueDelta * tickSpan;
151 153
152 154 if (retVal < 0.0)
153 155 retVal = 0.0;
154 156 }
155 157 return retVal;
156 158 }
157 159
158 160 QPointF XLogYPolarDomain::calculateDomainPoint(const QPointF &point) const
159 161 {
160 162 if (point == m_center)
161 163 return QPointF(0.0, m_minY);
162 164
163 165 QLineF line(m_center, point);
164 166 qreal a = 90.0 - line.angle();
165 167 if (a < 0.0)
166 168 a += 360.0;
167 169 a = ((a / 360.0) * (m_maxX - m_minX)) + m_minX;
168 170
169 171 const qreal deltaY = m_radius / qAbs(m_logOuterY - m_logInnerY);
170 172 qreal r = qPow(m_logBaseY, m_logInnerY + (line.length() / deltaY));
171 173
172 174 return QPointF(a, r);
173 175 }
174 176
175 177 bool XLogYPolarDomain::attachAxis(QAbstractAxis *axis)
176 178 {
177 179 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
178 180
179 181 if (logAxis && logAxis->orientation() == Qt::Vertical) {
180 182 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
181 183 handleVerticalAxisBaseChanged(logAxis->base());
182 184 }
183 185 return AbstractDomain::attachAxis(axis);
184 186 }
185 187
186 188 bool XLogYPolarDomain::detachAxis(QAbstractAxis *axis)
187 189 {
188 190 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
189 191
190 192 if (logAxis && logAxis->orientation() == Qt::Vertical)
191 193 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
192 194
193 195 return AbstractDomain::detachAxis(axis);
194 196 }
195 197
196 198 void XLogYPolarDomain::handleVerticalAxisBaseChanged(qreal baseY)
197 199 {
198 200 m_logBaseY = baseY;
199 201 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
200 202 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
201 203 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
202 204 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
203 205 emit updated();
204 206 }
205 207
206 208 // operators
207 209
208 210 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
209 211 {
210 212 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX)
211 213 && qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY)
212 214 && qFuzzyIsNull(domain1.m_minX - domain2.m_minX)
213 215 && qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
214 216 }
215 217
216 218
217 219 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
218 220 {
219 221 return !(domain1 == domain2);
220 222 }
221 223
222 224
223 225 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYPolarDomain &domain)
224 226 {
225 227 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
226 228 return dbg.maybeSpace();
227 229 }
228 230
229 231 #include "moc_xlogypolardomain_p.cpp"
230 232
231 233 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,180 +1,182
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "xydomain_p.h"
22 22 #include "qabstractaxis_p.h"
23 23 #include <qmath.h>
24 24
25 25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 26
27 27 XYDomain::XYDomain(QObject *parent)
28 28 : AbstractDomain(parent)
29 29 {
30 30 }
31 31
32 32 XYDomain::~XYDomain()
33 33 {
34 34 }
35 35
36 36 void XYDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
37 37 {
38 38 bool axisXChanged = false;
39 39 bool axisYChanged = false;
40 40
41 41 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
42 42 m_minX = minX;
43 43 m_maxX = maxX;
44 44 axisXChanged = true;
45 45 if(!m_signalsBlocked)
46 46 emit rangeHorizontalChanged(m_minX, m_maxX);
47 47 }
48 48
49 49 if (!qFuzzyCompare(m_minY, minY) || !qFuzzyCompare(m_maxY, maxY)) {
50 50 m_minY = minY;
51 51 m_maxY = maxY;
52 52 axisYChanged = true;
53 53 if(!m_signalsBlocked)
54 54 emit rangeVerticalChanged(m_minY, m_maxY);
55 55 }
56 56
57 57 if (axisXChanged || axisYChanged)
58 58 emit updated();
59 59 }
60 60
61 61
62 62 void XYDomain::zoomIn(const QRectF &rect)
63 63 {
64 storeZoomReset();
64 65 qreal dx = spanX() / m_size.width();
65 66 qreal dy = spanY() / m_size.height();
66 67
67 68 qreal maxX = m_maxX;
68 69 qreal minX = m_minX;
69 70 qreal minY = m_minY;
70 71 qreal maxY = m_maxY;
71 72
72 73 maxX = minX + dx * rect.right();
73 74 minX = minX + dx * rect.left();
74 75 minY = maxY - dy * rect.bottom();
75 76 maxY = maxY - dy * rect.top();
76 77
77 78 setRange(minX, maxX, minY, maxY);
78 79 }
79 80
80 81 void XYDomain::zoomOut(const QRectF &rect)
81 82 {
83 storeZoomReset();
82 84 qreal dx = spanX() / rect.width();
83 85 qreal dy = spanY() / rect.height();
84 86
85 87 qreal maxX = m_maxX;
86 88 qreal minX = m_minX;
87 89 qreal minY = m_minY;
88 90 qreal maxY = m_maxY;
89 91
90 92 minX = maxX - dx * rect.right();
91 93 maxX = minX + dx * m_size.width();
92 94 maxY = minY + dy * rect.bottom();
93 95 minY = maxY - dy * m_size.height();
94 96
95 97 setRange(minX, maxX, minY, maxY);
96 98 }
97 99
98 100 void XYDomain::move(qreal dx, qreal dy)
99 101 {
100 102 qreal x = spanX() / m_size.width();
101 103 qreal y = spanY() / m_size.height();
102 104
103 105 qreal maxX = m_maxX;
104 106 qreal minX = m_minX;
105 107 qreal minY = m_minY;
106 108 qreal maxY = m_maxY;
107 109
108 110 if (dx != 0) {
109 111 minX = minX + x * dx;
110 112 maxX = maxX + x * dx;
111 113 }
112 114 if (dy != 0) {
113 115 minY = minY + y * dy;
114 116 maxY = maxY + y * dy;
115 117 }
116 118 setRange(minX, maxX, minY, maxY);
117 119 }
118 120
119 121 QPointF XYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
120 122 {
121 123 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
122 124 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
123 125 qreal x = (point.x() - m_minX) * deltaX;
124 126 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
125 127 ok = true;
126 128 return QPointF(x, y);
127 129 }
128 130
129 131 QVector<QPointF> XYDomain::calculateGeometryPoints(const QList<QPointF> &vector) const
130 132 {
131 133 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
132 134 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
133 135
134 136 QVector<QPointF> result;
135 137 result.resize(vector.count());
136 138
137 139 for (int i = 0; i < vector.count(); ++i) {
138 140 qreal x = (vector[i].x() - m_minX) * deltaX;
139 141 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
140 142 result[i].setX(x);
141 143 result[i].setY(y);
142 144 }
143 145 return result;
144 146 }
145 147
146 148 QPointF XYDomain::calculateDomainPoint(const QPointF &point) const
147 149 {
148 150 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
149 151 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
150 152 qreal x = point.x() / deltaX + m_minX;
151 153 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
152 154 return QPointF(x, y);
153 155 }
154 156
155 157 // operators
156 158
157 159 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const XYDomain &domain1, const XYDomain &domain2)
158 160 {
159 161 return (qFuzzyCompare(domain1.m_maxX, domain2.m_maxX)
160 162 && qFuzzyCompare(domain1.m_maxY, domain2.m_maxY)
161 163 && qFuzzyCompare(domain1.m_minX, domain2.m_minX)
162 164 && qFuzzyCompare(domain1.m_minY, domain2.m_minY));
163 165 }
164 166
165 167
166 168 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XYDomain &domain1, const XYDomain &domain2)
167 169 {
168 170 return !(domain1 == domain2);
169 171 }
170 172
171 173
172 174 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYDomain &domain)
173 175 {
174 176 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
175 177 return dbg.maybeSpace();
176 178 }
177 179
178 180 #include "moc_xydomain_p.cpp"
179 181
180 182 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,178 +1,180
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "xypolardomain_p.h"
22 22 #include "qabstractaxis_p.h"
23 23 #include <qmath.h>
24 24
25 25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 26
27 27 XYPolarDomain::XYPolarDomain(QObject *parent)
28 28 : PolarDomain(parent)
29 29 {
30 30 }
31 31
32 32 XYPolarDomain::~XYPolarDomain()
33 33 {
34 34 }
35 35
36 36 void XYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
37 37 {
38 38 bool axisXChanged = false;
39 39 bool axisYChanged = false;
40 40
41 41 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
42 42 m_minX = minX;
43 43 m_maxX = maxX;
44 44 axisXChanged = true;
45 45 if (!m_signalsBlocked)
46 46 emit rangeHorizontalChanged(m_minX, m_maxX);
47 47 }
48 48
49 49 if (!qFuzzyCompare(m_minY, minY) || !qFuzzyCompare(m_maxY, maxY)) {
50 50 m_minY = minY;
51 51 m_maxY = maxY;
52 52 axisYChanged = true;
53 53 if (!m_signalsBlocked)
54 54 emit rangeVerticalChanged(m_minY, m_maxY);
55 55 }
56 56
57 57 if (axisXChanged || axisYChanged)
58 58 emit updated();
59 59 }
60 60
61 61
62 62 void XYPolarDomain::zoomIn(const QRectF &rect)
63 63 {
64 storeZoomReset();
64 65 qreal dx = spanX() / m_size.width();
65 66 qreal dy = spanY() / m_size.height();
66 67
67 68 qreal maxX = m_maxX;
68 69 qreal minX = m_minX;
69 70 qreal minY = m_minY;
70 71 qreal maxY = m_maxY;
71 72
72 73 maxX = minX + dx * rect.right();
73 74 minX = minX + dx * rect.left();
74 75 minY = maxY - dy * rect.bottom();
75 76 maxY = maxY - dy * rect.top();
76 77
77 78 setRange(minX, maxX, minY, maxY);
78 79 }
79 80
80 81 void XYPolarDomain::zoomOut(const QRectF &rect)
81 82 {
83 storeZoomReset();
82 84 qreal dx = spanX() / rect.width();
83 85 qreal dy = spanY() / rect.height();
84 86
85 87 qreal maxX = m_maxX;
86 88 qreal minX = m_minX;
87 89 qreal minY = m_minY;
88 90 qreal maxY = m_maxY;
89 91
90 92 minX = maxX - dx * rect.right();
91 93 maxX = minX + dx * m_size.width();
92 94 maxY = minY + dy * rect.bottom();
93 95 minY = maxY - dy * m_size.height();
94 96
95 97 setRange(minX, maxX, minY, maxY);
96 98 }
97 99
98 100 void XYPolarDomain::move(qreal dx, qreal dy)
99 101 {
100 102 // One unit scrolls one degree angular and one pixel radial
101 103 qreal x = spanX() / 360.0;
102 104 qreal y = spanY() / m_radius;
103 105
104 106 qreal maxX = m_maxX;
105 107 qreal minX = m_minX;
106 108 qreal minY = m_minY;
107 109 qreal maxY = m_maxY;
108 110
109 111 if (dx != 0) {
110 112 minX = minX + x * dx;
111 113 maxX = maxX + x * dx;
112 114 }
113 115 if (dy != 0) {
114 116 minY = minY + y * dy;
115 117 maxY = maxY + y * dy;
116 118 }
117 119 setRange(minX, maxX, minY, maxY);
118 120 }
119 121
120 122 QPointF XYPolarDomain::calculateDomainPoint(const QPointF &point) const
121 123 {
122 124 if (point == m_center)
123 125 return QPointF(0.0, m_minX);
124 126
125 127 QLineF line(m_center, point);
126 128 qreal a = 90.0 - line.angle();
127 129 if (a < 0.0)
128 130 a += 360.0;
129 131 a = ((a / 360.0) * (m_maxX - m_minX)) + m_minX;
130 132 qreal r = m_minY + ((m_maxY - m_minY) * (line.length() / m_radius));
131 133 return QPointF(a, r);
132 134 }
133 135
134 136 qreal XYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
135 137 {
136 138 ok = true;
137 139 qreal f = (value - m_minX) / (m_maxX - m_minX);
138 140 return f * 360.0;
139 141 }
140 142
141 143 qreal XYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
142 144 {
143 145 ok = true;
144 146 if (value < m_minY)
145 147 value = m_minY;
146 148
147 149 // Dont limit the max. The drawing should clip the stuff that goes out of the grid
148 150 qreal f = (value - m_minY) / (m_maxY - m_minY);
149 151
150 152 return f * m_radius;
151 153 }
152 154
153 155 // operators
154 156
155 157 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const XYPolarDomain &domain1, const XYPolarDomain &domain2)
156 158 {
157 159 return (qFuzzyCompare(domain1.m_maxX, domain2.m_maxX)
158 160 && qFuzzyCompare(domain1.m_maxY, domain2.m_maxY)
159 161 && qFuzzyCompare(domain1.m_minX, domain2.m_minX)
160 162 && qFuzzyCompare(domain1.m_minY, domain2.m_minY));
161 163 }
162 164
163 165
164 166 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XYPolarDomain &domain1, const XYPolarDomain &domain2)
165 167 {
166 168 return !(domain1 == domain2);
167 169 }
168 170
169 171
170 172 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYPolarDomain &domain)
171 173 {
172 174 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
173 175 return dbg.maybeSpace();
174 176 }
175 177
176 178 #include "moc_xypolardomain_p.cpp"
177 179
178 180 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,781 +1,811
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qchart.h"
22 22 #include "qchart_p.h"
23 23 #include "legendscroller_p.h"
24 24 #include "qlegend_p.h"
25 25 #include "chartbackground_p.h"
26 26 #include "qabstractaxis.h"
27 27 #include "abstractchartlayout_p.h"
28 28 #include "charttheme_p.h"
29 29 #include "chartpresenter_p.h"
30 30 #include "chartdataset_p.h"
31 31 #include <QGraphicsScene>
32 32 #include <QGraphicsSceneResizeEvent>
33 33
34 34 QTCOMMERCIALCHART_BEGIN_NAMESPACE
35 35
36 36 /*!
37 37 \enum QChart::ChartTheme
38 38
39 39 This enum describes the theme used by the chart.
40 40
41 41 \value ChartThemeLight The default theme
42 42 \value ChartThemeBlueCerulean
43 43 \value ChartThemeDark
44 44 \value ChartThemeBrownSand
45 45 \value ChartThemeBlueNcs
46 46 \value ChartThemeHighContrast
47 47 \value ChartThemeBlueIcy
48 48 */
49 49
50 50 /*!
51 51 \enum QChart::AnimationOption
52 52
53 53 For enabling/disabling animations. Defaults to NoAnimation.
54 54
55 55 \value NoAnimation
56 56 \value GridAxisAnimations
57 57 \value SeriesAnimations
58 58 \value AllAnimations
59 59 */
60 60
61 61 /*!
62 62 \enum QChart::ChartType
63 63
64 64 This enum describes the chart type.
65 65
66 66 \value ChartTypeUndefined
67 67 \value ChartTypeCartesian
68 68 \value ChartTypePolar
69 69 */
70 70
71 71 /*!
72 72 \class QChart
73 73 \brief QtCommercial chart API.
74 74
75 75 QChart is a QGraphicsWidget that you can show in a QGraphicsScene. It manages the graphical
76 76 representation of different types of series and other chart related objects like legend and
77 77 axes. If you simply want to show a chart in a layout, you can use the
78 78 convenience class QChartView instead of QChart.
79 79 \sa QChartView, QPolarChart
80 80 */
81 81
82 82 /*!
83 83 \property QChart::animationOptions
84 84 The animation \a options for the chart. Animations are enabled/disabled based on this setting.
85 85 */
86 86
87 87 /*!
88 88 \property QChart::backgroundVisible
89 89 Specifies whether the chart background is visible or not.
90 90 \sa setBackgroundBrush(), setBackgroundPen(), plotAreaBackgroundVisible
91 91 */
92 92
93 93 /*!
94 94 \property QChart::dropShadowEnabled
95 95 If set to true, the background drop shadow effect is enabled. If set to false, it is disabled. Note that the drop
96 96 shadow effect depends on theme, which means the setting may be changed if you switch to another theme.
97 97 */
98 98
99 99 /*!
100 100 \property QChart::minimumMargins
101 101 Minimum margins between the plot area (axes) and the edge of the chart widget.
102 102 This property is deprecated; use margins property instead.
103 103
104 104 \sa margins
105 105 */
106 106
107 107 /*!
108 108 \property QChart::margins
109 109 Margins between the plot area (axes) and the edge of the chart widget.
110 110 */
111 111
112 112 /*!
113 113 \property QChart::theme
114 114 Theme is a built-in collection of UI style related settings applied for all visual elements of a chart, like colors,
115 115 pens, brushes, and fonts of series, axes, title, and legend. \l {Chart themes demo} shows an example with a few
116 116 different themes.
117 117 \note Changing the theme will overwrite all customizations previously applied to the series.
118 118 */
119 119
120 120 /*!
121 121 \property QChart::title
122 122 Title is the name (label) of a chart. It is shown as a headline on top of the chart. Chart title supports html formatting.
123 123 */
124 124
125 125 /*!
126 126 \property QChart::chartType
127 127 Chart type indicates if the chart is a cartesian chart or a polar chart.
128 128 This property is set internally and it is read only.
129 129 \sa QPolarChart
130 130 */
131 131
132 132 /*!
133 133 \property QChart::plotAreaBackgroundVisible
134 134 Specifies whether the chart plot area background is visible or not.
135 135 \note By default the plot area background is not visible and the plot area uses
136 136 the general chart background.
137 137 \sa setPlotAreaBackgroundBrush(), setPlotAreaBackgroundPen(), backgroundVisible
138 138 */
139 139
140 140 /*!
141 141 \internal
142 142 Constructs a chart object of \a type which is a child of a \a parent.
143 143 Parameter \a wFlags is passed to the QGraphicsWidget constructor.
144 144 This constructor is called only by subclasses.
145 145 */
146 146 QChart::QChart(QChart::ChartType type, QGraphicsItem *parent, Qt::WindowFlags wFlags)
147 147 : QGraphicsWidget(parent, wFlags),
148 148 d_ptr(new QChartPrivate(this, type))
149 149 {
150 150 d_ptr->init();
151 151 }
152 152
153 153 /*!
154 154 Constructs a chart object which is a child of a \a parent.
155 155 Parameter \a wFlags is passed to the QGraphicsWidget constructor.
156 156 */
157 157 QChart::QChart(QGraphicsItem *parent, Qt::WindowFlags wFlags)
158 158 : QGraphicsWidget(parent, wFlags),
159 159 d_ptr(new QChartPrivate(this, ChartTypeCartesian))
160 160 {
161 161 d_ptr->init();
162 162 }
163 163
164 164 /*!
165 165 Destroys the chart object and its children, like series and axis objects added to it.
166 166 */
167 167 QChart::~QChart()
168 168 {
169 169 //start by deleting dataset, it will remove all series and axes
170 170 delete d_ptr->m_dataset;
171 171 d_ptr->m_dataset = 0;
172 172 }
173 173
174 174 /*!
175 175 Adds the \a series onto the chart and takes the ownership of it.
176 176
177 177 \note A newly added series is attached to no axes by default, including any axes that were created for the chart
178 178 using createDefaultAxes() before the series was added to the chart. If no axes are attached to
179 179 the newly added series before the chart is shown, the series will get drawn as if it had axes with ranges
180 180 that exactly fit the series to the plot area of the chart. This can be confusing if the same chart also displays other
181 181 series that have properly attached axes, so always make sure you either call createDefaultAxes() after
182 182 a series has been added or explicitly attach axes for the series.
183 183
184 184 \sa removeSeries(), removeAllSeries(), createDefaultAxes(), QAbstractSeries::attachAxis()
185 185 */
186 186 void QChart::addSeries(QAbstractSeries *series)
187 187 {
188 188 Q_ASSERT(series);
189 189 d_ptr->m_dataset->addSeries(series);
190 190 }
191 191
192 192 /*!
193 193 Removes the \a series from the chart.
194 194 The chart releases its ownership of the specified \a series object.
195 195
196 196 \sa addSeries(), removeAllSeries()
197 197 */
198 198 void QChart::removeSeries(QAbstractSeries *series)
199 199 {
200 200 Q_ASSERT(series);
201 201 d_ptr->m_dataset->removeSeries(series);
202 202 }
203 203
204 204 /*!
205 205 Removes and deletes all series objects that have been added to the chart.
206 206
207 207 \sa addSeries(), removeSeries()
208 208 */
209 209 void QChart::removeAllSeries()
210 210 {
211 211 foreach (QAbstractSeries *s , d_ptr->m_dataset->series()){
212 212 removeSeries(s);
213 213 delete s;
214 214 }
215 215 }
216 216
217 217 /*!
218 218 Sets the \a brush that is used for painting the background of the chart area.
219 219 */
220 220 void QChart::setBackgroundBrush(const QBrush &brush)
221 221 {
222 222 d_ptr->m_presenter->setBackgroundBrush(brush);
223 223 }
224 224
225 225 /*!
226 226 Gets the brush that is used for painting the background of the chart area.
227 227 */
228 228 QBrush QChart::backgroundBrush() const
229 229 {
230 230 return d_ptr->m_presenter->backgroundBrush();
231 231 }
232 232
233 233 /*!
234 234 Sets the \a pen that is used for painting the background of the chart area.
235 235 */
236 236 void QChart::setBackgroundPen(const QPen &pen)
237 237 {
238 238 d_ptr->m_presenter->setBackgroundPen(pen);
239 239 }
240 240
241 241 /*!
242 242 Gets the pen that is used for painting the background of the chart area.
243 243 */
244 244 QPen QChart::backgroundPen() const
245 245 {
246 246 return d_ptr->m_presenter->backgroundPen();
247 247 }
248 248
249 249 void QChart::setTitle(const QString &title)
250 250 {
251 251 d_ptr->m_presenter->setTitle(title);
252 252 }
253 253
254 254 QString QChart::title() const
255 255 {
256 256 return d_ptr->m_presenter->title();
257 257 }
258 258
259 259 /*!
260 260 Sets the \a font that is used for drawing the chart title.
261 261 */
262 262 void QChart::setTitleFont(const QFont &font)
263 263 {
264 264 d_ptr->m_presenter->setTitleFont(font);
265 265 }
266 266
267 267 /*!
268 268 Gets the font that is used for drawing the chart title.
269 269 */
270 270 QFont QChart::titleFont() const
271 271 {
272 272 return d_ptr->m_presenter->titleFont();
273 273 }
274 274
275 275 /*!
276 276 Sets the \a brush used for drawing the title text.
277 277 */
278 278 void QChart::setTitleBrush(const QBrush &brush)
279 279 {
280 280 d_ptr->m_presenter->setTitleBrush(brush);
281 281 }
282 282
283 283 /*!
284 284 Returns the brush used for drawing the title text.
285 285 */
286 286 QBrush QChart::titleBrush() const
287 287 {
288 288 return d_ptr->m_presenter->titleBrush();
289 289 }
290 290
291 291 void QChart::setTheme(QChart::ChartTheme theme)
292 292 {
293 293 d_ptr->m_themeManager->setTheme(theme);
294 294 }
295 295
296 296 QChart::ChartTheme QChart::theme() const
297 297 {
298 298 return d_ptr->m_themeManager->theme()->id();
299 299 }
300 300
301 301 /*!
302 302 Zooms in the view by a factor of two.
303 303 */
304 304 void QChart::zoomIn()
305 305 {
306 306 d_ptr->zoomIn(2.0);
307 307 }
308 308
309 309 /*!
310 310 Zooms in the view to a maximum level at which \a rect is still fully visible.
311 311 \note This is not supported for polar charts.
312 312 */
313 313 void QChart::zoomIn(const QRectF &rect)
314 314 {
315 315 if (d_ptr->m_type == QChart::ChartTypePolar)
316 316 return;
317 317 d_ptr->zoomIn(rect);
318 318 }
319 319
320 320 /*!
321 321 Zooms out the view by a factor of two.
322 322 */
323 323 void QChart::zoomOut()
324 324 {
325 325 d_ptr->zoomOut(2.0);
326 326 }
327 327
328 328 /*!
329 329 Zooms in the view by a custom \a factor.
330 330
331 331 A factor over 1.0 zooms the view in and factor between 0.0 and 1.0 zooms out.
332 332 */
333 333 void QChart::zoom(qreal factor)
334 334 {
335 335 if (qFuzzyCompare(factor, 0))
336 336 return;
337 337
338 338 if (qFuzzyCompare(factor, (qreal)1.0))
339 339 return;
340 340
341 341 if (factor < 0)
342 342 return;
343 343
344 344 if (factor > 1.0)
345 345 d_ptr->zoomIn(factor);
346 346 else
347 347 d_ptr->zoomOut(1.0 / factor);
348 348 }
349 349
350
351 /*!
352 Resets the series domains to what they were before any zoom method was called.
353 Note that this will also reset any scrolls and explicit axis range settings done between
354 the first zoom operation and calling this method. If no zoom operation has been
355 done, this method does nothing.
356 */
357 void QChart::zoomReset()
358 {
359 d_ptr->zoomReset();
360 }
361
362 /*!
363 Returns true if any series has a zoomed domain.
364 */
365 bool QChart::isZoomed()
366 {
367 return d_ptr->isZoomed();
368 }
369
350 370 /*!
351 371 Returns a pointer to the horizontal axis attached to the specified \a series.
352 372 If no \a series is specified, the first horizontal axis added to the chart is returned.
353 373
354 374 \sa addAxis(), QAbstractSeries::attachAxis()
355 375 */
356 376 QAbstractAxis *QChart::axisX(QAbstractSeries *series) const
357 377 {
358 378 QList<QAbstractAxis *> axisList = axes(Qt::Horizontal, series);
359 379 if (axisList.count())
360 380 return axisList[0];
361 381 return 0;
362 382 }
363 383
364 384 /*!
365 385 Returns a pointer to the vertical axis attached to the specified \a series.
366 386 If no \a series is specified, the first vertical axis added to the chart is returned.
367 387
368 388 \sa addAxis(), QAbstractSeries::attachAxis()
369 389 */
370 390 QAbstractAxis *QChart::axisY(QAbstractSeries *series) const
371 391 {
372 392 QList<QAbstractAxis *> axisList = axes(Qt::Vertical, series);
373 393 if (axisList.count())
374 394 return axisList[0];
375 395 return 0;
376 396 }
377 397
378 398 /*!
379 399 Returns the axes attached to the \a series with \a orientation. If no \a series is provided,
380 400 then all axes added to the chart with the specified orientation are returned.
381 401 \sa addAxis(), createDefaultAxes()
382 402 */
383 403 QList<QAbstractAxis *> QChart::axes(Qt::Orientations orientation, QAbstractSeries *series) const
384 404 {
385 405 QList<QAbstractAxis *> result ;
386 406
387 407 if (series) {
388 408 foreach (QAbstractAxis *axis, series->attachedAxes()){
389 409 if (orientation.testFlag(axis->orientation()))
390 410 result << axis;
391 411 }
392 412 } else {
393 413 foreach (QAbstractAxis *axis, d_ptr->m_dataset->axes()){
394 414 if (orientation.testFlag(axis->orientation()) && !result.contains(axis))
395 415 result << axis;
396 416 }
397 417 }
398 418
399 419 return result;
400 420 }
401 421
402 422 /*!
403 423 Creates axes for the chart based on the series that have already been added to the chart. Any axes previously added to
404 424 the chart will be deleted.
405 425
406 426 \note This function has to be called after all series have been added to the chart. The axes created by this function
407 427 will NOT get automatically attached to any series added to the chart after this function has been called.
408 428 A series with no axes attached will by default scale to utilize the entire plot area of the chart, which can be confusing
409 429 if there are other series with properly attached axes also present.
410 430
411 431 \table
412 432 \header
413 433 \o Series type
414 434 \o X-axis
415 435 \o Y-axis
416 436 \row
417 437 \o QXYSeries
418 438 \o QValueAxis
419 439 \o QValueAxis
420 440 \row
421 441 \o QBarSeries
422 442 \o QBarCategoryAxis
423 443 \o QValueAxis
424 444 \row
425 445 \o QPieSeries
426 446 \o None
427 447 \o None
428 448 \endtable
429 449
430 450 If there are several QXYSeries derived series added to the chart and no series of other types have been added, then only one pair of axes is created.
431 451 If there are several series of different types added to the chart, then each series gets its own axes pair.
432 452
433 453 The axes specific to the series can be later obtained from the chart by providing the series as the parameter for axes() function call.
434 454 QPieSeries does not create any axes.
435 455
436 456 \sa axisX(), axisY(), axes(), setAxisX(), setAxisY(), QAbstractSeries::attachAxis()
437 457 */
438 458 void QChart::createDefaultAxes()
439 459 {
440 460 d_ptr->m_dataset->createDefaultAxes();
441 461 }
442 462
443 463 /*!
444 464 Returns the legend object of the chart. Ownership stays with the chart.
445 465 */
446 466 QLegend *QChart::legend() const
447 467 {
448 468 return d_ptr->m_legend;
449 469 }
450 470
451 471 void QChart::setMinimumMargins(const QMargins &margins)
452 472 {
453 473 qWarning() << "QChart::setMinimumMargins is deprecated. Use QChart::setMargins instead.";
454 474 d_ptr->m_presenter->layout()->setMargins(margins);
455 475 }
456 476
457 477 QMargins QChart::minimumMargins() const
458 478 {
459 479 qWarning() << "QChart::minimumMargins is deprecated. Use QChart::margins instead.";
460 480 return d_ptr->m_presenter->layout()->margins();
461 481 }
462 482
463 483 void QChart::setMargins(const QMargins &margins)
464 484 {
465 485 d_ptr->m_presenter->layout()->setMargins(margins);
466 486 }
467 487
468 488 QMargins QChart::margins() const
469 489 {
470 490 return d_ptr->m_presenter->layout()->margins();
471 491 }
472 492
473 493 QChart::ChartType QChart::chartType() const
474 494 {
475 495 return d_ptr->m_type;
476 496 }
477 497
478 498 /*!
479 499 Returns the the rectangle within which the drawing of the chart is done.
480 500 It does not include the area defined by margins.
481 501 */
482 502 QRectF QChart::plotArea() const
483 503 {
484 504 return d_ptr->m_presenter->geometry();
485 505 }
486 506
487 507 /*!
488 508 Sets the \a brush for the background of the plot area of the chart.
489 509
490 510 \sa plotArea(), plotAreaBackgroundVisible, setPlotAreaBackgroundPen(), plotAreaBackgroundBrush()
491 511 */
492 512 void QChart::setPlotAreaBackgroundBrush(const QBrush &brush)
493 513 {
494 514 d_ptr->m_presenter->setPlotAreaBackgroundBrush(brush);
495 515 }
496 516
497 517 /*!
498 518 Returns the brush for the background of the plot area of the chart.
499 519
500 520 \sa plotArea(), plotAreaBackgroundVisible, plotAreaBackgroundPen(), setPlotAreaBackgroundBrush()
501 521 */
502 522 QBrush QChart::plotAreaBackgroundBrush() const
503 523 {
504 524 return d_ptr->m_presenter->plotAreaBackgroundBrush();
505 525 }
506 526
507 527 /*!
508 528 Sets the \a pen for the background of the plot area of the chart.
509 529
510 530 \sa plotArea(), plotAreaBackgroundVisible, setPlotAreaBackgroundBrush(), plotAreaBackgroundPen()
511 531 */
512 532 void QChart::setPlotAreaBackgroundPen(const QPen &pen)
513 533 {
514 534 d_ptr->m_presenter->setPlotAreaBackgroundPen(pen);
515 535 }
516 536
517 537 /*!
518 538 Returns the pen for the background of the plot area of the chart.
519 539
520 540 \sa plotArea(), plotAreaBackgroundVisible, plotAreaBackgroundBrush(), setPlotAreaBackgroundPen()
521 541 */
522 542 QPen QChart::plotAreaBackgroundPen() const
523 543 {
524 544 return d_ptr->m_presenter->plotAreaBackgroundPen();
525 545 }
526 546
527 547 void QChart::setPlotAreaBackgroundVisible(bool visible)
528 548 {
529 549 d_ptr->m_presenter->setPlotAreaBackgroundVisible(visible);
530 550 }
531 551
532 552 bool QChart::isPlotAreaBackgroundVisible() const
533 553 {
534 554 return d_ptr->m_presenter->isPlotAreaBackgroundVisible();
535 555 }
536 556
537 557 void QChart::setAnimationOptions(AnimationOptions options)
538 558 {
539 559 d_ptr->m_presenter->setAnimationOptions(options);
540 560 }
541 561
542 562 QChart::AnimationOptions QChart::animationOptions() const
543 563 {
544 564 return d_ptr->m_presenter->animationOptions();
545 565 }
546 566
547 567 /*!
548 568 Scrolls the visible area of the chart by the distance defined in the \a dx and \a dy.
549 569
550 570 For polar charts, \a dx indicates the angle along angular axis instead of distance.
551 571 */
552 572 void QChart::scroll(qreal dx, qreal dy)
553 573 {
554 574 d_ptr->scroll(dx,dy);
555 575 }
556 576
557 577 void QChart::setBackgroundVisible(bool visible)
558 578 {
559 579 d_ptr->m_presenter->setBackgroundVisible(visible);
560 580 }
561 581
562 582 bool QChart::isBackgroundVisible() const
563 583 {
564 584 return d_ptr->m_presenter->isBackgroundVisible();
565 585 }
566 586
567 587 void QChart::setDropShadowEnabled(bool enabled)
568 588 {
569 589 d_ptr->m_presenter->setBackgroundDropShadowEnabled(enabled);
570 590 }
571 591
572 592 bool QChart::isDropShadowEnabled() const
573 593 {
574 594 return d_ptr->m_presenter->isBackgroundDropShadowEnabled();
575 595 }
576 596
577 597 /*!
578 598 Returns all series that are added to the chart.
579 599
580 600 \sa addSeries(), removeSeries(), removeAllSeries()
581 601 */
582 602 QList<QAbstractSeries *> QChart::series() const
583 603 {
584 604 return d_ptr->m_dataset->series();
585 605 }
586 606
587 607 /*!
588 608 Adds the \a axis to the chart and attaches it to the \a series as a bottom-aligned horizontal axis.
589 609 The chart takes ownership of both the \a axis and the \a series.
590 610 Any horizontal axes previously attached to the \a series are deleted.
591 611
592 612 \sa axisX(), axisY(), setAxisY(), createDefaultAxes(), QAbstractSeries::attachAxis()
593 613 */
594 614 void QChart::setAxisX(QAbstractAxis *axis ,QAbstractSeries *series)
595 615 {
596 616 QList<QAbstractAxis*> list = axes(Qt::Horizontal, series);
597 617
598 618 foreach (QAbstractAxis* a, list) {
599 619 d_ptr->m_dataset->removeAxis(a);
600 620 delete a;
601 621 }
602 622
603 623 if (!d_ptr->m_dataset->axes().contains(axis))
604 624 d_ptr->m_dataset->addAxis(axis, Qt::AlignBottom);
605 625 d_ptr->m_dataset->attachAxis(series, axis);
606 626 }
607 627
608 628 /*!
609 629 Adds the \a axis to the chart and attaches it to the \a series as a left-aligned vertical axis.
610 630 The chart takes ownership of both the \a axis and the \a series.
611 631 Any vertical axes previously attached to the \a series are deleted.
612 632
613 633 \sa axisX(), axisY(), setAxisX(), createDefaultAxes(), QAbstractSeries::attachAxis()
614 634 */
615 635 void QChart::setAxisY(QAbstractAxis *axis ,QAbstractSeries *series)
616 636 {
617 637 QList<QAbstractAxis*> list = axes(Qt::Vertical, series);
618 638
619 639 foreach (QAbstractAxis* a, list) {
620 640 d_ptr->m_dataset->removeAxis(a);
621 641 delete a;
622 642 }
623 643
624 644 if (!d_ptr->m_dataset->axes().contains(axis))
625 645 d_ptr->m_dataset->addAxis(axis, Qt::AlignLeft);
626 646 d_ptr->m_dataset->attachAxis(series, axis);
627 647 }
628 648
629 649 /*!
630 650 Adds the \a axis to the chart with \a alignment. The chart takes the ownership of the axis.
631 651
632 652 \sa removeAxis(), createDefaultAxes(), QAbstractSeries::attachAxis()
633 653 */
634 654 void QChart::addAxis(QAbstractAxis *axis, Qt::Alignment alignment)
635 655 {
636 656 d_ptr->m_dataset->addAxis(axis, alignment);
637 657 }
638 658
639 659 /*!
640 660 Removes the \a axis from the chart.
641 661 The chart releases its ownership of the specified \a axis object.
642 662
643 663 \sa addAxis(), createDefaultAxes(), QAbstractSeries::detachAxis()
644 664 */
645 665 void QChart::removeAxis(QAbstractAxis *axis)
646 666 {
647 667 d_ptr->m_dataset->removeAxis(axis);
648 668 }
649 669
650 670 /*!
651 671 Returns the value in the \a series domain that corresponds to the \a position relative to chart widget.
652 672 */
653 673 QPointF QChart::mapToValue(const QPointF &position, QAbstractSeries *series)
654 674 {
655 675 return d_ptr->m_dataset->mapToValue(position, series);
656 676 }
657 677
658 678 /*!
659 679 Returns the position on the chart widget that corresponds to the \a value in the \a series domain.
660 680 */
661 681 QPointF QChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
662 682 {
663 683 return d_ptr->m_dataset->mapToPosition(value, series);
664 684 }
665 685
666 686 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
667 687
668 688 QChartPrivate::QChartPrivate(QChart *q, QChart::ChartType type):
669 689 q_ptr(q),
670 690 m_legend(0),
671 691 m_dataset(new ChartDataSet(q)),
672 692 m_presenter(new ChartPresenter(q, type)),
673 693 m_themeManager(new ChartThemeManager(q)),
674 694 m_type(type)
675 695 {
676 696 QObject::connect(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), m_presenter, SLOT(handleSeriesAdded(QAbstractSeries*)));
677 697 QObject::connect(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), m_presenter, SLOT(handleSeriesRemoved(QAbstractSeries*)));
678 698 QObject::connect(m_dataset, SIGNAL(axisAdded(QAbstractAxis*)), m_presenter, SLOT(handleAxisAdded(QAbstractAxis*)));
679 699 QObject::connect(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*)), m_presenter, SLOT(handleAxisRemoved(QAbstractAxis*)));
680 700 QObject::connect(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), m_themeManager, SLOT(handleSeriesAdded(QAbstractSeries*)));
681 701 QObject::connect(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), m_themeManager, SLOT(handleSeriesRemoved(QAbstractSeries*)));
682 702 QObject::connect(m_dataset, SIGNAL(axisAdded(QAbstractAxis*)), m_themeManager, SLOT(handleAxisAdded(QAbstractAxis*)));
683 703 QObject::connect(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*)), m_themeManager, SLOT(handleAxisRemoved(QAbstractAxis*)));
684 704 }
685 705
686 706 QChartPrivate::~QChartPrivate()
687 707 {
688 708 }
689 709
690 710 // Hackish solution to the problem of explicitly assigning the default pen/brush/font
691 711 // to a series or axis and having theme override it:
692 712 // Initialize pens, brushes, and fonts to something nobody is likely to ever use,
693 713 // so that default theme initialization will always set these properly.
694 714 QPen &QChartPrivate::defaultPen()
695 715 {
696 716 static QPen defaultPen(QColor(1, 2, 0), 0.93247536);
697 717 return defaultPen;
698 718 }
699 719
700 720 QBrush &QChartPrivate::defaultBrush()
701 721 {
702 722 static QBrush defaultBrush(QColor(1, 2, 0), Qt::Dense7Pattern);
703 723 return defaultBrush;
704 724 }
705 725
706 726 QFont &QChartPrivate::defaultFont()
707 727 {
708 728 static bool defaultFontInitialized(false);
709 729 static QFont defaultFont;
710 730 if (!defaultFontInitialized) {
711 731 defaultFont.setPointSizeF(8.34563465);
712 732 defaultFontInitialized = true;
713 733 }
714 734 return defaultFont;
715 735 }
716 736
717 737 void QChartPrivate::init()
718 738 {
719 739 m_legend = new LegendScroller(q_ptr);
720 740 q_ptr->setTheme(QChart::ChartThemeLight);
721 741 q_ptr->setLayout(m_presenter->layout());
722 742 }
723 743
724 744 void QChartPrivate::zoomIn(qreal factor)
725 745 {
726 746 QRectF rect = m_presenter->geometry();
727 747 rect.setWidth(rect.width() / factor);
728 748 rect.setHeight(rect.height() / factor);
729 749 rect.moveCenter(m_presenter->geometry().center());
730 750 zoomIn(rect);
731 751 }
732 752
733 753 void QChartPrivate::zoomIn(const QRectF &rect)
734 754 {
735 755 if (!rect.isValid())
736 756 return;
737 757
738 758 QRectF r = rect.normalized();
739 759 const QRectF geometry = m_presenter->geometry();
740 760 r.translate(-geometry.topLeft());
741 761
742 762 if (!r.isValid())
743 763 return;
744 764
745 765 QPointF zoomPoint(r.center().x() / geometry.width(), r.center().y() / geometry.height());
746 766 m_presenter->setState(ChartPresenter::ZoomInState,zoomPoint);
747 767 m_dataset->zoomInDomain(r);
748 768 m_presenter->setState(ChartPresenter::ShowState,QPointF());
749 769
750 770 }
751 771
772 void QChartPrivate::zoomReset()
773 {
774 m_dataset->zoomResetDomain();
775 }
776
777 bool QChartPrivate::isZoomed()
778 {
779 return m_dataset->isZoomedDomain();
780 }
781
752 782 void QChartPrivate::zoomOut(qreal factor)
753 783 {
754 784 const QRectF geometry = m_presenter->geometry();
755 785
756 786 QRectF r;
757 787 r.setSize(geometry.size() / factor);
758 788 r.moveCenter(QPointF(geometry.size().width()/2 ,geometry.size().height()/2));
759 789 if (!r.isValid())
760 790 return;
761 791
762 792 QPointF zoomPoint(r.center().x() / geometry.width(), r.center().y() / geometry.height());
763 793 m_presenter->setState(ChartPresenter::ZoomOutState,zoomPoint);
764 794 m_dataset->zoomOutDomain(r);
765 795 m_presenter->setState(ChartPresenter::ShowState,QPointF());
766 796 }
767 797
768 798 void QChartPrivate::scroll(qreal dx, qreal dy)
769 799 {
770 800 if (dx < 0) m_presenter->setState(ChartPresenter::ScrollLeftState,QPointF());
771 801 if (dx > 0) m_presenter->setState(ChartPresenter::ScrollRightState,QPointF());
772 802 if (dy < 0) m_presenter->setState(ChartPresenter::ScrollUpState,QPointF());
773 803 if (dy > 0) m_presenter->setState(ChartPresenter::ScrollDownState,QPointF());
774 804
775 805 m_dataset->scrollDomain(dx, dy);
776 806 m_presenter->setState(ChartPresenter::ShowState,QPointF());
777 807 }
778 808
779 809 #include "moc_qchart.cpp"
780 810
781 811 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,169 +1,171
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #ifndef QCHART_H
22 22 #define QCHART_H
23 23
24 24 #include <QAbstractSeries>
25 25 #include <QLegend>
26 26 #include <QGraphicsWidget>
27 27 #include <QMargins>
28 28
29 29 class QGraphicsSceneResizeEvent;
30 30
31 31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 32
33 33 class QAbstractSeries;
34 34 class QAbstractAxis;
35 35 class QLegend;
36 36 class QChartPrivate;
37 37
38 38 class QTCOMMERCIALCHART_EXPORT QChart : public QGraphicsWidget
39 39 {
40 40 Q_OBJECT
41 41 Q_PROPERTY(QChart::ChartTheme theme READ theme WRITE setTheme)
42 42 Q_PROPERTY(QString title READ title WRITE setTitle)
43 43 Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible)
44 44 Q_PROPERTY(bool dropShadowEnabled READ isDropShadowEnabled WRITE setDropShadowEnabled)
45 45 Q_PROPERTY(QChart::AnimationOptions animationOptions READ animationOptions WRITE setAnimationOptions)
46 46 Q_PROPERTY(QMargins minimumMargins READ minimumMargins WRITE setMinimumMargins)
47 47 Q_PROPERTY(QMargins margins READ margins WRITE setMargins)
48 48 Q_PROPERTY(QChart::ChartType chartType READ chartType)
49 49 Q_PROPERTY(bool plotAreaBackgroundVisible READ isPlotAreaBackgroundVisible WRITE setPlotAreaBackgroundVisible)
50 50 Q_ENUMS(ChartTheme)
51 51 Q_ENUMS(AnimationOption)
52 52 Q_ENUMS(ChartType)
53 53
54 54 public:
55 55 enum ChartType {
56 56 ChartTypeUndefined = 0,
57 57 ChartTypeCartesian,
58 58 ChartTypePolar
59 59 };
60 60
61 61 enum ChartTheme {
62 62 ChartThemeLight = 0,
63 63 ChartThemeBlueCerulean,
64 64 ChartThemeDark,
65 65 ChartThemeBrownSand,
66 66 ChartThemeBlueNcs,
67 67 ChartThemeHighContrast,
68 68 ChartThemeBlueIcy
69 69 };
70 70
71 71 enum AnimationOption {
72 72 NoAnimation = 0x0,
73 73 GridAxisAnimations = 0x1,
74 74 SeriesAnimations = 0x2,
75 75 AllAnimations = 0x3
76 76 };
77 77
78 78 Q_DECLARE_FLAGS(AnimationOptions, AnimationOption)
79 79
80 80 public:
81 81 explicit QChart(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
82 82 ~QChart();
83 83
84 84 void addSeries(QAbstractSeries *series);
85 85 void removeSeries(QAbstractSeries *series);
86 86 void removeAllSeries();
87 87 QList<QAbstractSeries *> series() const;
88 88
89 89 // *** deprecated ***
90 90 void setAxisX(QAbstractAxis *axis, QAbstractSeries *series = 0);
91 91 void setAxisY(QAbstractAxis *axis, QAbstractSeries *series = 0);
92 92 QAbstractAxis *axisX(QAbstractSeries *series = 0) const;
93 93 QAbstractAxis *axisY(QAbstractSeries *series = 0) const;
94 94 // ******************
95 95
96 96 void addAxis(QAbstractAxis *axis, Qt::Alignment alignment);
97 97 void removeAxis(QAbstractAxis *axis);
98 98 QList<QAbstractAxis*> axes(Qt::Orientations orientation = Qt::Horizontal|Qt::Vertical, QAbstractSeries *series = 0) const;
99 99
100 100 void createDefaultAxes();
101 101
102 102 void setTheme(QChart::ChartTheme theme);
103 103 QChart::ChartTheme theme() const;
104 104
105 105 void setTitle(const QString &title);
106 106 QString title() const;
107 107 void setTitleFont(const QFont &font);
108 108 QFont titleFont() const;
109 109 void setTitleBrush(const QBrush &brush);
110 110 QBrush titleBrush() const;
111 111
112 112 void setBackgroundBrush(const QBrush &brush);
113 113 QBrush backgroundBrush() const;
114 114 void setBackgroundPen(const QPen &pen);
115 115 QPen backgroundPen() const;
116 116 void setBackgroundVisible(bool visible = true);
117 117 bool isBackgroundVisible() const;
118 118
119 119 void setDropShadowEnabled(bool enabled = true);
120 120 bool isDropShadowEnabled() const;
121 121 void setAnimationOptions(AnimationOptions options);
122 122 AnimationOptions animationOptions() const;
123 123
124 124 void zoomIn();
125 125 void zoomOut();
126 126
127 127 void zoomIn(const QRectF &rect);
128 128 void zoom(qreal factor);
129 void zoomReset();
130 bool isZoomed();
129 131
130 132 void scroll(qreal dx, qreal dy);
131 133
132 134 QLegend *legend() const;
133 135
134 136 void setMinimumMargins(const QMargins& margins);
135 137 QMargins minimumMargins() const;
136 138
137 139 void setMargins(const QMargins &margins);
138 140 QMargins margins() const;
139 141
140 142 QRectF plotArea() const;
141 143 void setPlotAreaBackgroundBrush(const QBrush &brush);
142 144 QBrush plotAreaBackgroundBrush() const;
143 145 void setPlotAreaBackgroundPen(const QPen &pen);
144 146 QPen plotAreaBackgroundPen() const;
145 147 void setPlotAreaBackgroundVisible(bool visible = true);
146 148 bool isPlotAreaBackgroundVisible() const;
147 149
148 150 QPointF mapToValue(const QPointF &position, QAbstractSeries *series = 0);
149 151 QPointF mapToPosition(const QPointF &value, QAbstractSeries *series = 0);
150 152
151 153 ChartType chartType() const;
152 154
153 155 protected:
154 156 explicit QChart(QChart::ChartType type, QGraphicsItem *parent, Qt::WindowFlags wFlags);
155 157 QScopedPointer<QChartPrivate> d_ptr;
156 158 friend class QLegend;
157 159 friend class DeclarativeChart;
158 160 friend class ChartDataSet;
159 161 friend class ChartPresenter;
160 162 friend class ChartThemeManager;
161 163 friend class QAbstractSeries;
162 164 Q_DISABLE_COPY(QChart)
163 165 };
164 166
165 167 QTCOMMERCIALCHART_END_NAMESPACE
166 168
167 169 Q_DECLARE_OPERATORS_FOR_FLAGS(QTCOMMERCIALCHART_NAMESPACE::QChart::AnimationOptions)
168 170
169 171 #endif // QCHART_H
@@ -1,68 +1,70
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef QCHART_P_H
31 31 #define QCHART_P_H
32 32
33 33 #include "qchartglobal.h"
34 34 #include "qchart.h"
35 35
36 36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 37
38 38 class ChartThemeManager;
39 39 class ChartPresenter;
40 40 class QLegend;
41 41 class ChartDataSet;
42 42
43 43 class QChartPrivate
44 44 {
45 45
46 46 public:
47 47 QChartPrivate(QChart *q, QChart::ChartType type);
48 48 ~QChartPrivate();
49 49 QChart *q_ptr;
50 50 QLegend *m_legend;
51 51 ChartDataSet *m_dataset;
52 52 ChartPresenter *m_presenter;
53 53 ChartThemeManager *m_themeManager;
54 54 QChart::ChartType m_type;
55 55
56 56 static QPen &defaultPen();
57 57 static QBrush &defaultBrush();
58 58 static QFont &defaultFont();
59 59
60 60 void init();
61 61 void zoomIn(qreal factor);
62 62 void zoomOut(qreal factor);
63 63 void zoomIn(const QRectF &rect);
64 void zoomReset();
65 bool isZoomed();
64 66 void scroll(qreal dx, qreal dy);
65 67 };
66 68
67 69 QTCOMMERCIALCHART_END_NAMESPACE
68 70 #endif
@@ -1,285 +1,285
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qchartview.h"
22 22 #include "qchartview_p.h"
23 23 #include "qchart_p.h"
24 24 #include <QGraphicsScene>
25 25 #include <QRubberBand>
26 26
27 27 /*!
28 28 \enum QChartView::RubberBand
29 29
30 30 This enum describes the different types of rubber bands that can be used for zoom rect selection
31 31
32 32 \value NoRubberBand
33 33 \value VerticalRubberBand
34 34 \value HorizonalRubberBand
35 35 \value RectangleRubberBand
36 36 */
37 37
38 38 /*!
39 39 \class QChartView
40 40 \brief Standalone charting widget.
41 41
42 42 QChartView is a standalone widget that can display charts. It does not require separate
43 43 QGraphicsScene to work. If you want to display a chart in your existing QGraphicsScene,
44 44 you need to use the QChart (or QPolarChart) class instead.
45 45
46 46 \sa QChart, QPolarChart
47 47 */
48 48
49 49 QTCOMMERCIALCHART_BEGIN_NAMESPACE
50 50
51 51 /*!
52 52 Constructs a chartView object with parent \a parent.
53 53 */
54 54
55 55 QChartView::QChartView(QWidget *parent)
56 56 : QGraphicsView(parent),
57 57 d_ptr(new QChartViewPrivate(this))
58 58 {
59 59
60 60 }
61 61
62 62 /*!
63 63 Constructs a chartview object with parent \a parent to display a \a chart.
64 64 Ownership of the \a chart is passed to chartview.
65 65 */
66 66
67 67 QChartView::QChartView(QChart *chart, QWidget *parent)
68 68 : QGraphicsView(parent),
69 69 d_ptr(new QChartViewPrivate(this, chart))
70 70 {
71 71
72 72 }
73 73
74 74
75 75 /*!
76 76 Destroys the chartview object and the associated chart.
77 77 */
78 78 QChartView::~QChartView()
79 79 {
80 80 }
81 81
82 82 /*!
83 83 Returns the pointer to the associated chart.
84 84 */
85 85 QChart *QChartView::chart() const
86 86 {
87 87 return d_ptr->m_chart;
88 88 }
89 89
90 90 /*!
91 91 Sets the current chart to \a chart. Ownership of the new chart is passed to chartview
92 92 and ownership of the previous chart is released.
93 93
94 94 To avoid memory leaks users need to make sure the previous chart is deleted.
95 95 */
96 96
97 97 void QChartView::setChart(QChart *chart)
98 98 {
99 99 d_ptr->setChart(chart);
100 100 }
101 101
102 102 /*!
103 103 Sets the rubber band flags to \a rubberBand.
104 104 Selected flags determine the way zooming is performed.
105 105
106 106 \note Rubber band zooming is not supported for polar charts.
107 107 */
108 108 void QChartView::setRubberBand(const RubberBands &rubberBand)
109 109 {
110 110 d_ptr->m_rubberBandFlags = rubberBand;
111 111
112 112 if (!d_ptr->m_rubberBandFlags) {
113 113 delete d_ptr->m_rubberBand;
114 114 d_ptr->m_rubberBand = 0;
115 115 return;
116 116 }
117 117
118 118 if (!d_ptr->m_rubberBand) {
119 119 d_ptr->m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
120 120 d_ptr->m_rubberBand->setEnabled(true);
121 121 }
122 122 }
123 123
124 124 /*!
125 125 Returns the rubber band flags that are currently being used by the widget.
126 126 */
127 127 QChartView::RubberBands QChartView::rubberBand() const
128 128 {
129 129 return d_ptr->m_rubberBandFlags;
130 130 }
131 131
132 132 /*!
133 133 If Left mouse button is pressed and the rubber band is enabled the \a event is accepted and the rubber band is displayed on the screen allowing the user to select the zoom area.
134 134 If different mouse button is pressed and/or the rubber band is disabled then the \a event is passed to QGraphicsView::mousePressEvent() implementation.
135 135 */
136 136 void QChartView::mousePressEvent(QMouseEvent *event)
137 137 {
138 138 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isEnabled() && event->button() == Qt::LeftButton) {
139 139
140 140 QRectF plotArea = d_ptr->m_chart->plotArea();
141 141
142 142 if (plotArea.contains(event->pos())) {
143 143 d_ptr->m_rubberBandOrigin = event->pos();
144 144 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin, QSize()));
145 145 d_ptr->m_rubberBand->show();
146 146 event->accept();
147 147 }
148 148 } else {
149 149 QGraphicsView::mousePressEvent(event);
150 150 }
151 151 }
152 152
153 153 /*!
154 154 If the rubber band rectange has been displayed in pressEvent then \a event data is used to update the rubber band geometry.
155 155 Otherwise the default QGraphicsView::mouseMoveEvent implementation is called.
156 156 */
157 157 void QChartView::mouseMoveEvent(QMouseEvent *event)
158 158 {
159 159 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
160 160 QRect rect = d_ptr->m_chart->plotArea().toRect();
161 161 int width = event->pos().x() - d_ptr->m_rubberBandOrigin.x();
162 162 int height = event->pos().y() - d_ptr->m_rubberBandOrigin.y();
163 163 if (!d_ptr->m_rubberBandFlags.testFlag(VerticalRubberBand)) {
164 164 d_ptr->m_rubberBandOrigin.setY(rect.top());
165 165 height = rect.height();
166 166 }
167 167 if (!d_ptr->m_rubberBandFlags.testFlag(HorizonalRubberBand)) {
168 168 d_ptr->m_rubberBandOrigin.setX(rect.left());
169 169 width = rect.width();
170 170 }
171 171 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin.x(), d_ptr->m_rubberBandOrigin.y(), width, height).normalized());
172 172 } else {
173 173 QGraphicsView::mouseMoveEvent(event);
174 174 }
175 175 }
176 176
177 177 /*!
178 178 If left mouse button is released and the rubber band is enabled then \a event is accepted and
179 179 the view is zoomed into the rect specified by the rubber band.
180 If it is a right mouse button \a event then the rubber band is dismissed and the zoom is canceled.
180 If it is a right mouse button \a event then the view is zoomed out.
181 181 */
182 182 void QChartView::mouseReleaseEvent(QMouseEvent *event)
183 183 {
184 184 if (d_ptr->m_rubberBand) {
185 185 if (event->button() == Qt::LeftButton && d_ptr->m_rubberBand->isVisible()) {
186 186 d_ptr->m_rubberBand->hide();
187 187 QRectF rect = d_ptr->m_rubberBand->geometry();
188 188 // Since plotArea uses QRectF and rubberband uses QRect, we can't just blindly use
189 189 // rubberband's dimensions for vertical and horizontal rubberbands, where one
190 190 // dimension must match the corresponding plotArea dimension exactly.
191 191 if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
192 192 rect.setX(d_ptr->m_chart->plotArea().x());
193 193 rect.setWidth(d_ptr->m_chart->plotArea().width());
194 194 } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
195 195 rect.setY(d_ptr->m_chart->plotArea().y());
196 196 rect.setHeight(d_ptr->m_chart->plotArea().height());
197 197 }
198 198 d_ptr->m_chart->zoomIn(rect);
199 199 event->accept();
200 200 }
201 201
202 202 if (event->button() == Qt::RightButton) {
203 203 d_ptr->m_chart->zoomOut();
204 204 event->accept();
205 205 }
206 206 } else {
207 207 QGraphicsView::mouseReleaseEvent(event);
208 208 }
209 209 }
210 210
211 211 /*!
212 212 Resizes and updates the chart area using the \a event data
213 213 */
214 214 void QChartView::resizeEvent(QResizeEvent *event)
215 215 {
216 216 QGraphicsView::resizeEvent(event);
217 217 d_ptr->resize();
218 218 }
219 219
220 220 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
221 221
222 222 QChartViewPrivate::QChartViewPrivate(QChartView *q, QChart *chart)
223 223 : q_ptr(q),
224 224 m_scene(new QGraphicsScene(q)),
225 225 m_chart(chart),
226 226 m_rubberBand(0),
227 227 m_rubberBandFlags(QChartView::NoRubberBand)
228 228 {
229 229 q_ptr->setFrameShape(QFrame::NoFrame);
230 230 q_ptr->setBackgroundRole(QPalette::Window);
231 231 q_ptr->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
232 232 q_ptr->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
233 233 q_ptr->setScene(m_scene);
234 234 q_ptr->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
235 235 if (!m_chart)
236 236 m_chart = new QChart();
237 237 m_scene->addItem(m_chart);
238 238 }
239 239
240 240 QChartViewPrivate::~QChartViewPrivate()
241 241 {
242 242 }
243 243
244 244 void QChartViewPrivate::setChart(QChart *chart)
245 245 {
246 246 Q_ASSERT(chart);
247 247
248 248 if (m_chart == chart)
249 249 return;
250 250
251 251 if (m_chart)
252 252 m_scene->removeItem(m_chart);
253 253
254 254 m_chart = chart;
255 255 m_scene->addItem(m_chart);
256 256
257 257 resize();
258 258 }
259 259
260 260 void QChartViewPrivate::resize()
261 261 {
262 262 // Fit the chart into view if it has been rotated
263 263 qreal sinA = qAbs(q_ptr->transform().m21());
264 264 qreal cosA = qAbs(q_ptr->transform().m11());
265 265 QSize chartSize = q_ptr->size();
266 266
267 267 if (sinA == 1.0) {
268 268 chartSize.setHeight(q_ptr->size().width());
269 269 chartSize.setWidth(q_ptr->size().height());
270 270 } else if (sinA != 0.0) {
271 271 // Non-90 degree rotation, find largest square chart that can fit into the view.
272 272 qreal minDimension = qMin(q_ptr->size().width(), q_ptr->size().height());
273 273 qreal h = (minDimension - (minDimension / ((sinA / cosA) + 1.0))) / sinA;
274 274 chartSize.setHeight(h);
275 275 chartSize.setWidth(h);
276 276 }
277 277
278 278 m_chart->resize(chartSize);
279 279 q_ptr->setMinimumSize(m_chart->minimumSize().toSize());
280 280 q_ptr->setSceneRect(m_chart->geometry());
281 281 }
282 282
283 283 #include "moc_qchartview.cpp"
284 284
285 285 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,961 +1,1033
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include <QtTest/QtTest>
22 22 #include <qchartview.h>
23 23 #include <qlineseries.h>
24 24 #include <qareaseries.h>
25 25 #include <qscatterseries.h>
26 26 #include <qsplineseries.h>
27 27 #include <qpieseries.h>
28 28 #include <qabstractbarseries.h>
29 29 #include <qbarseries.h>
30 30 #include <qpercentbarseries.h>
31 31 #include <qstackedbarseries.h>
32 32 #include <qvalueaxis.h>
33 33 #include <qbarcategoryaxis.h>
34 34 #include "tst_definitions.h"
35 35
36 36 QTCOMMERCIALCHART_USE_NAMESPACE
37 37
38 38 Q_DECLARE_METATYPE(QAbstractAxis *)
39 39 Q_DECLARE_METATYPE(QValueAxis *)
40 40 Q_DECLARE_METATYPE(QBarCategoryAxis *)
41 41 Q_DECLARE_METATYPE(QAbstractSeries *)
42 42 Q_DECLARE_METATYPE(QChart::AnimationOption)
43 43 Q_DECLARE_METATYPE(QBrush)
44 44 Q_DECLARE_METATYPE(QPen)
45 45 Q_DECLARE_METATYPE(QChart::ChartTheme)
46 46
47 47 class tst_QChart : public QObject
48 48 {
49 49 Q_OBJECT
50 50
51 51 public slots:
52 52 void initTestCase();
53 53 void cleanupTestCase();
54 54 void init();
55 55 void cleanup();
56 56
57 57 private slots:
58 58 void qchart_data();
59 59 void qchart();
60 60 void addSeries_data();
61 61 void addSeries();
62 62 void animationOptions_data();
63 63 void animationOptions();
64 64 void axisX_data();
65 65 void axisX();
66 66 void axisY_data();
67 67 void axisY();
68 68 void backgroundBrush_data();
69 69 void backgroundBrush();
70 70 void backgroundPen_data();
71 71 void backgroundPen();
72 72 void isBackgroundVisible_data();
73 73 void isBackgroundVisible();
74 74 void plotAreaBackgroundBrush_data();
75 75 void plotAreaBackgroundBrush();
76 76 void plotAreaBackgroundPen_data();
77 77 void plotAreaBackgroundPen();
78 78 void isPlotAreaBackgroundVisible_data();
79 79 void isPlotAreaBackgroundVisible();
80 80 void legend_data();
81 81 void legend();
82 82 void plotArea_data();
83 83 void plotArea();
84 84 void removeAllSeries_data();
85 85 void removeAllSeries();
86 86 void removeSeries_data();
87 87 void removeSeries();
88 88 void scroll_right_data();
89 89 void scroll_right();
90 90 void scroll_left_data();
91 91 void scroll_left();
92 92 void scroll_up_data();
93 93 void scroll_up();
94 94 void scroll_down_data();
95 95 void scroll_down();
96 96 void theme_data();
97 97 void theme();
98 98 void title_data();
99 99 void title();
100 100 void titleBrush_data();
101 101 void titleBrush();
102 102 void titleFont_data();
103 103 void titleFont();
104 104 void zoomIn_data();
105 105 void zoomIn();
106 106 void zoomOut_data();
107 107 void zoomOut();
108 void zoomReset();
108 109 void createDefaultAxesForLineSeries_data();
109 110 void createDefaultAxesForLineSeries();
110 111 void axisPolarOrientation();
111 112 private:
112 113 void createTestData();
113 114
114 115 private:
115 116 QChartView* m_view;
116 117 QChart* m_chart;
117 118 };
118 119
119 120 void tst_QChart::initTestCase()
120 121 {
121 122
122 123 }
123 124
124 125 void tst_QChart::cleanupTestCase()
125 126 {
126 127
127 128 }
128 129
129 130 void tst_QChart::init()
130 131 {
131 132 m_view = new QChartView(newQChartOrQPolarChart());
132 133 m_chart = m_view->chart();
133 134 }
134 135
135 136 void tst_QChart::cleanup()
136 137 {
137 138 delete m_view;
138 139 m_view = 0;
139 140 m_chart = 0;
140 141 }
141 142
142 143
143 144 void tst_QChart::createTestData()
144 145 {
145 146 QLineSeries* series0 = new QLineSeries(this);
146 147 *series0 << QPointF(0, 0) << QPointF(100, 100);
147 148 m_chart->addSeries(series0);
148 149 m_view->show();
149 150 QTest::qWaitForWindowShown(m_view);
150 151 }
151 152
152 153 void tst_QChart::qchart_data()
153 154 {
154 155 }
155 156
156 157 void tst_QChart::qchart()
157 158 {
158 159 QVERIFY(m_chart);
159 160 QVERIFY(m_chart->legend());
160 161 QVERIFY(m_chart->legend()->isVisible());
161 162
162 163 QCOMPARE(m_chart->animationOptions(), QChart::NoAnimation);
163 164 QVERIFY(!m_chart->axisX());
164 165 QVERIFY(!m_chart->axisY());
165 166 QVERIFY(m_chart->backgroundBrush()!=QBrush());
166 167 QVERIFY(m_chart->backgroundPen()!=QPen());
167 168 QCOMPARE(m_chart->isBackgroundVisible(), true);
168 169 QVERIFY(m_chart->plotArea().top()==0);
169 170 QVERIFY(m_chart->plotArea().left()==0);
170 171 QVERIFY(m_chart->plotArea().right()==0);
171 172 QVERIFY(m_chart->plotArea().bottom()==0);
172 173 QCOMPARE(m_chart->theme(), QChart::ChartThemeLight);
173 174 QCOMPARE(m_chart->title(), QString());
174 175
175 176 //QCOMPARE(m_chart->titleBrush(),QBrush());
176 177 //QCOMPARE(m_chart->titleFont(),QFont());
177 178
178 179 m_chart->removeAllSeries();
179 180 m_chart->scroll(0,0);
180 181
181 182 m_chart->zoomIn();
182 183 m_chart->zoomIn(QRectF());
183 184 m_chart->zoomOut();
184 185
185 186 m_view->show();
186 187
187 188 QVERIFY(m_chart->plotArea().top()>0);
188 189 QVERIFY(m_chart->plotArea().left()>0);
189 190 QVERIFY(m_chart->plotArea().right()>0);
190 191 QVERIFY(m_chart->plotArea().bottom()>0);
191 192 }
192 193
193 194 void tst_QChart::addSeries_data()
194 195 {
195 196 QTest::addColumn<QAbstractSeries *>("series");
196 197
197 198 QAbstractSeries* line = new QLineSeries(this);
198 199 QAbstractSeries* area = new QAreaSeries(static_cast<QLineSeries*>(line));
199 200 QAbstractSeries* scatter = new QScatterSeries(this);
200 201 QAbstractSeries* spline = new QSplineSeries(this);
201 202
202 203 QTest::newRow("lineSeries") << line;
203 204 QTest::newRow("areaSeries") << area;
204 205 QTest::newRow("scatterSeries") << scatter;
205 206 QTest::newRow("splineSeries") << spline;
206 207
207 208 if (!isPolarTest()) {
208 209 QAbstractSeries* pie = new QPieSeries(this);
209 210 QAbstractSeries* bar = new QBarSeries(this);
210 211 QAbstractSeries* percent = new QPercentBarSeries(this);
211 212 QAbstractSeries* stacked = new QStackedBarSeries(this);
212 213 QTest::newRow("pieSeries") << pie;
213 214 QTest::newRow("barSeries") << bar;
214 215 QTest::newRow("percentBarSeries") << percent;
215 216 QTest::newRow("stackedBarSeries") << stacked;
216 217 }
217 218 }
218 219
219 220 void tst_QChart::addSeries()
220 221 {
221 222 QFETCH(QAbstractSeries *, series);
222 223 m_view->show();
223 224 QTest::qWaitForWindowShown(m_view);
224 225 QVERIFY(!series->chart());
225 226 QCOMPARE(m_chart->series().count(), 0);
226 227 m_chart->addSeries(series);
227 228 QCOMPARE(m_chart->series().count(), 1);
228 229 QCOMPARE(m_chart->series().first(), series);
229 230 QVERIFY(series->chart() == m_chart);
230 231 m_chart->createDefaultAxes();
231 232 if(series->type()!=QAbstractSeries::SeriesTypePie){
232 233 QVERIFY(m_chart->axisY(series));
233 234 QVERIFY(m_chart->axisX(series));
234 235 }else{
235 236 QVERIFY(!m_chart->axisY(series));
236 237 QVERIFY(!m_chart->axisX(series));
237 238 }
238 239 m_chart->removeSeries(series);
239 240 QVERIFY(!series->chart());
240 241 QCOMPARE(m_chart->series().count(), 0);
241 242 }
242 243
243 244 void tst_QChart::animationOptions_data()
244 245 {
245 246 QTest::addColumn<QChart::AnimationOption>("animationOptions");
246 247 QTest::newRow("AllAnimations") << QChart::AllAnimations;
247 248 QTest::newRow("NoAnimation") << QChart::NoAnimation;
248 249 QTest::newRow("GridAxisAnimations") << QChart::GridAxisAnimations;
249 250 QTest::newRow("SeriesAnimations") << QChart::SeriesAnimations;
250 251 }
251 252
252 253 void tst_QChart::animationOptions()
253 254 {
254 255 createTestData();
255 256 QFETCH(QChart::AnimationOption, animationOptions);
256 257 m_chart->setAnimationOptions(animationOptions);
257 258 QCOMPARE(m_chart->animationOptions(), animationOptions);
258 259 }
259 260
260 261 void tst_QChart::axisX_data()
261 262 {
262 263
263 264 QTest::addColumn<QAbstractAxis*>("axis");
264 265 QTest::addColumn<QAbstractSeries *>("series");
265 266
266 267 QTest::newRow("categories,lineSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QLineSeries(this);
267 268 QTest::newRow("categories,areaSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QAreaSeries(new QLineSeries(this));
268 269 QTest::newRow("categories,scatterSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QScatterSeries(this);
269 270 QTest::newRow("categories,splineSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QSplineSeries(this);
270 271 if (!isPolarTest()) {
271 272 QTest::newRow("categories,pieSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QPieSeries(this);
272 273 QTest::newRow("categories,barSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QBarSeries(this);
273 274 QTest::newRow("categories,percentBarSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QPercentBarSeries(this);
274 275 QTest::newRow("categories,stackedBarSeries") << (QAbstractAxis*) new QBarCategoryAxis() << (QAbstractSeries*) new QStackedBarSeries(this);
275 276 }
276 277
277 278 QTest::newRow("value,lineSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QLineSeries(this);
278 279 QTest::newRow("value,areaSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QAreaSeries(new QLineSeries(this));
279 280 QTest::newRow("value,scatterSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QScatterSeries(this);
280 281 QTest::newRow("value,splineSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QSplineSeries(this);
281 282 if (!isPolarTest()) {
282 283 QTest::newRow("value,pieSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QPieSeries(this);
283 284 QTest::newRow("value,barSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QBarSeries(this);
284 285 QTest::newRow("value,percentBarSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QPercentBarSeries(this);
285 286 QTest::newRow("value,stackedBarSeries") << (QAbstractAxis*) new QValueAxis() << (QAbstractSeries*) new QStackedBarSeries(this);
286 287 }
287 288 }
288 289
289 290 void tst_QChart::axisX()
290 291 {
291 292 QFETCH(QAbstractAxis*, axis);
292 293 QFETCH(QAbstractSeries*, series);
293 294 QVERIFY(!m_chart->axisX());
294 295 m_view->show();
295 296 QTest::qWaitForWindowShown(m_view);
296 297 m_chart->addSeries(series);
297 298 m_chart->setAxisX(axis,series);
298 299 QVERIFY(m_chart->axisX(series)==axis);
299 300 }
300 301
301 302 void tst_QChart::axisY_data()
302 303 {
303 304 axisX_data();
304 305 }
305 306
306 307
307 308 void tst_QChart::axisY()
308 309 {
309 310 QFETCH(QAbstractAxis*, axis);
310 311 QFETCH(QAbstractSeries*, series);
311 312 QVERIFY(!m_chart->axisY());
312 313 m_view->show();
313 314 QTest::qWaitForWindowShown(m_view);
314 315 m_chart->addSeries(series);
315 316 m_chart->setAxisY(axis,series);
316 317 QVERIFY(m_chart->axisY(series)==axis);
317 318 }
318 319
319 320 void tst_QChart::backgroundBrush_data()
320 321 {
321 322 QTest::addColumn<QBrush>("backgroundBrush");
322 323 QTest::newRow("null") << QBrush();
323 324 QTest::newRow("blue") << QBrush(Qt::blue);
324 325 QTest::newRow("white") << QBrush(Qt::white);
325 326 QTest::newRow("black") << QBrush(Qt::black);
326 327 }
327 328
328 329 void tst_QChart::backgroundBrush()
329 330 {
330 331 QFETCH(QBrush, backgroundBrush);
331 332 m_chart->setBackgroundBrush(backgroundBrush);
332 333 QCOMPARE(m_chart->backgroundBrush(), backgroundBrush);
333 334 }
334 335
335 336 void tst_QChart::backgroundPen_data()
336 337 {
337 338 QTest::addColumn<QPen>("backgroundPen");
338 339 QTest::newRow("null") << QPen();
339 340 QTest::newRow("blue") << QPen(Qt::blue);
340 341 QTest::newRow("white") << QPen(Qt::white);
341 342 QTest::newRow("black") << QPen(Qt::black);
342 343 }
343 344
344 345
345 346 void tst_QChart::backgroundPen()
346 347 {
347 348 QFETCH(QPen, backgroundPen);
348 349 m_chart->setBackgroundPen(backgroundPen);
349 350 QCOMPARE(m_chart->backgroundPen(), backgroundPen);
350 351 }
351 352
352 353 void tst_QChart::isBackgroundVisible_data()
353 354 {
354 355 QTest::addColumn<bool>("isBackgroundVisible");
355 356 QTest::newRow("true") << true;
356 357 QTest::newRow("false") << false;
357 358 }
358 359
359 360 void tst_QChart::isBackgroundVisible()
360 361 {
361 362 QFETCH(bool, isBackgroundVisible);
362 363 m_chart->setBackgroundVisible(isBackgroundVisible);
363 364 QCOMPARE(m_chart->isBackgroundVisible(), isBackgroundVisible);
364 365 }
365 366
366 367 void tst_QChart::plotAreaBackgroundBrush_data()
367 368 {
368 369 QTest::addColumn<QBrush>("plotAreaBackgroundBrush");
369 370 QTest::newRow("null") << QBrush();
370 371 QTest::newRow("blue") << QBrush(Qt::blue);
371 372 QTest::newRow("white") << QBrush(Qt::white);
372 373 QTest::newRow("black") << QBrush(Qt::black);
373 374 }
374 375
375 376 void tst_QChart::plotAreaBackgroundBrush()
376 377 {
377 378 QFETCH(QBrush, plotAreaBackgroundBrush);
378 379 m_chart->setPlotAreaBackgroundBrush(plotAreaBackgroundBrush);
379 380 QCOMPARE(m_chart->plotAreaBackgroundBrush(), plotAreaBackgroundBrush);
380 381 }
381 382
382 383 void tst_QChart::plotAreaBackgroundPen_data()
383 384 {
384 385 QTest::addColumn<QPen>("plotAreaBackgroundPen");
385 386 QTest::newRow("null") << QPen();
386 387 QTest::newRow("blue") << QPen(Qt::blue);
387 388 QTest::newRow("white") << QPen(Qt::white);
388 389 QTest::newRow("black") << QPen(Qt::black);
389 390 }
390 391
391 392
392 393 void tst_QChart::plotAreaBackgroundPen()
393 394 {
394 395 QFETCH(QPen, plotAreaBackgroundPen);
395 396 m_chart->setPlotAreaBackgroundPen(plotAreaBackgroundPen);
396 397 QCOMPARE(m_chart->plotAreaBackgroundPen(), plotAreaBackgroundPen);
397 398 }
398 399
399 400 void tst_QChart::isPlotAreaBackgroundVisible_data()
400 401 {
401 402 QTest::addColumn<bool>("isPlotAreaBackgroundVisible");
402 403 QTest::newRow("true") << true;
403 404 QTest::newRow("false") << false;
404 405 }
405 406
406 407 void tst_QChart::isPlotAreaBackgroundVisible()
407 408 {
408 409 QFETCH(bool, isPlotAreaBackgroundVisible);
409 410 m_chart->setPlotAreaBackgroundVisible(isPlotAreaBackgroundVisible);
410 411 QCOMPARE(m_chart->isPlotAreaBackgroundVisible(), isPlotAreaBackgroundVisible);
411 412 }
412 413 void tst_QChart::legend_data()
413 414 {
414 415
415 416 }
416 417
417 418 void tst_QChart::legend()
418 419 {
419 420 QLegend *legend = m_chart->legend();
420 421 QVERIFY(legend);
421 422
422 423 // Colors related signals
423 424 QSignalSpy colorSpy(legend, SIGNAL(colorChanged(QColor)));
424 425 QSignalSpy borderColorSpy(legend, SIGNAL(borderColorChanged(QColor)));
425 426 QSignalSpy labelColorSpy(legend, SIGNAL(labelColorChanged(QColor)));
426 427
427 428 // colorChanged
428 429 legend->setColor(QColor("aliceblue"));
429 430 QCOMPARE(colorSpy.count(), 1);
430 431 QBrush b = legend->brush();
431 432 b.setColor(QColor("aqua"));
432 433 legend->setBrush(b);
433 434 QCOMPARE(colorSpy.count(), 2);
434 435
435 436 // borderColorChanged
436 437 legend->setBorderColor(QColor("aliceblue"));
437 438 QCOMPARE(borderColorSpy.count(), 1);
438 439 QPen p = legend->pen();
439 440 p.setColor(QColor("aqua"));
440 441 legend->setPen(p);
441 442 QCOMPARE(borderColorSpy.count(), 2);
442 443
443 444 // labelColorChanged
444 445 legend->setLabelColor(QColor("lightsalmon"));
445 446 QCOMPARE(labelColorSpy.count(), 1);
446 447 b = legend->labelBrush();
447 448 b.setColor(QColor("lightseagreen"));
448 449 legend->setLabelBrush(b);
449 450 QCOMPARE(labelColorSpy.count(), 2);
450 451
451 452 // fontChanged
452 453 QSignalSpy fontSpy(legend, SIGNAL(fontChanged(QFont)));
453 454 QFont f = legend->font();
454 455 f.setBold(!f.bold());
455 456 legend->setFont(f);
456 457 QCOMPARE(fontSpy.count(), 1);
457 458 }
458 459
459 460 void tst_QChart::plotArea_data()
460 461 {
461 462
462 463 }
463 464
464 465 void tst_QChart::plotArea()
465 466 {
466 467 createTestData();
467 468 QRectF rect = m_chart->geometry();
468 469 QVERIFY(m_chart->plotArea().isValid());
469 470 QVERIFY(m_chart->plotArea().height() < rect.height());
470 471 QVERIFY(m_chart->plotArea().width() < rect.width());
471 472 }
472 473
473 474 void tst_QChart::removeAllSeries_data()
474 475 {
475 476
476 477 }
477 478
478 479 void tst_QChart::removeAllSeries()
479 480 {
480 481 QLineSeries* series0 = new QLineSeries(this);
481 482 QLineSeries* series1 = new QLineSeries(this);
482 483 QLineSeries* series2 = new QLineSeries(this);
483 484 QSignalSpy deleteSpy1(series0, SIGNAL(destroyed()));
484 485 QSignalSpy deleteSpy2(series1, SIGNAL(destroyed()));
485 486 QSignalSpy deleteSpy3(series2, SIGNAL(destroyed()));
486 487
487 488 m_chart->addSeries(series0);
488 489 m_chart->addSeries(series1);
489 490 m_chart->addSeries(series2);
490 491 m_view->show();
491 492 QTest::qWaitForWindowShown(m_view);
492 493 m_chart->createDefaultAxes();
493 494 QCOMPARE(m_chart->axes().count(), 2);
494 495 QVERIFY(m_chart->axisY(series0)!=0);
495 496 QVERIFY(m_chart->axisY(series1)!=0);
496 497 QVERIFY(m_chart->axisY(series2)!=0);
497 498
498 499 m_chart->removeAllSeries();
499 500 QCOMPARE(m_chart->axes().count(), 2);
500 501 QVERIFY(m_chart->axisX() != 0);
501 502 QVERIFY(m_chart->axisY() != 0);
502 503 QCOMPARE(deleteSpy1.count(), 1);
503 504 QCOMPARE(deleteSpy2.count(), 1);
504 505 QCOMPARE(deleteSpy3.count(), 1);
505 506 }
506 507
507 508 void tst_QChart::removeSeries_data()
508 509 {
509 510 axisX_data();
510 511 }
511 512
512 513 void tst_QChart::removeSeries()
513 514 {
514 515 QFETCH(QAbstractAxis *, axis);
515 516 QFETCH(QAbstractSeries *, series);
516 517 QSignalSpy deleteSpy(series, SIGNAL(destroyed()));
517 518 m_view->show();
518 519 QTest::qWaitForWindowShown(m_view);
519 520 if(!axis) axis = m_chart->axisY();
520 521 m_chart->addSeries(series);
521 522 m_chart->setAxisY(axis,series);
522 523 QCOMPARE(m_chart->axisY(series),axis);
523 524 m_chart->removeSeries(series);
524 525 QCOMPARE(m_chart->axes().count(), 1);
525 526 QVERIFY(m_chart->axisY() != 0);
526 527 QVERIFY(m_chart->axisY(series)==0);
527 528 QCOMPARE(deleteSpy.count(), 0);
528 529 }
529 530
530 531 void tst_QChart::scroll_right_data()
531 532 {
532 533 QTest::addColumn<QAbstractSeries *>("series");
533 534
534 535 QLineSeries* series0 = new QLineSeries(this);
535 536 *series0 << QPointF(0, 0) << QPointF(100, 100);
536 537
537 538 QTest::newRow("lineSeries") << (QAbstractSeries*) series0;
538 539
539 540
540 541 }
541 542
542 543 void tst_QChart::scroll_right()
543 544 {
544 545 QFETCH(QAbstractSeries *, series);
545 546 m_chart->addSeries(series);
546 547 m_chart->createDefaultAxes();
547 548 m_view->show();
548 549 QTest::qWaitForWindowShown(m_view);
549 550 QAbstractAxis * axis = m_chart->axisX();
550 551 QVERIFY(axis!=0);
551 552
552 553 switch(axis->type())
553 554 {
554 555 case QAbstractAxis::AxisTypeValue:{
555 556 QValueAxis* vaxis = qobject_cast<QValueAxis*>(axis);
556 557 QVERIFY(vaxis!=0);
557 558 qreal min = vaxis->min();
558 559 qreal max = vaxis->max();
559 560 QVERIFY(max>min);
560 561 m_chart->scroll(50, 0);
561 562 QVERIFY(min<vaxis->min());
562 563 QVERIFY(max<vaxis->max());
563 564 break;
564 565 }
565 566 case QAbstractAxis::AxisTypeBarCategory:{
566 567 QBarCategoryAxis* caxis = qobject_cast<QBarCategoryAxis*>(axis);
567 568 QVERIFY(caxis!=0);
568 569 qreal min = caxis->min().toDouble();
569 570 qreal max = caxis->max().toDouble();
570 571 m_chart->scroll(50, 0);
571 572 QVERIFY(min<caxis->min().toDouble());
572 573 QVERIFY(max<caxis->max().toDouble());
573 574 break;
574 575 }
575 576 default:
576 577 qFatal("Unsupported type");
577 578 break;
578 579 }
579 580 }
580 581
581 582 void tst_QChart::scroll_left_data()
582 583 {
583 584 scroll_right_data();
584 585 }
585 586
586 587 void tst_QChart::scroll_left()
587 588 {
588 589 QFETCH(QAbstractSeries *, series);
589 590 m_chart->addSeries(series);
590 591 m_chart->createDefaultAxes();
591 592 m_view->show();
592 593 QTest::qWaitForWindowShown(m_view);
593 594 QAbstractAxis * axis = m_chart->axisX();
594 595 QVERIFY(axis!=0);
595 596
596 597 switch(axis->type())
597 598 {
598 599 case QAbstractAxis::AxisTypeValue:{
599 600 QValueAxis* vaxis = qobject_cast<QValueAxis*>(axis);
600 601 QVERIFY(vaxis!=0);
601 602 qreal min = vaxis->min();
602 603 qreal max = vaxis->max();
603 604 m_chart->scroll(-50, 0);
604 605 QVERIFY(min>vaxis->min());
605 606 QVERIFY(max>vaxis->max());
606 607 break;
607 608 }
608 609 case QAbstractAxis::AxisTypeBarCategory:{
609 610 QBarCategoryAxis* caxis = qobject_cast<QBarCategoryAxis*>(axis);
610 611 QVERIFY(caxis!=0);
611 612 qreal min = caxis->min().toDouble();
612 613 qreal max = caxis->max().toDouble();
613 614 m_chart->scroll(-50, 0);
614 615 QVERIFY(min>caxis->min().toDouble());
615 616 QVERIFY(max>caxis->max().toDouble());
616 617 break;
617 618 }
618 619 default:
619 620 qFatal("Unsupported type");
620 621 break;
621 622 }
622 623 }
623 624
624 625 void tst_QChart::scroll_up_data()
625 626 {
626 627 scroll_right_data();
627 628 }
628 629
629 630 void tst_QChart::scroll_up()
630 631 {
631 632 QFETCH(QAbstractSeries *, series);
632 633 m_chart->addSeries(series);
633 634 m_chart->createDefaultAxes();
634 635 m_view->show();
635 636 QTest::qWaitForWindowShown(m_view);
636 637 QAbstractAxis * axis = m_chart->axisY();
637 638 QVERIFY(axis!=0);
638 639
639 640 switch(axis->type())
640 641 {
641 642 case QAbstractAxis::AxisTypeValue:{
642 643 QValueAxis* vaxis = qobject_cast<QValueAxis*>(axis);
643 644 QVERIFY(vaxis!=0);
644 645 qreal min = vaxis->min();
645 646 qreal max = vaxis->max();
646 647 m_chart->scroll(0, 50);
647 648 QVERIFY(min<vaxis->min());
648 649 QVERIFY(max<vaxis->max());
649 650 break;
650 651 }
651 652 case QAbstractAxis::AxisTypeBarCategory:{
652 653 QBarCategoryAxis* caxis = qobject_cast<QBarCategoryAxis*>(axis);
653 654 QVERIFY(caxis!=0);
654 655 qreal min = caxis->min().toDouble();
655 656 qreal max = caxis->max().toDouble();
656 657 m_chart->scroll(0, 50);
657 658 QVERIFY(min<caxis->min().toDouble());
658 659 QVERIFY(max<caxis->max().toDouble());
659 660 break;
660 661 }
661 662 default:
662 663 qFatal("Unsupported type");
663 664 break;
664 665 }
665 666 }
666 667
667 668 void tst_QChart::scroll_down_data()
668 669 {
669 670 scroll_right_data();
670 671 }
671 672
672 673 void tst_QChart::scroll_down()
673 674 {
674 675 QFETCH(QAbstractSeries *, series);
675 676 m_chart->addSeries(series);
676 677 m_chart->createDefaultAxes();
677 678 m_view->show();
678 679 QTest::qWaitForWindowShown(m_view);
679 680 QAbstractAxis * axis = m_chart->axisY();
680 681 QVERIFY(axis!=0);
681 682
682 683 switch(axis->type())
683 684 {
684 685 case QAbstractAxis::AxisTypeValue:{
685 686 QValueAxis* vaxis = qobject_cast<QValueAxis*>(axis);
686 687 QVERIFY(vaxis!=0);
687 688 qreal min = vaxis->min();
688 689 qreal max = vaxis->max();
689 690 m_chart->scroll(0, -50);
690 691 QVERIFY(min>vaxis->min());
691 692 QVERIFY(max>vaxis->max());
692 693 break;
693 694 }
694 695 case QAbstractAxis::AxisTypeBarCategory:{
695 696 QBarCategoryAxis* caxis = qobject_cast<QBarCategoryAxis*>(axis);
696 697 QVERIFY(caxis!=0);
697 698 qreal min = caxis->min().toDouble();
698 699 qreal max = caxis->max().toDouble();
699 700 m_chart->scroll(0, -50);
700 701 QVERIFY(min>caxis->min().toDouble());
701 702 QVERIFY(max>caxis->max().toDouble());
702 703 break;
703 704 }
704 705 default:
705 706 qFatal("Unsupported type");
706 707 break;
707 708 }
708 709 }
709 710
710 711 void tst_QChart::theme_data()
711 712 {
712 713 QTest::addColumn<QChart::ChartTheme>("theme");
713 714 QTest::newRow("ChartThemeBlueCerulean") << QChart::ChartThemeBlueCerulean;
714 715 QTest::newRow("ChartThemeBlueIcy") << QChart::ChartThemeBlueIcy;
715 716 QTest::newRow("ChartThemeBlueNcs") << QChart::ChartThemeBlueNcs;
716 717 QTest::newRow("ChartThemeBrownSand") << QChart::ChartThemeBrownSand;
717 718 QTest::newRow("ChartThemeDark") << QChart::ChartThemeDark;
718 719 QTest::newRow("hartThemeHighContrast") << QChart::ChartThemeHighContrast;
719 720 QTest::newRow("ChartThemeLight") << QChart::ChartThemeLight;
720 721 }
721 722
722 723 void tst_QChart::theme()
723 724 {
724 725 QFETCH(QChart::ChartTheme, theme);
725 726 createTestData();
726 727 m_chart->setTheme(theme);
727 728 QVERIFY(m_chart->theme()==theme);
728 729 }
729 730
730 731 void tst_QChart::title_data()
731 732 {
732 733 QTest::addColumn<QString>("title");
733 734 QTest::newRow("null") << QString();
734 735 QTest::newRow("foo") << QString("foo");
735 736 }
736 737
737 738 void tst_QChart::title()
738 739 {
739 740 QFETCH(QString, title);
740 741 m_chart->setTitle(title);
741 742 QCOMPARE(m_chart->title(), title);
742 743 }
743 744
744 745 void tst_QChart::titleBrush_data()
745 746 {
746 747 QTest::addColumn<QBrush>("titleBrush");
747 748 QTest::newRow("null") << QBrush();
748 749 QTest::newRow("blue") << QBrush(Qt::blue);
749 750 QTest::newRow("white") << QBrush(Qt::white);
750 751 QTest::newRow("black") << QBrush(Qt::black);
751 752 }
752 753
753 754 void tst_QChart::titleBrush()
754 755 {
755 756 QFETCH(QBrush, titleBrush);
756 757 m_chart->setTitleBrush(titleBrush);
757 758 QCOMPARE(m_chart->titleBrush().color(), titleBrush.color());
758 759 }
759 760
760 761 void tst_QChart::titleFont_data()
761 762 {
762 763 QTest::addColumn<QFont>("titleFont");
763 764 QTest::newRow("null") << QFont();
764 765 QTest::newRow("courier") << QFont("Courier", 8, QFont::Bold, true);
765 766 }
766 767
767 768 void tst_QChart::titleFont()
768 769 {
769 770 QFETCH(QFont, titleFont);
770 771 m_chart->setTitleFont(titleFont);
771 772 QCOMPARE(m_chart->titleFont(), titleFont);
772 773 }
773 774
774 775 void tst_QChart::zoomIn_data()
775 776 {
776 777 QTest::addColumn<QRectF>("rect");
777 778 QTest::newRow("null") << QRectF();
778 779 QTest::newRow("100x100") << QRectF(10,10,100,100);
779 780 QTest::newRow("200x200") << QRectF(10,10,200,200);
780 781 }
781 782
782 783
783 784 void tst_QChart::zoomIn()
784 785 {
785 786
786 787 QFETCH(QRectF, rect);
787 788 createTestData();
788 789 m_chart->createDefaultAxes();
789 790 QRectF marigns = m_chart->plotArea();
790 791 rect.adjust(marigns.left(),marigns.top(),-marigns.right(),-marigns.bottom());
791 792 QValueAxis* axisX = qobject_cast<QValueAxis*>(m_chart->axisX());
792 793 QVERIFY(axisX!=0);
793 794 QValueAxis* axisY = qobject_cast<QValueAxis*>(m_chart->axisY());
794 795 QVERIFY(axisY!=0);
795 796 qreal minX = axisX->min();
796 797 qreal minY = axisY->min();
797 798 qreal maxX = axisX->max();
798 799 qreal maxY = axisY->max();
799 800 m_chart->zoomIn(rect);
800 801 if(rect.isValid()){
801 802 QVERIFY(minX<axisX->min());
802 803 QVERIFY(maxX>axisX->max());
803 804 QVERIFY(minY<axisY->min());
804 805 QVERIFY(maxY>axisY->max());
805 806 }
806 807
807 808 }
808 809
809 810 void tst_QChart::zoomOut_data()
810 811 {
811 812
812 813 }
813 814
814 815 void tst_QChart::zoomOut()
815 816 {
816 817 createTestData();
817 818 m_chart->createDefaultAxes();
818 819
819 820 QValueAxis* axisX = qobject_cast<QValueAxis*>(m_chart->axisX());
820 821 QVERIFY(axisX!=0);
821 822 QValueAxis* axisY = qobject_cast<QValueAxis*>(m_chart->axisY());
822 823 QVERIFY(axisY!=0);
823 824
824 825 qreal minX = axisX->min();
825 826 qreal minY = axisY->min();
826 827 qreal maxX = axisX->max();
827 828 qreal maxY = axisY->max();
828 829
829 830 m_chart->zoomIn();
830 831
831 832 QVERIFY(minX < axisX->min());
832 833 QVERIFY(maxX > axisX->max());
833 834 QVERIFY(minY < axisY->min());
834 835 QVERIFY(maxY > axisY->max());
835 836
836 837 m_chart->zoomOut();
837 838
838 839 // min x may be a zero value
839 840 if (qFuzzyIsNull(minX))
840 841 QVERIFY(qFuzzyIsNull(axisX->min()));
841 842 else
842 843 QCOMPARE(minX, axisX->min());
843 844
844 845 // min y may be a zero value
845 846 if (qFuzzyIsNull(minY))
846 847 QVERIFY(qFuzzyIsNull(axisY->min()));
847 848 else
848 849 QCOMPARE(minY, axisY->min());
849 850
850 851 QVERIFY(maxX == axisX->max());
851 852 QVERIFY(maxY == axisY->max());
852 853
853 854 }
854 855
856 void tst_QChart::zoomReset()
857 {
858 createTestData();
859 m_chart->createDefaultAxes();
860 QValueAxis *axisX = qobject_cast<QValueAxis *>(m_chart->axisX());
861 QVERIFY(axisX != 0);
862 QValueAxis *axisY = qobject_cast<QValueAxis *>(m_chart->axisY());
863 QVERIFY(axisY != 0);
864
865 qreal minX = axisX->min();
866 qreal minY = axisY->min();
867 qreal maxX = axisX->max();
868 qreal maxY = axisY->max();
869
870 QVERIFY(!m_chart->isZoomed());
871
872 m_chart->zoomIn();
873
874 QVERIFY(m_chart->isZoomed());
875 QVERIFY(minX < axisX->min());
876 QVERIFY(maxX > axisX->max());
877 QVERIFY(minY < axisY->min());
878 QVERIFY(maxY > axisY->max());
879
880 m_chart->zoomReset();
881
882 // Reset after zoomIn should restore originals
883 QVERIFY(!m_chart->isZoomed());
884 QVERIFY(minX == axisX->min());
885 QVERIFY(maxX == axisX->max());
886 QVERIFY(minY == axisY->min());
887 QVERIFY(maxY == axisY->max());
888
889 m_chart->zoomOut();
890
891 QVERIFY(m_chart->isZoomed());
892 QVERIFY(minX > axisX->min());
893 QVERIFY(maxX < axisX->max());
894 QVERIFY(minY > axisY->min());
895 QVERIFY(maxY < axisY->max());
896
897 m_chart->zoomReset();
898
899 // Reset after zoomOut should restore originals
900 QVERIFY(!m_chart->isZoomed());
901 QVERIFY(minX == axisX->min());
902 QVERIFY(maxX == axisX->max());
903 QVERIFY(minY == axisY->min());
904 QVERIFY(maxY == axisY->max());
905
906 axisX->setRange(234, 345);
907 axisY->setRange(345, 456);
908
909 minX = axisX->min();
910 minY = axisY->min();
911 maxX = axisX->max();
912 maxY = axisY->max();
913
914 QVERIFY(!m_chart->isZoomed());
915
916 m_chart->zoomReset();
917
918 // Reset without zoom should not change anything
919 QVERIFY(!m_chart->isZoomed());
920 QVERIFY(minX == axisX->min());
921 QVERIFY(maxX == axisX->max());
922 QVERIFY(minY == axisY->min());
923 QVERIFY(maxY == axisY->max());
924
925 }
926
855 927 void tst_QChart::createDefaultAxesForLineSeries_data()
856 928 {
857 929 QTest::addColumn<qreal>("series1minX");
858 930 QTest::addColumn<qreal>("series1midX");
859 931 QTest::addColumn<qreal>("series1maxX");
860 932 QTest::addColumn<qreal>("series2minX");
861 933 QTest::addColumn<qreal>("series2midX");
862 934 QTest::addColumn<qreal>("series2maxX");
863 935 QTest::addColumn<qreal>("overallminX");
864 936 QTest::addColumn<qreal>("overallmaxX");
865 937 QTest::addColumn<qreal>("series1minY");
866 938 QTest::addColumn<qreal>("series1midY");
867 939 QTest::addColumn<qreal>("series1maxY");
868 940 QTest::addColumn<qreal>("series2minY");
869 941 QTest::addColumn<qreal>("series2midY");
870 942 QTest::addColumn<qreal>("series2maxY");
871 943 QTest::addColumn<qreal>("overallminY");
872 944 QTest::addColumn<qreal>("overallmaxY");
873 945 QTest::newRow("series1hasMinAndMax") << (qreal)1.0 << (qreal)2.0 << (qreal)3.0 << (qreal)1.1 << (qreal)1.7 << (qreal)2.9 << (qreal)1.0 << (qreal)3.0
874 946 << (qreal)1.0 << (qreal)2.0 << (qreal)3.0 << (qreal)1.1 << (qreal)1.7 << (qreal)2.9 << (qreal)1.0 << (qreal)3.0;
875 947 QTest::newRow("series2hasMinAndMax") << (qreal)1.1 << (qreal)2.0 << (qreal)2.9 << (qreal)1.0 << (qreal)1.7 << (qreal)3.0 << (qreal)1.0 << (qreal)3.0
876 948 << (qreal)1.1 << (qreal)2.0 << (qreal)2.9 << (qreal)1.0 << (qreal)1.7 << (qreal)3.0 << (qreal)1.0 << (qreal)3.0;
877 949 QTest::newRow("series1hasMinAndMaxX_series2hasMinAndMaxY") << (qreal)1.0 << (qreal)2.0 << (qreal)3.0 << (qreal)1.1 << (qreal)1.7 << (qreal)2.9 << (qreal)1.0 << (qreal)3.0
878 950 << (qreal)1.1 << (qreal)2.0 << (qreal)2.9 << (qreal)1.0 << (qreal)2.0 << (qreal)3.0 << (qreal)1.0 << (qreal)3.0;
879 951 QTest::newRow("series1hasMin_series2hasMax") << (qreal)1.0 << (qreal)2.0 << (qreal)2.9 << (qreal)1.1 << (qreal)1.7 << (qreal)3.0 << (qreal)1.0 << (qreal)3.0
880 952 << (qreal)1.0 << (qreal)2.0 << (qreal)2.9 << (qreal)1.1 << (qreal)1.7 << (qreal)3.0 << (qreal)1.0 << (qreal)3.0;
881 953 QTest::newRow("bothSeriesHaveSameMinAndMax") << (qreal)1.0 << (qreal)2.0 << (qreal)2.9 << (qreal)1.1 << (qreal)1.7 << (qreal)3.0 << (qreal)1.0 << (qreal)3.0
882 954 << (qreal)1.1 << (qreal)1.1 << (qreal)1.1 << (qreal)1.1 << (qreal)1.1 << (qreal)1.1 << (qreal)0.6 << (qreal)1.6;
883 955 }
884 956
885 957 void tst_QChart::createDefaultAxesForLineSeries()
886 958 {
887 959 QFETCH(qreal, series1minX);
888 960 QFETCH(qreal, series1midX);
889 961 QFETCH(qreal, series1maxX);
890 962 QFETCH(qreal, series2minX);
891 963 QFETCH(qreal, series2midX);
892 964 QFETCH(qreal, series2maxX);
893 965 QFETCH(qreal, series1minY);
894 966 QFETCH(qreal, series1midY);
895 967 QFETCH(qreal, series1maxY);
896 968 QFETCH(qreal, series2minY);
897 969 QFETCH(qreal, series2midY);
898 970 QFETCH(qreal, series2maxY);
899 971 QFETCH(qreal, overallminX);
900 972 QFETCH(qreal, overallmaxX);
901 973 QFETCH(qreal, overallminY);
902 974 QFETCH(qreal, overallmaxY);
903 975 QLineSeries* series1 = new QLineSeries(this);
904 976 series1->append(series1minX, series1minY);
905 977 series1->append(series1midX, series1midY);
906 978 series1->append(series1maxX, series1maxY);
907 979 QLineSeries* series2 = new QLineSeries(this);
908 980 series2->append(series2minX, series2minY);
909 981 series2->append(series2midX, series2midY);
910 982 series2->append(series2maxX, series2maxY);
911 983 QChart *chart = newQChartOrQPolarChart();
912 984 chart->addSeries(series1);
913 985 chart->addSeries(series2);
914 986 chart->createDefaultAxes();
915 987 QValueAxis *xAxis = (QValueAxis *)chart->axisX();
916 988 QCOMPARE(xAxis->min(), overallminX);
917 989 QCOMPARE(xAxis->max(), overallmaxX);
918 990 QValueAxis *yAxis = (QValueAxis *)chart->axisY();
919 991 QCOMPARE(yAxis->min(), overallminY);
920 992 QCOMPARE(yAxis->max(), overallmaxY);
921 993 QLineSeries *series3 = new QLineSeries(this);
922 994 // Numbers clearly out of existing range
923 995 series3->append(0, 0);
924 996 series3->append(100, 100);
925 997 // Adding a new series should not change the axes as they have not been told to update
926 998 chart->addSeries(series3);
927 999 QCOMPARE(xAxis->min(), overallminX);
928 1000 QCOMPARE(xAxis->max(), overallmaxX);
929 1001 QCOMPARE(yAxis->min(), overallminY);
930 1002 QCOMPARE(yAxis->max(), overallmaxY);
931 1003 }
932 1004
933 1005 void tst_QChart::axisPolarOrientation()
934 1006 {
935 1007 QLineSeries* series1 = new QLineSeries(this);
936 1008 series1->append(1, 2);
937 1009 series1->append(2, 4);
938 1010 series1->append(3, 8);
939 1011 QPolarChart chart;
940 1012 chart.addSeries(series1);
941 1013
942 1014 QValueAxis *xAxis = new QValueAxis();
943 1015 QValueAxis *yAxis = new QValueAxis();
944 1016 chart.addAxis(xAxis, QPolarChart::PolarOrientationAngular);
945 1017 chart.addAxis(yAxis, QPolarChart::PolarOrientationRadial);
946 1018
947 1019 QList<QAbstractAxis *> xAxes = chart.axes(QPolarChart::PolarOrientationAngular);
948 1020 QList<QAbstractAxis *> yAxes = chart.axes(QPolarChart::PolarOrientationRadial);
949 1021
950 1022 QCOMPARE(xAxes.size(), 1);
951 1023 QCOMPARE(yAxes.size(), 1);
952 1024 QCOMPARE(xAxes[0], xAxis);
953 1025 QCOMPARE(yAxes[0], yAxis);
954 1026
955 1027 QCOMPARE(chart.axisPolarOrientation(xAxes[0]), QPolarChart::PolarOrientationAngular);
956 1028 QCOMPARE(chart.axisPolarOrientation(yAxes[0]), QPolarChart::PolarOrientationRadial);
957 1029 }
958 1030
959 1031 QTEST_MAIN(tst_QChart)
960 1032 #include "tst_qchart.moc"
961 1033
General Comments 0
You need to be logged in to leave comments. Login now