##// END OF EJS Templates
Negative values with log axis handled
Marek Rosa -
r2356:c0053ad31507
parent child
Show More
@@ -1,90 +1,97
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "horizontalbarchartitem_p.h"
22 22 #include "qabstractbarseries_p.h"
23 23 #include "qbarset_p.h"
24 24 #include "bar_p.h"
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 HorizontalBarChartItem::HorizontalBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item)
29 29 : AbstractBarChartItem(series, item)
30 30 {
31 31 }
32 32
33 33 void HorizontalBarChartItem::initializeLayout()
34 34 {
35 35 qreal categoryCount = m_series->d_func()->categoryCount();
36 36 qreal setCount = m_series->count();
37 37 qreal barWidth = m_series->d_func()->barWidth();
38 38
39 39 m_layout.clear();
40 40 for(int category = 0; category < categoryCount; category++) {
41 41 for (int set = 0; set < setCount; set++) {
42 42 QRectF rect;
43 43 QPointF topLeft;
44 44 QPointF bottomRight;
45 45 if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) {
46 topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2 + set/setCount * barWidth));
47 bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2 + (set + 1)/setCount * barWidth));
46 topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2 + set/setCount * barWidth), m_validData);
47 bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2 + (set + 1)/setCount * barWidth), m_validData);
48 48 } else {
49 topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + set/setCount * barWidth));
50 bottomRight = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + (set + 1)/setCount * barWidth));
49 topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + set/setCount * barWidth), m_validData);
50 bottomRight = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + (set + 1)/setCount * barWidth), m_validData);
51 51 }
52 52
53 if (!m_validData)
54 return;
55
53 56 rect.setTopLeft(topLeft);
54 57 rect.setBottomRight(bottomRight);
55 58 m_layout.append(rect.normalized());
56 59 }
57 60 }
58 61 }
59 62
60 63 QVector<QRectF> HorizontalBarChartItem::calculateLayout()
61 64 {
62 65 QVector<QRectF> layout;
63 66
64 67 // Use temporary qreals for accuracy
65 68 qreal categoryCount = m_series->d_func()->categoryCount();
66 69 qreal setCount = m_series->count();
67 70 qreal barWidth = m_series->d_func()->barWidth();
68 71
69 72 for(int category = 0; category < categoryCount; category++) {
70 73 for (int set = 0; set < setCount; set++) {
71 74 qreal value = m_series->barSets().at(set)->at(category);
72 75 QRectF rect;
73 76 QPointF topLeft;
74 77 if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
75 topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2 + set/setCount * barWidth));
78 topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2 + set/setCount * barWidth), m_validData);
76 79 else
77 topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + set/setCount * barWidth));
80 topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2 + set/setCount * barWidth), m_validData);
81
82 QPointF bottomRight = domain()->calculateGeometryPoint(QPointF(value, category - barWidth / 2 + (set + 1)/setCount * barWidth), m_validData);
83
84 if (!m_validData)
85 return QVector<QRectF>();
78 86
79 QPointF bottomRight = domain()->calculateGeometryPoint(QPointF(value, category - barWidth / 2 + (set + 1)/setCount * barWidth));
80 87 rect.setTopLeft(topLeft);
81 88 rect.setBottomRight(bottomRight);
82 89 layout.append(rect.normalized());
83 90 }
84 91 }
85 92 return layout;
86 93 }
87 94
88 95 #include "moc_horizontalbarchartitem_p.cpp"
89 96
90 97 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,122 +1,128
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "horizontalpercentbarchartitem_p.h"
22 22 #include "qabstractbarseries_p.h"
23 23 #include "qbarset_p.h"
24 24 #include "bar_p.h"
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 HorizontalPercentBarChartItem::HorizontalPercentBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item)
29 29 : AbstractBarChartItem(series, item)
30 30 {
31 31 }
32 32
33 33 void HorizontalPercentBarChartItem::initializeLayout()
34 34 {
35 35 qreal categoryCount = m_series->d_func()->categoryCount();
36 36 qreal setCount = m_series->count();
37 37 qreal barWidth = m_series->d_func()->barWidth();
38 38
39 39 m_layout.clear();
40 40 for(int category = 0; category < categoryCount; category++) {
41 41 for (int set = 0; set < setCount; set++) {
42 42 QRectF rect;
43 43 QPointF topLeft;
44 44 QPointF bottomRight;
45 45 if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) {
46 topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2));
47 bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2));
46 topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2), m_validData);
47 bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2), m_validData);
48 48 } else {
49 topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2));
50 bottomRight = domain()->calculateGeometryPoint(QPointF(0, category + barWidth / 2));
49 topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2), m_validData);
50 bottomRight = domain()->calculateGeometryPoint(QPointF(0, category + barWidth / 2), m_validData);
51 51 }
52 52
53 if (!m_validData)
54 return;
55
53 56 rect.setTopLeft(topLeft);
54 57 rect.setBottomRight(bottomRight);
55 58 m_layout.append(rect.normalized());
56 59 }
57 60 }
58 61 }
59 62
60 63 QVector<QRectF> HorizontalPercentBarChartItem::calculateLayout()
61 64 {
62 65 QVector<QRectF> layout;
63 66
64 67 // Use temporary qreals for accuracy
65 68 qreal categoryCount = m_series->d_func()->categoryCount();
66 69 qreal setCount = m_series->count();
67 70 qreal barWidth = m_series->d_func()->barWidth();
68 71
69 72 for(int category = 0; category < categoryCount; category++) {
70 73 qreal sum = 0;
71 74 qreal categorySum = m_series->d_func()->categorySum(category);
72 75 for (int set = 0; set < setCount; set++) {
73 76 qreal value = m_series->barSets().at(set)->at(category);
74 77 QRectF rect;
75 78 QPointF topLeft;
76 79 if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
77 topLeft = domain()->calculateGeometryPoint(QPointF(set ? 100 * sum/categorySum : domain()->minX(), category - barWidth/2));
80 topLeft = domain()->calculateGeometryPoint(QPointF(set ? 100 * sum/categorySum : domain()->minX(), category - barWidth/2), m_validData);
78 81 else
79 topLeft = domain()->calculateGeometryPoint(QPointF(set ? 100 * sum/categorySum : 0, category - barWidth/2));
80 QPointF bottomRight = domain()->calculateGeometryPoint(QPointF(100 * (value + sum)/categorySum, category + barWidth/2));
82 topLeft = domain()->calculateGeometryPoint(QPointF(set ? 100 * sum/categorySum : 0, category - barWidth/2), m_validData);
83 QPointF bottomRight = domain()->calculateGeometryPoint(QPointF(100 * (value + sum)/categorySum, category + barWidth/2), m_validData);
84
85 if (!m_validData)
86 return QVector<QRectF>();
81 87 rect.setTopLeft(topLeft);
82 88 rect.setBottomRight(bottomRight);
83 89 layout.append(rect.normalized());
84 90 sum +=value;
85 91 }
86 92 }
87 93 return layout;
88 94 }
89 95
90 96 void HorizontalPercentBarChartItem::handleUpdatedBars()
91 97 {
92 98 // Handle changes in pen, brush, labels etc.
93 99 int categoryCount = m_series->d_func()->categoryCount();
94 100 int setCount = m_series->count();
95 101 int itemIndex(0);
96 102
97 103 for (int category = 0; category < categoryCount; category++) {
98 104 for (int set = 0; set < setCount; set++) {
99 105 QBarSetPrivate *barSet = m_series->d_func()->barsetAt(set)->d_ptr.data();
100 106 Bar *bar = m_bars.at(itemIndex);
101 107 bar->setPen(barSet->m_pen);
102 108 bar->setBrush(barSet->m_brush);
103 109 bar->update();
104 110
105 111 QGraphicsSimpleTextItem *label = m_labels.at(itemIndex);
106 112 int p = m_series->d_func()->percentageAt(set, category) * 100;
107 113 QString vString(QString::number(p));
108 114 vString.truncate(3);
109 115 vString.append("%");
110 116 label->setText(vString);
111 117 label->setFont(barSet->m_labelFont);
112 118 label->setBrush(barSet->m_labelBrush);
113 119 label->update();
114 120 itemIndex++;
115 121 }
116 122 }
117 123 }
118 124
119 125 #include "moc_horizontalpercentbarchartitem_p.cpp"
120 126
121 127 QTCOMMERCIALCHART_END_NAMESPACE
122 128
@@ -1,103 +1,108
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "horizontalstackedbarchartitem_p.h"
22 22 #include "qabstractbarseries_p.h"
23 23 #include "qbarset_p.h"
24 24 #include "bar_p.h"
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 HorizontalStackedBarChartItem::HorizontalStackedBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item)
29 29 : AbstractBarChartItem(series, item)
30 30 {
31 31 }
32 32
33 33 void HorizontalStackedBarChartItem::initializeLayout()
34 34 {
35 35 qreal categoryCount = m_series->d_func()->categoryCount();
36 36 qreal setCount = m_series->count();
37 37 qreal barWidth = m_series->d_func()->barWidth();
38 38
39 39 m_layout.clear();
40 40 for(int category = 0; category < categoryCount; category++) {
41 41 for (int set = 0; set < setCount; set++) {
42 42 QRectF rect;
43 43 QPointF topLeft;
44 44 QPointF bottomRight;
45 45 if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) {
46 topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2));
47 bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2));
46 topLeft = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category - barWidth / 2), m_validData);
47 bottomRight = domain()->calculateGeometryPoint(QPointF(domain()->minX(), category + barWidth / 2), m_validData);
48 48 } else {
49 topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2));
50 bottomRight = domain()->calculateGeometryPoint(QPointF(0, category + barWidth / 2));
49 topLeft = domain()->calculateGeometryPoint(QPointF(0, category - barWidth / 2), m_validData);
50 bottomRight = domain()->calculateGeometryPoint(QPointF(0, category + barWidth / 2), m_validData);
51 51 }
52 52
53 if (!m_validData)
54 return;
55
53 56 rect.setTopLeft(topLeft);
54 57 rect.setBottomRight(bottomRight);
55 58 m_layout.append(rect.normalized());
56 59 }
57 60 }
58 61 }
59 62
60 63 QVector<QRectF> HorizontalStackedBarChartItem::calculateLayout()
61 64 {
62 65 QVector<QRectF> layout;
63 66
64 67 // Use temporary qreals for accuracy
65 68 qreal categoryCount = m_series->d_func()->categoryCount();
66 69 qreal setCount = m_series->count();
67 70 qreal barWidth = m_series->d_func()->barWidth();
68 71
69 72 for(int category = 0; category < categoryCount; category++) {
70 73 qreal positiveSum = 0;
71 74 qreal negativeSum = 0;
72 75 for (int set = 0; set < setCount; set++) {
73 76 qreal value = m_series->barSets().at(set)->at(category);
74 77 QRectF rect;
75 78 QPointF topLeft;
76 79 QPointF bottomRight;
77 80 if (value < 0) {
78 bottomRight = domain()->calculateGeometryPoint(QPointF(value + negativeSum, category - barWidth / 2));
81 bottomRight = domain()->calculateGeometryPoint(QPointF(value + negativeSum, category - barWidth / 2), m_validData);
79 82 if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
80 topLeft = domain()->calculateGeometryPoint(QPointF(set ? negativeSum : domain()->minX(), category + barWidth / 2));
83 topLeft = domain()->calculateGeometryPoint(QPointF(set ? negativeSum : domain()->minX(), category + barWidth / 2), m_validData);
81 84 else
82 topLeft = domain()->calculateGeometryPoint(QPointF(set ? negativeSum : 0, category + barWidth / 2));
85 topLeft = domain()->calculateGeometryPoint(QPointF(set ? negativeSum : 0, category + barWidth / 2), m_validData);
83 86 negativeSum += value;
84 87 } else {
85 bottomRight = domain()->calculateGeometryPoint(QPointF(value + positiveSum, category - barWidth / 2));
88 bottomRight = domain()->calculateGeometryPoint(QPointF(value + positiveSum, category - barWidth / 2), m_validData);
86 89 if (domain()->type() == AbstractDomain::LogXYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
87 topLeft = domain()->calculateGeometryPoint(QPointF(set ? positiveSum : domain()->minX(), category + barWidth / 2));
90 topLeft = domain()->calculateGeometryPoint(QPointF(set ? positiveSum : domain()->minX(), category + barWidth / 2), m_validData);
88 91 else
89 topLeft = domain()->calculateGeometryPoint(QPointF(set ? positiveSum : 0, category + barWidth / 2));
92 topLeft = domain()->calculateGeometryPoint(QPointF(set ? positiveSum : 0, category + barWidth / 2), m_validData);
90 93 positiveSum += value;
91 94 }
95 if (!m_validData)
96 return QVector<QRectF>();
92 97 rect.setTopLeft(topLeft);
93 98 rect.setBottomRight(bottomRight);
94 99 layout.append(rect.normalized());
95 100 }
96 101 }
97 102 return layout;
98 103 }
99 104
100 105 #include "moc_horizontalstackedbarchartitem_p.cpp"
101 106
102 107 QTCOMMERCIALCHART_END_NAMESPACE
103 108
@@ -1,91 +1,97
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "barchartitem_p.h"
22 22 #include "bar_p.h"
23 23 #include "qabstractbarseries_p.h"
24 24 #include "qbarset.h"
25 25 #include "qbarset_p.h"
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 BarChartItem::BarChartItem(QAbstractBarSeries *series, QGraphicsItem* item) :
30 30 AbstractBarChartItem(series, item)
31 31 {
32 32 }
33 33
34 34 void BarChartItem::initializeLayout()
35 35 {
36 36 qreal categoryCount = m_series->d_func()->categoryCount();
37 37 qreal setCount = m_series->count();
38 38 qreal barWidth = m_series->d_func()->barWidth();
39 39
40 40 m_layout.clear();
41 41 for(int category = 0; category < categoryCount; category++) {
42 42 for (int set = 0; set < setCount; set++) {
43 43 QRectF rect;
44 44 QPointF topLeft;
45 45 QPointF bottomRight;
46 46
47 47 if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) {
48 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + set/setCount * barWidth, domain()->minY()));
49 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2 + (set + 1)/setCount * barWidth, domain()->minY()));
48 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + set/setCount * barWidth, domain()->minY()), m_validData);
49 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2 + (set + 1)/setCount * barWidth, domain()->minY()), m_validData);
50 50 } else {
51 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + set/setCount * barWidth, 0));
52 bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/setCount * barWidth, 0));
51 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + set/setCount * barWidth, 0), m_validData);
52 bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/setCount * barWidth, 0), m_validData);
53 53 }
54 54
55 if (!m_validData)
56 return;
55 57 rect.setTopLeft(topLeft);
56 58 rect.setBottomRight(bottomRight);
57 59 m_layout.append(rect.normalized());
58 60 }
59 61 }
60 62 }
61 63
62 64 QVector<QRectF> BarChartItem::calculateLayout()
63 65 {
64 66 QVector<QRectF> layout;
65 67
66 68 // Use temporary qreals for accuracy
67 69 qreal categoryCount = m_series->d_func()->categoryCount();
68 70 qreal setCount = m_series->count();
69 71 qreal barWidth = m_series->d_func()->barWidth();
70 72
71 73 for(int category = 0; category < categoryCount; category++) {
72 74 for (int set = 0; set < setCount; set++) {
73 75 qreal value = m_series->barSets().at(set)->at(category);
74 76 QRectF rect;
75 QPointF topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set)/(setCount) * barWidth, value));
77 QPointF topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set)/(setCount) * barWidth, value), m_validData);
76 78 QPointF bottomRight;
77 79 if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
78 bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/(setCount) * barWidth, domain()->minY()));
80 bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/(setCount) * barWidth, domain()->minY()), m_validData);
79 81 else
80 bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/(setCount) * barWidth, 0));
82 bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2 + (set + 1)/(setCount) * barWidth, 0), m_validData);
83
84 if (!m_validData)
85 return QVector<QRectF>();
86
81 87 rect.setTopLeft(topLeft);
82 88 rect.setBottomRight(bottomRight);
83 89 layout.append(rect.normalized());
84 90 }
85 91 }
86 92 return layout;
87 93 }
88 94
89 95 #include "moc_barchartitem_p.cpp"
90 96
91 97 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,123 +1,129
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "percentbarchartitem_p.h"
22 22 #include "bar_p.h"
23 23 #include "qabstractbarseries_p.h"
24 24 #include "qbarset.h"
25 25 #include "qbarset_p.h"
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 PercentBarChartItem::PercentBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item) :
30 30 AbstractBarChartItem(series, item)
31 31 {
32 32 }
33 33
34 34 void PercentBarChartItem::initializeLayout()
35 35 {
36 36 qreal categoryCount = m_series->d_func()->categoryCount();
37 37 qreal setCount = m_series->count();
38 38 qreal barWidth = m_series->d_func()->barWidth();
39 39
40 40 m_layout.clear();
41 41 for(int category = 0; category < categoryCount; category++) {
42 42 for (int set = 0; set < setCount; set++) {
43 43 QRectF rect;
44 44 QPointF topLeft;
45 45 QPointF bottomRight;
46 46
47 47 if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) {
48 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, domain()->minY()));
49 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, domain()->minY()));
48 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, domain()->minY()), m_validData);
49 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, domain()->minY()), m_validData);
50 50 } else {
51 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, 0));
52 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, 0));
51 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, 0), m_validData);
52 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, 0), m_validData);
53 53 }
54 54
55 if (!m_validData)
56 return;
57
55 58 rect.setTopLeft(topLeft);
56 59 rect.setBottomRight(bottomRight);
57 60 m_layout.append(rect.normalized());
58 61 }
59 62 }
60 63 }
61 64
62 65 QVector<QRectF> PercentBarChartItem::calculateLayout()
63 66 {
64 67 QVector<QRectF> layout;
65 68
66 69 // Use temporary qreals for accuracy
67 70 qreal categoryCount = m_series->d_func()->categoryCount();
68 71 qreal setCount = m_series->count();
69 72 qreal barWidth = m_series->d_func()->barWidth();
70 73
71 74 for(int category = 0; category < categoryCount; category++) {
72 75 qreal sum = 0;
73 76 qreal categorySum = m_series->d_func()->categorySum(category);
74 77 for (int set = 0; set < setCount; set++) {
75 78 qreal value = m_series->barSets().at(set)->at(category);
76 79 QRectF rect;
77 QPointF topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth/2, 100 * (value + sum)/categorySum));
80 QPointF topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth/2, 100 * (value + sum)/categorySum), m_validData);
78 81 QPointF bottomRight;
79 82 if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
80 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth/2, set ? 100 * sum/categorySum : domain()->minY()));
83 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth/2, set ? 100 * sum/categorySum : domain()->minY()), m_validData);
81 84 else
82 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth/2, set ? 100 * sum/categorySum : 0));
85 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth/2, set ? 100 * sum/categorySum : 0), m_validData);
86
87 if (!m_validData)
88 return QVector<QRectF>();
83 89 rect.setTopLeft(topLeft);
84 90 rect.setBottomRight(bottomRight);
85 91 layout.append(rect.normalized());
86 92 sum +=value;
87 93 }
88 94 }
89 95 return layout;
90 96 }
91 97
92 98 void PercentBarChartItem::handleUpdatedBars()
93 99 {
94 100 // Handle changes in pen, brush, labels etc.
95 101 int categoryCount = m_series->d_func()->categoryCount();
96 102 int setCount = m_series->count();
97 103 int itemIndex(0);
98 104
99 105 for (int category = 0; category < categoryCount; category++) {
100 106 for (int set = 0; set < setCount; set++) {
101 107 QBarSetPrivate *barSet = m_series->d_func()->barsetAt(set)->d_ptr.data();
102 108 Bar *bar = m_bars.at(itemIndex);
103 109 bar->setPen(barSet->m_pen);
104 110 bar->setBrush(barSet->m_brush);
105 111 bar->update();
106 112
107 113 QGraphicsSimpleTextItem *label = m_labels.at(itemIndex);
108 114 int p = m_series->d_func()->percentageAt(set, category) * 100;
109 115 QString vString(QString::number(p));
110 116 vString.truncate(3);
111 117 vString.append("%");
112 118 label->setText(vString);
113 119 label->setFont(barSet->m_labelFont);
114 120 label->setBrush(barSet->m_labelBrush);
115 121 label->update();
116 122 itemIndex++;
117 123 }
118 124 }
119 125 }
120 126
121 127 #include "moc_percentbarchartitem_p.cpp"
122 128
123 129 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,103 +1,108
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "stackedbarchartitem_p.h"
22 22 #include "bar_p.h"
23 23 #include "qbarset_p.h"
24 24 #include "qabstractbarseries_p.h"
25 25 #include "qbarset.h"
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 StackedBarChartItem::StackedBarChartItem(QAbstractBarSeries *series, QGraphicsItem* item) :
30 30 AbstractBarChartItem(series, item)
31 31 {
32 32 }
33 33
34 34 void StackedBarChartItem::initializeLayout()
35 35 {
36 36 qreal categoryCount = m_series->d_func()->categoryCount();
37 37 qreal setCount = m_series->count();
38 38 qreal barWidth = m_series->d_func()->barWidth();
39 39
40 40 m_layout.clear();
41 41 for(int category = 0; category < categoryCount; category++) {
42 42 for (int set = 0; set < setCount; set++) {
43 43 QRectF rect;
44 44 QPointF topLeft;
45 45 QPointF bottomRight;
46 46
47 47 if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain) {
48 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, domain()->minY()));
49 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, domain()->minY()));
48 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, domain()->minY()), m_validData);
49 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, domain()->minY()), m_validData);
50 50 } else {
51 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, 0));
52 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, 0));
51 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, 0), m_validData);
52 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, 0), m_validData);
53 53 }
54 54
55 if (!m_validData)
56 return;
57
55 58 rect.setTopLeft(topLeft);
56 59 rect.setBottomRight(bottomRight);
57 60 m_layout.append(rect.normalized());
58 61 }
59 62 }
60 63 }
61 64
62 65 QVector<QRectF> StackedBarChartItem::calculateLayout()
63 66 {
64 67 QVector<QRectF> layout;
65 68 // Use temporary qreals for accuracy
66 69 qreal categoryCount = m_series->d_func()->categoryCount();
67 70 qreal setCount = m_series->count();
68 71 qreal barWidth = m_series->d_func()->barWidth();
69 72
70 73 for(int category = 0; category < categoryCount; category++) {
71 74 qreal positiveSum = 0;
72 75 qreal negativeSum = 0;
73 76 for (int set = 0; set < setCount; set++) {
74 77 qreal value = m_series->barSets().at(set)->at(category);
75 78 QRectF rect;
76 79 QPointF topLeft;
77 80 QPointF bottomRight;
78 81 if (value < 0) {
79 bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, value + negativeSum));
82 bottomRight = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, value + negativeSum), m_validData);
80 83 if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
81 topLeft = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? negativeSum : domain()->minY()));
84 topLeft = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? negativeSum : domain()->minY()), m_validData);
82 85 else
83 topLeft = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? negativeSum : 0));
86 topLeft = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? negativeSum : 0), m_validData);
84 87 negativeSum += value;
85 88 } else {
86 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, value + positiveSum));
89 topLeft = domain()->calculateGeometryPoint(QPointF(category - barWidth / 2, value + positiveSum), m_validData);
87 90 if (domain()->type() == AbstractDomain::XLogYDomain || domain()->type() == AbstractDomain::LogXLogYDomain)
88 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? positiveSum : domain()->minY()));
91 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? positiveSum : domain()->minY()), m_validData);
89 92 else
90 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? positiveSum : 0));
93 bottomRight = domain()->calculateGeometryPoint(QPointF(category + barWidth / 2, set ? positiveSum : 0), m_validData);
91 94 positiveSum += value;
92 95 }
96 if (!m_validData)
97 return QVector<QRectF>();
93 98 rect.setTopLeft(topLeft);
94 99 rect.setBottomRight(bottomRight);
95 100 layout.append(rect.normalized());
96 101 }
97 102 }
98 103 return layout;
99 104 }
100 105
101 106 #include "moc_stackedbarchartitem_p.cpp"
102 107
103 108 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,510 +1,511
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "xlogydomain_p.h"
37 37 #include "logxydomain_p.h"
38 38 #include "logxlogydomain_p.h"
39 39
40 40 #ifndef QT_ON_ARM
41 41 #include "qdatetimeaxis.h"
42 42 #endif
43 43
44 44 QTCOMMERCIALCHART_BEGIN_NAMESPACE
45 45
46 46 ChartDataSet::ChartDataSet(QChart *chart)
47 47 : QObject(chart),
48 48 m_chart(chart)
49 49 {
50 50
51 51 }
52 52
53 53 ChartDataSet::~ChartDataSet()
54 54 {
55 55 deleteAllSeries();
56 56 deleteAllAxes();
57 57 }
58 58
59 59 /*
60 60 * This method adds series to chartdataset, series ownership is taken from caller.
61 61 */
62 62 void ChartDataSet::addSeries(QAbstractSeries *series)
63 63 {
64 64 if (m_seriesList.contains(series)) {
65 65 qWarning() << QObject::tr("Can not add series. Series already on the chart.");
66 66 return;
67 67 }
68 68
69 69 series->d_ptr->initializeDomain();
70 70 m_seriesList.append(series);
71 71
72 72 series->setParent(this); // take ownership
73 73 series->d_ptr->m_chart = m_chart;
74 74
75 75 emit seriesAdded(series);
76 76 }
77 77
78 78 /*
79 79 * This method adds axis to chartdataset, axis ownership is taken from caller.
80 80 */
81 81 void ChartDataSet::addAxis(QAbstractAxis *axis,Qt::Alignment aligment)
82 82 {
83 83 if (m_axisList.contains(axis)) {
84 84 qWarning() << QObject::tr("Can not add axis. Axis already on the chart.");
85 85 return;
86 86 }
87 87
88 88 axis->d_ptr->setAlignment(aligment);
89 89
90 90 if(!axis->alignment()) {
91 91 qWarning()<< QObject::tr("No alignment specified !");
92 92 return;
93 93 };
94 94
95 95 QSharedPointer<AbstractDomain> domain(new XYDomain());
96 96 axis->d_ptr->initializeDomain(domain.data());
97 97
98 98 axis->setParent(this);
99 99 axis->d_ptr->m_chart = m_chart;
100 100 m_axisList.append(axis);
101 101
102 102 emit axisAdded(axis);
103 103 }
104 104
105 105 /*
106 106 * This method removes series form chartdataset, series ownership is passed back to caller.
107 107 */
108 108 void ChartDataSet::removeSeries(QAbstractSeries *series)
109 109 {
110 110
111 111 if (! m_seriesList.contains(series)) {
112 112 qWarning() << QObject::tr("Can not remove series. Series not found on the chart.");
113 113 return;
114 114 }
115 115
116 116 QList<QAbstractAxis*> axes = series->d_ptr->m_axes;
117 117
118 118 foreach(QAbstractAxis* axis, axes) {
119 119 detachAxis(series,axis);
120 120 }
121 121
122 122 emit seriesRemoved(series);
123 123 m_seriesList.removeAll(series);
124 124
125 125 series->setParent(0);
126 126 series->d_ptr->m_chart = 0;
127 127 }
128 128
129 129 /*
130 130 * This method removes axis form chartdataset, series ownership is passed back to caller.
131 131 */
132 132 void ChartDataSet::removeAxis(QAbstractAxis *axis)
133 133 {
134 134 if (! m_axisList.contains(axis)) {
135 135 qWarning() << QObject::tr("Can not remove axis. Axis not found on the chart.");
136 136 return;
137 137 }
138 138
139 139 QList<QAbstractSeries*> series = axis->d_ptr->m_series;
140 140
141 141 foreach(QAbstractSeries* s, series) {
142 142 detachAxis(s,axis);
143 143 }
144 144
145 145 emit axisRemoved(axis);
146 146 m_axisList.removeAll(axis);
147 147
148 148 axis->setParent(0);
149 149 axis->d_ptr->m_chart = 0;
150 150 }
151 151
152 152 /*
153 153 * This method attaches axis to series, return true if success.
154 154 */
155 155 bool ChartDataSet::attachAxis(QAbstractSeries* series,QAbstractAxis *axis)
156 156 {
157 157 Q_ASSERT(series);
158 158 Q_ASSERT(axis);
159 159
160 160 QList<QAbstractSeries* > attachedSeriesList = axis->d_ptr->m_series;
161 161 QList<QAbstractAxis* > attachedAxisList = series->d_ptr->m_axes;
162 162
163 163 if (!m_seriesList.contains(series)) {
164 164 qWarning() << QObject::tr("Can not find series on the chart.");
165 165 return false;
166 166 }
167 167
168 168 if (axis && !m_axisList.contains(axis)) {
169 169 qWarning() << QObject::tr("Can not find axis on the chart.");
170 170 return false;
171 171 }
172 172
173 173 if (attachedAxisList.contains(axis)) {
174 174 qWarning() << QObject::tr("Axis already attached to series.");
175 175 return false;
176 176 }
177 177
178 178 if (attachedSeriesList.contains(series)) {
179 179 qWarning() << QObject::tr("Axis already attached to series.");
180 180 return false;
181 181 }
182 182
183 183 AbstractDomain* domain = series->d_ptr->domain();
184 184 AbstractDomain::DomainType type = selectDomain(attachedAxisList<<axis);
185 185
186 186 if(type == AbstractDomain::UndefinedDomain) return false;
187 187
188 188 if(domain->type()!=type){
189 189 domain = createDomain(type);
190 190 }
191 191
192 192 if(!domain) return false;
193 193
194 194 if(!domain->attachAxis(axis)) return false;
195 195
196 196 if(domain!=series->d_ptr->domain()){
197 197 foreach(QAbstractAxis* axis,series->d_ptr->m_axes){
198 198 series->d_ptr->domain()->detachAxis(axis);
199 199 domain->attachAxis(axis);
200 200 }
201 201 series->d_ptr->setDomain(domain);
202 202 series->d_ptr->initializeDomain();
203 203 }
204 204
205 205 series->d_ptr->m_axes<<axis;
206 206 axis->d_ptr->m_series<<series;
207 207
208 208 series->d_ptr->initializeAxes();
209 209 axis->d_ptr->initializeDomain(domain);
210 210
211 211 return true;
212 212 }
213 213
214 214 /*
215 215 * This method detaches axis to series, return true if success.
216 216 */
217 217 bool ChartDataSet::detachAxis(QAbstractSeries* series,QAbstractAxis *axis)
218 218 {
219 219 Q_ASSERT(series);
220 220 Q_ASSERT(axis);
221 221
222 222 QList<QAbstractSeries* > attachedSeriesList = axis->d_ptr->m_series;
223 223 QList<QAbstractAxis* > attachedAxisList = series->d_ptr->m_axes;
224 224 AbstractDomain* domain = series->d_ptr->domain();
225 225
226 226 if (!m_seriesList.contains(series)) {
227 227 qWarning() << QObject::tr("Can not find series on the chart.");
228 228 return false;
229 229 }
230 230
231 231 if (axis && !m_axisList.contains(axis)) {
232 232 qWarning() << QObject::tr("Can not find axis on the chart.");
233 233 return false;
234 234 }
235 235
236 236 if (!attachedAxisList.contains(axis)) {
237 237 qWarning() << QObject::tr("Axis not attached to series.");
238 238 return false;
239 239 }
240 240
241 241 Q_ASSERT(axis->d_ptr->m_series.contains(series));
242 242
243 243 domain->detachAxis(axis);
244 244 series->d_ptr->m_axes.removeAll(axis);
245 245 axis->d_ptr->m_series.removeAll(series);
246 246
247 247 return true;
248 248 }
249 249
250 250 void ChartDataSet::createDefaultAxes()
251 251 {
252 252 if (m_seriesList.isEmpty())
253 253 return;
254 254
255 255 QAbstractAxis::AxisTypes typeX(0);
256 256 QAbstractAxis::AxisTypes typeY(0);
257 257
258 258 // Remove possibly existing axes
259 259 deleteAllAxes();
260 260
261 261 Q_ASSERT(m_axisList.isEmpty());
262 262
263 263 // Select the required axis x and axis y types based on the types of the current series
264 264 foreach(QAbstractSeries* s, m_seriesList) {
265 265 typeX |= s->d_ptr->defaultAxisType(Qt::Horizontal);
266 266 typeY |= s->d_ptr->defaultAxisType(Qt::Vertical);
267 267 }
268 268
269 269 // Create the axes of the types selected
270 270 createAxes(typeX, Qt::Horizontal);
271 271 createAxes(typeY, Qt::Vertical);
272 272
273 273 }
274 274
275 275 void ChartDataSet::createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation)
276 276 {
277 277 QAbstractAxis *axis = 0;
278 278 //decide what axis should be created
279 279
280 280 switch (type) {
281 281 case QAbstractAxis::AxisTypeValue:
282 282 axis = new QValueAxis(this);
283 283 break;
284 284 case QAbstractAxis::AxisTypeBarCategory:
285 285 axis = new QBarCategoryAxis(this);
286 286 break;
287 287 case QAbstractAxis::AxisTypeCategory:
288 288 axis = new QCategoryAxis(this);
289 289 break;
290 290 #ifndef Q_WS_QWS
291 291 case QAbstractAxis::AxisTypeDateTime:
292 292 axis = new QDateTimeAxis(this);
293 293 break;
294 294 #endif
295 295 default:
296 296 axis = 0;
297 297 break;
298 298 }
299 299
300 300 if (axis) {
301 301 //create one axis for all
302 302
303 303 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
304 304
305 305 foreach(QAbstractSeries *s, m_seriesList) {
306 306 attachAxis(s,axis);
307 307 }
308 308
309 309 }
310 310 else if (!type.testFlag(QAbstractAxis::AxisTypeNoAxis)) {
311 311 //create separate axis
312 312 foreach(QAbstractSeries *s, m_seriesList) {
313 313 QAbstractAxis *axis = s->d_ptr->createDefaultAxis(orientation);
314 314 if(axis) {
315 315 addAxis(axis,orientation==Qt::Horizontal?Qt::AlignBottom:Qt::AlignLeft);
316 316 attachAxis(s,axis);
317 317 }
318 318 }
319 319 }
320 320 }
321 321
322 322 void ChartDataSet::deleteAllSeries()
323 323 {
324 324 foreach (QAbstractSeries *s , m_seriesList){
325 325 removeSeries(s);
326 326 s->deleteLater();
327 327 }
328 328 Q_ASSERT(m_seriesList.count() == 0);
329 329 }
330 330
331 331 void ChartDataSet::deleteAllAxes()
332 332 {
333 333 foreach (QAbstractAxis *a , m_axisList){
334 334 removeAxis(a);
335 335 a->deleteLater();
336 336 }
337 337 Q_ASSERT(m_axisList.count() == 0);
338 338 }
339 339
340 340 void ChartDataSet::zoomInDomain(const QRectF &rect)
341 341 {
342 342 QList<AbstractDomain*> domains;
343 343 foreach(QAbstractSeries *s, m_seriesList) {
344 344 AbstractDomain* domain = s->d_ptr->domain();
345 345 s->d_ptr->m_domain->blockRangeSignals(true);
346 346 domains<<domain;
347 347 }
348 348
349 349 foreach(AbstractDomain *domain, domains)
350 350 domain->zoomIn(rect);
351 351
352 352 foreach(AbstractDomain *domain, domains)
353 353 domain->blockRangeSignals(false);
354 354 }
355 355
356 356 void ChartDataSet::zoomOutDomain(const QRectF &rect)
357 357 {
358 358 QList<AbstractDomain*> domains;
359 359 foreach(QAbstractSeries *s, m_seriesList) {
360 360 AbstractDomain* domain = s->d_ptr->domain();
361 361 s->d_ptr->m_domain->blockRangeSignals(true);
362 362 domains<<domain;
363 363 }
364 364
365 365 foreach(AbstractDomain *domain, domains)
366 366 domain->zoomOut(rect);
367 367
368 368 foreach(AbstractDomain *domain, domains)
369 369 domain->blockRangeSignals(false);
370 370 }
371 371
372 372 void ChartDataSet::scrollDomain(qreal dx, qreal dy)
373 373 {
374 374 QList<AbstractDomain*> domains;
375 375 foreach(QAbstractSeries *s, m_seriesList) {
376 376 AbstractDomain* domain = s->d_ptr->domain();
377 377 s->d_ptr->m_domain->blockRangeSignals(true);
378 378 domains<<domain;
379 379 }
380 380
381 381 foreach(AbstractDomain *domain, domains)
382 382 domain->move(dx, dy);
383 383
384 384 foreach(AbstractDomain *domain, domains)
385 385 domain->blockRangeSignals(false);
386 386 }
387 387
388 388 QPointF ChartDataSet::mapToValue(const QPointF &position, QAbstractSeries *series)
389 389 {
390 390 QPointF point;
391 391 if (series == 0 && !m_seriesList.isEmpty())
392 392 series = m_seriesList.first();
393 393
394 394 if (series && series->type() == QAbstractSeries::SeriesTypePie)
395 395 return point;
396 396
397 397 if (series && m_seriesList.contains(series))
398 398 point = series->d_ptr->m_domain->calculateDomainPoint(position - m_chart->plotArea().topLeft());
399 399 return point;
400 400 }
401 401
402 402 QPointF ChartDataSet::mapToPosition(const QPointF &value, QAbstractSeries *series)
403 403 {
404 404 QPointF point = m_chart->plotArea().topLeft();
405 405 if (series == 0 && !m_seriesList.isEmpty())
406 406 series = m_seriesList.first();
407 407
408 408 if (series && series->type() == QAbstractSeries::SeriesTypePie)
409 409 return QPoint(0, 0);
410 410
411 bool ok;
411 412 if (series && m_seriesList.contains(series))
412 point += series->d_ptr->m_domain->calculateGeometryPoint(value);
413 point += series->d_ptr->m_domain->calculateGeometryPoint(value, ok);
413 414 return point;
414 415 }
415 416
416 417 QList<QAbstractAxis*> ChartDataSet::axes() const
417 418 {
418 419 return m_axisList;
419 420 }
420 421
421 422 QList<QAbstractSeries *> ChartDataSet::series() const
422 423 {
423 424 return m_seriesList;
424 425 }
425 426
426 427 AbstractDomain::DomainType ChartDataSet::selectDomain(QList<QAbstractAxis*> axes)
427 428 {
428 429 enum Type {
429 430 Undefined = 0,
430 431 LogType = 0x1,
431 432 ValueType = 0x2
432 433 };
433 434
434 435 int horizontal(Undefined);
435 436 int vertical(Undefined);
436 437
437 438 foreach(QAbstractAxis* axis, axes)
438 439 {
439 440 switch(axis->type()) {
440 441 case QAbstractAxis::AxisTypeLogValue:
441 442
442 443 if(axis->orientation()==Qt::Horizontal) {
443 444 horizontal|=LogType;
444 445 }
445 446 if(axis->orientation()==Qt::Vertical) {
446 447 vertical|=LogType;
447 448 }
448 449
449 450 break;
450 451 case QAbstractAxis::AxisTypeValue:
451 452 case QAbstractAxis::AxisTypeBarCategory:
452 453 case QAbstractAxis::AxisTypeCategory:
453 454 case QAbstractAxis::AxisTypeDateTime:
454 455 if(axis->orientation()==Qt::Horizontal) {
455 456 horizontal|=ValueType;
456 457 }
457 458 if(axis->orientation()==Qt::Vertical) {
458 459 vertical|=ValueType;
459 460 }
460 461 break;
461 462 default:
462 463 qWarning()<<"Undefined type";
463 464 break;
464 465 }
465 466 }
466 467
467 468 if(vertical==Undefined) vertical=ValueType;
468 469 if(horizontal==Undefined) horizontal=ValueType;
469 470
470 471 if(vertical==ValueType && horizontal== ValueType) {
471 472 return AbstractDomain::XYDomain;
472 473 }
473 474
474 475 if(vertical==LogType && horizontal== ValueType) {
475 476 return AbstractDomain::XLogYDomain;
476 477 }
477 478
478 479 if(vertical==ValueType && horizontal== LogType) {
479 480 return AbstractDomain::LogXYDomain;
480 481 }
481 482
482 483 if(vertical==LogType && horizontal== LogType) {
483 484 return AbstractDomain::LogXLogYDomain;
484 485 }
485 486
486 487 return AbstractDomain::UndefinedDomain;
487 488 }
488 489
489 490
490 491 //refactor create factory
491 492 AbstractDomain* ChartDataSet::createDomain(AbstractDomain::DomainType type)
492 493 {
493 494 switch(type)
494 495 {
495 496 case AbstractDomain::LogXLogYDomain:
496 497 return new LogXLogYDomain();
497 498 case AbstractDomain::XYDomain:
498 499 return new XYDomain();
499 500 case AbstractDomain::XLogYDomain:
500 501 return new XLogYDomain();
501 502 case AbstractDomain::LogXYDomain:
502 503 return new LogXYDomain();
503 504 default:
504 505 return 0;
505 506 }
506 507 }
507 508
508 509 #include "moc_chartdataset_p.cpp"
509 510
510 511 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,46 +1,47
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "chartitem_p.h"
22 22 #include "qabstractseries_p.h"
23 23 #include "abstractdomain_p.h"
24 24
25 25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 26
27 27 ChartItem::ChartItem(QAbstractSeriesPrivate *series,QGraphicsItem* item):
28 28 ChartElement(item),
29 m_validData(true),
29 30 m_series(series)
30 31 {
31 32
32 33 }
33 34
34 35 AbstractDomain* ChartItem::domain() const
35 36 {
36 37 return m_series->domain();
37 38 }
38 39
39 40 void ChartItem::handleDomainUpdated()
40 41 {
41 42 qWarning() << __FUNCTION__<< "Slot not implemented";
42 43 }
43 44
44 45 #include "moc_chartitem_p.cpp"
45 46
46 47 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,54 +1,57
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 CHARTITEM_H
31 31 #define CHARTITEM_H
32 32
33 33 #include "chartelement_p.h"
34 34 #include "chartpresenter_p.h"
35 35 #include <QGraphicsItem>
36 36
37 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 38
39 39 class ChartItem : public ChartElement
40 40 {
41 41 Q_OBJECT
42 42 enum ChartItemTypes { AXIS_ITEM = UserType + 1, XYLINE_ITEM };
43 43 public:
44 44 ChartItem(QAbstractSeriesPrivate *series,QGraphicsItem* item);
45 45 AbstractDomain* domain() const;
46 46 public Q_SLOTS:
47 47 virtual void handleDomainUpdated();
48
49 protected:
50 bool m_validData;
48 51 private:
49 QAbstractSeriesPrivate* m_series;
52 QAbstractSeriesPrivate* m_series;
50 53 };
51 54
52 55 QTCOMMERCIALCHART_END_NAMESPACE
53 56
54 57 #endif /* CHARTITEM_H */
@@ -1,113 +1,113
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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, XYDomain, XLogYDomain, LogXYDomain, LogXLogYDomain };
46 46 public:
47 47 explicit AbstractDomain(QObject *object = 0);
48 48 virtual ~AbstractDomain();
49 49
50 50 void setSize(const QSizeF& size);
51 51 QSizeF size() const;
52 52
53 53 virtual DomainType type() = 0;
54 54
55 55 virtual void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY) = 0;
56 56 void setRangeX(qreal min, qreal max);
57 57 void setRangeY(qreal min, qreal max);
58 58 void setMinX(qreal min);
59 59 void setMaxX(qreal max);
60 60 void setMinY(qreal min);
61 61 void setMaxY(qreal max);
62 62
63 63 qreal minX() const { return m_minX; }
64 64 qreal maxX() const { return m_maxX; }
65 65 qreal minY() const { return m_minY; }
66 66 qreal maxY() const { return m_maxY; }
67 67
68 68 qreal spanX() const;
69 69 qreal spanY() const;
70 70 bool isEmpty() const;
71 71
72 72 void blockRangeSignals(bool block);
73 73 bool rangeSignalsBlocked() const { return m_signalsBlocked; }
74 74
75 75 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const AbstractDomain &domain1, const AbstractDomain &domain2);
76 76 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const AbstractDomain &domain1, const AbstractDomain &domain2);
77 77 friend QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const AbstractDomain &domain);
78 78
79 79 virtual void zoomIn(const QRectF &rect) = 0;
80 80 virtual void zoomOut(const QRectF &rect) = 0;
81 81 virtual void move(qreal dx, qreal dy) = 0;
82 82
83 virtual QPointF calculateGeometryPoint(const QPointF &point) const = 0;
83 virtual QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const = 0;
84 84 virtual QPointF calculateDomainPoint(const QPointF &point) const = 0;
85 85 virtual QVector<QPointF> calculateGeometryPoints(const QList<QPointF>& vector) const = 0;
86 86
87 87 virtual bool attachAxis(QAbstractAxis* axis);
88 88 virtual bool detachAxis(QAbstractAxis* axis);
89 89
90 90 static void looseNiceNumbers(qreal &min, qreal &max, int &ticksCount);
91 91 static qreal niceNumber(qreal x, bool ceiling);
92 92
93 93 Q_SIGNALS:
94 94 void updated();
95 95 void rangeHorizontalChanged(qreal min, qreal max);
96 96 void rangeVerticalChanged(qreal min, qreal max);
97 97
98 98 public Q_SLOTS:
99 99 void handleVerticalAxisRangeChanged(qreal min,qreal max);
100 100 void handleHorizontalAxisRangeChanged(qreal min,qreal max);
101 101
102 102 protected:
103 103 qreal m_minX;
104 104 qreal m_maxX;
105 105 qreal m_minY;
106 106 qreal m_maxY;
107 107 QSizeF m_size;
108 108 bool m_signalsBlocked;
109 109 };
110 110
111 111 QTCOMMERCIALCHART_END_NAMESPACE
112 112
113 113 #endif // ABSTRACTDOMAIN_H
@@ -1,246 +1,258
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
49 49 m_minX = minX;
50 50 m_maxX = maxX;
51 51 axisXChanged = true;
52 52 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
53 53 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
54 54 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
55 55 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
56 56 if(!m_signalsBlocked)
57 emit rangeHorizontalChanged(m_minX, m_maxX);
57 emit rangeHorizontalChanged(m_minX, m_maxX);
58 58 }
59 59
60 60 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
61 61 m_minY = minY;
62 62 m_maxY = maxY;
63 63 axisYChanged = true;
64 64 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
65 65 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
66 66 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
67 67 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
68 68 if(!m_signalsBlocked)
69 emit rangeVerticalChanged(m_minY, m_maxY);
69 emit rangeVerticalChanged(m_minY, m_maxY);
70 70 }
71 71
72 72 if (axisXChanged || axisYChanged)
73 73 emit updated();
74 74 }
75 75
76 76 void LogXLogYDomain::zoomIn(const QRectF &rect)
77 77 {
78 78 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
79 79 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
80 80 qreal leftX = qPow(m_logBaseX, logLeftX);
81 81 qreal rightX = qPow(m_logBaseX, logRightX);
82 82 qreal minX = leftX < rightX ? leftX : rightX;
83 83 qreal maxX = leftX > rightX ? leftX : rightX;
84 84
85 85 qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
86 86 qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
87 87 qreal leftY = qPow(m_logBaseY, logLeftY);
88 88 qreal rightY = qPow(m_logBaseY, logRightY);
89 89 qreal minY = leftY < rightY ? leftY : rightY;
90 90 qreal maxY = leftY > rightY ? leftY : rightY;
91 91
92 92 setRange(minX, maxX, minY, maxY);
93 93 }
94 94
95 95 void LogXLogYDomain::zoomOut(const QRectF &rect)
96 96 {
97 97 const qreal factorX = m_size.width() / rect.width();
98 98 const qreal factorY = m_size.height() / rect.height();
99 99
100 100 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
101 101 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
102 102 qreal leftX = qPow(m_logBaseX, logLeftX);
103 103 qreal rightX = qPow(m_logBaseX, logRIghtX);
104 104 qreal minX = leftX < rightX ? leftX : rightX;
105 105 qreal maxX = leftX > rightX ? leftX : rightX;
106 106
107 107 qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
108 108 qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
109 109 qreal leftY = qPow(m_logBaseY, newLogMinY);
110 110 qreal rightY = qPow(m_logBaseY, newLogMaxY);
111 111 qreal minY = leftY < rightY ? leftY : rightY;
112 112 qreal maxY = leftY > rightY ? leftY : rightY;
113 113
114 114 setRange(minX, maxX, minY, maxY);
115 115 }
116 116
117 117 void LogXLogYDomain::move(qreal dx, qreal dy)
118 118 {
119 119 qreal stepX = dx * qAbs(m_logRightX - m_logLeftX) / m_size.width();
120 120 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
121 121 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
122 122 qreal minX = leftX < rightX ? leftX : rightX;
123 123 qreal maxX = leftX > rightX ? leftX : rightX;
124 124
125 125 qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
126 126 qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
127 127 qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
128 128 qreal minY = leftY < rightY ? leftY : rightY;
129 129 qreal maxY = leftY > rightY ? leftY : rightY;
130 130
131 131 setRange(minX, maxX, minY, maxY);
132 132 }
133 133
134 QPointF LogXLogYDomain::calculateGeometryPoint(const QPointF &point) const
134 QPointF LogXLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
135 135 {
136 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
137 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
138 qreal x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
139 qreal y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
140 return QPointF(x, y);
136 if (point.x() > 0 && point.y() > 0) {
137 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
138 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
139 qreal x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
140 qreal y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
141 ok = true;
142 return QPointF(x, y);
143 } else {
144 qWarning() << "Logarithm of negative value is undefined. Empty layout returned";
145 ok = false;
146 return QPointF();
147 }
141 148 }
142 149
143 150 QVector<QPointF> LogXLogYDomain::calculateGeometryPoints(const QList<QPointF>& vector) const
144 151 {
145 152 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
146 153 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
147 154
148 155 QVector<QPointF> result;
149 156 result.resize(vector.count());
150 157
151 158 for (int i = 0; i < vector.count(); ++i) {
152 qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
153 qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
154 result[i].setX(x);
155 result[i].setY(y);
159 if (vector[i].x() > 0 && vector[i].y() > 0) {
160 qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
161 qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
162 result[i].setX(x);
163 result[i].setY(y);
164 } else {
165 qWarning() << "Logarithm of negative value is undefined. Empty layout returned";
166 return QVector<QPointF>();
167 }
156 168 }
157 169 return result;
158 170 }
159 171
160 172 QPointF LogXLogYDomain::calculateDomainPoint(const QPointF &point) const
161 173 {
162 174 const qreal deltaX = m_size.width() / qAbs(m_logRightX - m_logLeftX);
163 175 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
164 176 qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
165 177 qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
166 178 return QPointF(x, y);
167 179 }
168 180
169 181 bool LogXLogYDomain::attachAxis(QAbstractAxis* axis)
170 182 {
171 183 AbstractDomain::attachAxis(axis);
172 184 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
173 185
174 186 if(logAxis && logAxis->orientation()==Qt::Vertical) {
175 187 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
176 188 handleVerticalAxisBaseChanged(logAxis->base());
177 189 }
178 190
179 191 if(logAxis && logAxis->orientation()==Qt::Horizontal) {
180 192 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
181 193 handleHorizontalAxisBaseChanged(logAxis->base());
182 194 }
183 195
184 196 return true;
185 197 }
186 198
187 199 bool LogXLogYDomain::detachAxis(QAbstractAxis* axis)
188 200 {
189 201 AbstractDomain::detachAxis(axis);
190 202 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
191 203
192 204 if(logAxis && logAxis->orientation()==Qt::Vertical)
193 205 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
194 206
195 207 if(logAxis && logAxis->orientation()==Qt::Horizontal)
196 208 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
197 209
198 210 return true;
199 211 }
200 212
201 213 void LogXLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
202 214 {
203 215 m_logBaseY = baseY;
204 216 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
205 217 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
206 218 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
207 219 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
208 220 emit updated();
209 221 }
210 222
211 223 void LogXLogYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
212 224 {
213 225 m_logBaseX = baseX;
214 226 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
215 227 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
216 228 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
217 229 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
218 230 emit updated();
219 231 }
220 232
221 233 // operators
222 234
223 235 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
224 236 {
225 237 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX) &&
226 238 qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY) &&
227 239 qFuzzyIsNull(domain1.m_minX - domain2.m_minX) &&
228 240 qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
229 241 }
230 242
231 243
232 244 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2)
233 245 {
234 246 return !(domain1 == domain2);
235 247 }
236 248
237 249
238 250 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYDomain &domain)
239 251 {
240 252 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
241 253 return dbg.maybeSpace();
242 254 }
243 255
244 256 #include "moc_logxlogydomain_p.cpp"
245 257
246 258 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,79 +1,79
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 LOGXLOGYDOMAIN_H
31 31 #define LOGXLOGYDOMAIN_H
32 32 #include "abstractdomain_p.h"
33 33 #include <QRectF>
34 34 #include <QSizeF>
35 35
36 36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 37
38 38 class QTCOMMERCIALCHART_AUTOTEST_EXPORT LogXLogYDomain: public AbstractDomain
39 39 {
40 40 Q_OBJECT
41 41 public:
42 42 explicit LogXLogYDomain(QObject *object = 0);
43 43 virtual ~LogXLogYDomain();
44 44
45 45 DomainType type(){ return AbstractDomain::LogXLogYDomain;}
46 46
47 47 void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
48 48
49 49 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2);
50 50 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const LogXLogYDomain &domain1, const LogXLogYDomain &domain2);
51 51 friend QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXLogYDomain &domain);
52 52
53 53 void zoomIn(const QRectF &rect);
54 54 void zoomOut(const QRectF &rect);
55 55 void move(qreal dx, qreal dy);
56 56
57 QPointF calculateGeometryPoint(const QPointF &point) const;
57 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
58 58 QPointF calculateDomainPoint(const QPointF &point) const;
59 59 QVector<QPointF> calculateGeometryPoints(const QList<QPointF>& vector) const;
60 60
61 61 bool attachAxis(QAbstractAxis* axis);
62 62 bool detachAxis(QAbstractAxis* axis);
63 63
64 64 public Q_SLOTS:
65 65 void handleVerticalAxisBaseChanged(qreal baseY);
66 66 void handleHorizontalAxisBaseChanged(qreal baseX);
67 67
68 68 private:
69 69 qreal m_logLeftX;
70 70 qreal m_logRightX;
71 71 qreal m_logBaseX;
72 72 qreal m_logLeftY;
73 73 qreal m_logRightY;
74 74 qreal m_logBaseY;
75 75 };
76 76
77 77 QTCOMMERCIALCHART_END_NAMESPACE
78 78
79 79 #endif // LOGXLOGYDOMAIN_H
@@ -1,223 +1,236
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 if (!qFuzzyCompare(m_minX, minX) || !qFuzzyCompare(m_maxX, maxX)) {
46 46 m_minX = minX;
47 47 m_maxX = maxX;
48 48 axisXChanged = true;
49 49 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
50 50 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
51 51 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
52 52 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
53 53 if(!m_signalsBlocked)
54 emit rangeHorizontalChanged(m_minX, m_maxX);
54 emit rangeHorizontalChanged(m_minX, m_maxX);
55 55 }
56 56
57 57 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
58 58 m_minY = minY;
59 59 m_maxY = maxY;
60 60 axisYChanged = true;
61 61 if(!m_signalsBlocked)
62 emit rangeVerticalChanged(m_minY, m_maxY);
62 emit rangeVerticalChanged(m_minY, m_maxY);
63 63 }
64 64
65 65 if (axisXChanged || axisYChanged)
66 66 emit updated();
67 67 }
68 68
69 69 void LogXYDomain::zoomIn(const QRectF &rect)
70 70 {
71 71 qreal logLeftX = rect.left() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
72 72 qreal logRightX = rect.right() * (m_logRightX - m_logLeftX) / m_size.width() + m_logLeftX;
73 73 qreal leftX = qPow(m_logBaseX, logLeftX);
74 74 qreal rightX = qPow(m_logBaseX, logRightX);
75 75 qreal minX = leftX < rightX ? leftX : rightX;
76 76 qreal maxX = leftX > rightX ? leftX : rightX;
77 77
78 78 qreal dy = spanY() / m_size.height();
79 79 qreal minY = m_minY;
80 80 qreal maxY = m_maxY;
81 81
82 82 minY = maxY - dy * rect.bottom();
83 83 maxY = maxY - dy * rect.top();
84 84
85 85 setRange(minX, maxX, minY, maxY);
86 86 }
87 87
88 88 void LogXYDomain::zoomOut(const QRectF &rect)
89 89 {
90 90 const qreal factorX = m_size.width() / rect.width();
91 91
92 92 qreal logLeftX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 - factorX);
93 93 qreal logRIghtX = m_logLeftX + (m_logRightX - m_logLeftX) / 2 * (1 + factorX);
94 94 qreal leftX = qPow(m_logBaseX, logLeftX);
95 95 qreal rightX = qPow(m_logBaseX, logRIghtX);
96 96 qreal minX = leftX < rightX ? leftX : rightX;
97 97 qreal maxX = leftX > rightX ? leftX : rightX;
98 98
99 99 qreal dy = spanY() / rect.height();
100 100 qreal minY = m_minY;
101 101 qreal maxY = m_maxY;
102 102
103 103 maxY = minY + dy * rect.bottom();
104 104 minY = maxY - dy * m_size.height();
105 105
106 106 setRange(minX, maxX, minY, maxY);
107 107 }
108 108
109 109 void LogXYDomain::move(qreal dx, qreal dy)
110 110 {
111 111 qreal stepX = dx * (m_logRightX - m_logLeftX) / m_size.width();
112 112 qreal leftX = qPow(m_logBaseX, m_logLeftX + stepX);
113 113 qreal rightX = qPow(m_logBaseX, m_logRightX + stepX);
114 114 qreal minX = leftX < rightX ? leftX : rightX;
115 115 qreal maxX = leftX > rightX ? leftX : rightX;
116 116
117 117 qreal y = spanY() / m_size.height();
118 118 qreal minY = m_minY;
119 119 qreal maxY = m_maxY;
120 120
121 121 if (dy != 0) {
122 122 minY = minY + y * dy;
123 123 maxY = maxY + y * dy;
124 124 }
125 125 setRange(minX, maxX, minY, maxY);
126 126 }
127 127
128 QPointF LogXYDomain::calculateGeometryPoint(const QPointF &point) const
128 QPointF LogXYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
129 129 {
130 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
131 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
132 130
133 qreal x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
134 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
135 return QPointF(x, y);
131 if (point.x() > 0) {
132 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
133 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
134
135 qreal x = (log10(point.x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
136 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
137 ok = true;
138 return QPointF(x, y);
139 } else {
140 qWarning() << "Logarithm of negative value is undefined. Empty layout returned";
141 ok = false;
142 return QPointF();
143 }
136 144 }
137 145
138 146 QVector<QPointF> LogXYDomain::calculateGeometryPoints(const QList<QPointF>& vector) const
139 147 {
140 148 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
141 149 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
142 150
143 151 QVector<QPointF> result;
144 152 result.resize(vector.count());
145 153
146 154 for (int i = 0; i < vector.count(); ++i) {
147 qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
148 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
149 result[i].setX(x);
150 result[i].setY(y);
155 if (vector[i].x() > 0) {
156 qreal x = (log10(vector[i].x()) / log10(m_logBaseX)) * deltaX - m_logLeftX * deltaX;
157 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
158 result[i].setX(x);
159 result[i].setY(y);
160 } else {
161 qWarning() << "Logarithm of negative value is undefined. Empty layout returned";
162 return QVector<QPointF>();
163 }
151 164 }
152 165 return result;
153 166 }
154 167
155 168 QPointF LogXYDomain::calculateDomainPoint(const QPointF &point) const
156 169 {
157 170 const qreal deltaX = m_size.width() / (m_logRightX - m_logLeftX);
158 171 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
159 172 qreal x = qPow(m_logBaseX, m_logLeftX + point.x() / deltaX);
160 173 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
161 174 return QPointF(x, y);
162 175 }
163 176
164 177 bool LogXYDomain::attachAxis(QAbstractAxis* axis)
165 178 {
166 179 AbstractDomain::attachAxis(axis);
167 180 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
168 181
169 182 if(logAxis && logAxis->orientation()==Qt::Horizontal) {
170 183 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
171 184 handleHorizontalAxisBaseChanged(logAxis->base());
172 185 }
173 186
174 187 return true;
175 188 }
176 189
177 190 bool LogXYDomain::detachAxis(QAbstractAxis* axis)
178 191 {
179 192 AbstractDomain::detachAxis(axis);
180 193 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
181 194
182 195 if(logAxis && logAxis->orientation()==Qt::Horizontal)
183 196 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleHorizontalAxisBaseChanged(qreal)));
184 197
185 198 return true;
186 199 }
187 200
188 201 void LogXYDomain::handleHorizontalAxisBaseChanged(qreal baseX)
189 202 {
190 203 m_logBaseX = baseX;
191 204 qreal logMinX = log10(m_minX) / log10(m_logBaseX);
192 205 qreal logMaxX = log10(m_maxX) / log10(m_logBaseX);
193 206 m_logLeftX = logMinX < logMaxX ? logMinX : logMaxX;
194 207 m_logRightX = logMinX > logMaxX ? logMinX : logMaxX;
195 208 emit updated();
196 209 }
197 210
198 211 // operators
199 212
200 213 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const LogXYDomain &domain1, const LogXYDomain &domain2)
201 214 {
202 215 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX) &&
203 216 qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY) &&
204 217 qFuzzyIsNull(domain1.m_minX - domain2.m_minX) &&
205 218 qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
206 219 }
207 220
208 221
209 222 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const LogXYDomain &domain1, const LogXYDomain &domain2)
210 223 {
211 224 return !(domain1 == domain2);
212 225 }
213 226
214 227
215 228 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYDomain &domain)
216 229 {
217 230 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
218 231 return dbg.maybeSpace();
219 232 }
220 233
221 234 #include "moc_logxydomain_p.cpp"
222 235
223 236 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,75 +1,75
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 LOGXYDOMAIN_H
31 31 #define LOGXYDOMAIN_H
32 32 #include "abstractdomain_p.h"
33 33 #include <QRectF>
34 34 #include <QSizeF>
35 35
36 36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 37
38 38 class QTCOMMERCIALCHART_AUTOTEST_EXPORT LogXYDomain: public AbstractDomain
39 39 {
40 40 Q_OBJECT
41 41 public:
42 42 explicit LogXYDomain(QObject *object = 0);
43 43 virtual ~LogXYDomain();
44 44
45 45 DomainType type(){ return AbstractDomain::LogXYDomain;}
46 46
47 47 void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
48 48
49 49 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const LogXYDomain &domain1, const LogXYDomain &domain2);
50 50 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const LogXYDomain &domain1, const LogXYDomain &domain2);
51 51 friend QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const LogXYDomain &domain);
52 52
53 53 void zoomIn(const QRectF &rect);
54 54 void zoomOut(const QRectF &rect);
55 55 void move(qreal dx, qreal dy);
56 56
57 QPointF calculateGeometryPoint(const QPointF &point) const;
57 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
58 58 QPointF calculateDomainPoint(const QPointF &point) const;
59 59 QVector<QPointF> calculateGeometryPoints(const QList<QPointF>& vector) const;
60 60
61 61 bool attachAxis(QAbstractAxis* axis);
62 62 bool detachAxis(QAbstractAxis* axis);
63 63
64 64 public Q_SLOTS:
65 65 void handleHorizontalAxisBaseChanged(qreal baseX);
66 66
67 67 private:
68 68 qreal m_logLeftX;
69 69 qreal m_logRightX;
70 70 qreal m_logBaseX;
71 71 };
72 72
73 73 QTCOMMERCIALCHART_END_NAMESPACE
74 74
75 75 #endif // LOGXYDOMAIN_H
@@ -1,220 +1,232
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 if (!qFuzzyIsNull(m_minX - minX) || !qFuzzyIsNull(m_maxX - maxX)) {
46 46 m_minX = minX;
47 47 m_maxX = maxX;
48 48 axisXChanged = true;
49 49 if(!m_signalsBlocked)
50 emit rangeHorizontalChanged(m_minX, m_maxX);
50 emit rangeHorizontalChanged(m_minX, m_maxX);
51 51 }
52 52
53 53 if (!qFuzzyIsNull(m_minY - minY) || !qFuzzyIsNull(m_maxY - maxY)) {
54 54 m_minY = minY;
55 55 m_maxY = maxY;
56 56 axisYChanged = true;
57 57 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
58 58 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
59 59 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
60 60 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
61 61 if(!m_signalsBlocked)
62 emit rangeVerticalChanged(m_minY, m_maxY);
62 emit rangeVerticalChanged(m_minY, m_maxY);
63 63 }
64 64
65 65 if (axisXChanged || axisYChanged)
66 66 emit updated();
67 67 }
68 68
69 69 void XLogYDomain::zoomIn(const QRectF &rect)
70 70 {
71 71 qreal dx = spanX() / m_size.width();
72 72 qreal maxX = m_maxX;
73 73 qreal minX = m_minX;
74 74
75 75 maxX = minX + dx * rect.right();
76 76 minX = minX + dx * rect.left();
77 77
78 78 qreal logLeftY = m_logRightY - rect.bottom() * (m_logRightY - m_logLeftY) / m_size.height();
79 79 qreal logRightY = m_logRightY - rect.top() * (m_logRightY - m_logLeftY) / m_size.height();
80 80 qreal leftY = qPow(m_logBaseY, logLeftY);
81 81 qreal rightY = qPow(m_logBaseY, logRightY);
82 82 qreal minY = leftY < rightY ? leftY : rightY;
83 83 qreal maxY = leftY > rightY ? leftY : rightY;
84 84
85 85 setRange(minX, maxX, minY, maxY);
86 86 }
87 87
88 88 void XLogYDomain::zoomOut(const QRectF &rect)
89 89 {
90 90 qreal dx = spanX() / rect.width();
91 91 qreal maxX = m_maxX;
92 92 qreal minX = m_minX;
93 93
94 94 minX = maxX - dx * rect.right();
95 95 maxX = minX + dx * m_size.width();
96 96
97 97 const qreal factorY = m_size.height() / rect.height();
98 98 qreal newLogMinY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 - factorY);
99 99 qreal newLogMaxY = m_logLeftY + (m_logRightY - m_logLeftY) / 2 * (1 + factorY);
100 100 qreal leftY = qPow(m_logBaseY, newLogMinY);
101 101 qreal rightY = qPow(m_logBaseY, newLogMaxY);
102 102 qreal minY = leftY < rightY ? leftY : rightY;
103 103 qreal maxY = leftY > rightY ? leftY : rightY;
104 104
105 105 setRange(minX, maxX, minY, maxY);
106 106 }
107 107
108 108 void XLogYDomain::move(qreal dx, qreal dy)
109 109 {
110 110 qreal x = spanX() / m_size.width();
111 111 qreal maxX = m_maxX;
112 112 qreal minX = m_minX;
113 113
114 114 if (dx != 0) {
115 115 minX = minX + x * dx;
116 116 maxX = maxX + x * dx;
117 117 }
118 118
119 119 qreal stepY = dy * (m_logRightY - m_logLeftY) / m_size.height();
120 120 qreal leftY = qPow(m_logBaseY, m_logLeftY + stepY);
121 121 qreal rightY = qPow(m_logBaseY, m_logRightY + stepY);
122 122 qreal minY = leftY < rightY ? leftY : rightY;
123 123 qreal maxY = leftY > rightY ? leftY : rightY;
124 124
125 125 setRange(minX, maxX, minY, maxY);
126 126 }
127 127
128 QPointF XLogYDomain::calculateGeometryPoint(const QPointF &point) const
128 QPointF XLogYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
129 129 {
130 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
131 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
132
133 qreal x = (point.x() - m_minX) * deltaX;
134 qreal y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
135 return QPointF(x, y);
130 if (point.y() > 0) {
131 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
132 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
133
134 qreal x = (point.x() - m_minX) * deltaX;
135 qreal y = (log10(point.y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
136 ok = true;
137 return QPointF(x, y);
138 } else {
139 qWarning() << "Logarithm of negative value is undefined. Empty layout returned";
140 ok = false;
141 return QPointF();
142 }
136 143 }
137 144
138 145 QVector<QPointF> XLogYDomain::calculateGeometryPoints(const QList<QPointF>& vector) const
139 146 {
140 147 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
141 148 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
142 149
143 150 QVector<QPointF> result;
144 151 result.resize(vector.count());
145 152
146 153 for (int i = 0; i < vector.count(); ++i) {
147 qreal x = (vector[i].x() - m_minX) * deltaX;
148 qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
149 result[i].setX(x);
150 result[i].setY(y);
154 if (vector[i].y() > 0) {
155 qreal x = (vector[i].x() - m_minX) * deltaX;
156 qreal y = (log10(vector[i].y()) / log10(m_logBaseY)) * -deltaY - m_logLeftY * -deltaY + m_size.height();
157 result[i].setX(x);
158 result[i].setY(y);
159 } else {
160 qWarning() << "Logarithm of negative value is undefined. Empty layout returned";
161 return QVector<QPointF>();
162 }
151 163 }
152 164 return result;
153 165 }
154 166
155 167 QPointF XLogYDomain::calculateDomainPoint(const QPointF &point) const
156 168 {
157 169 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
158 170 const qreal deltaY = m_size.height() / qAbs(m_logRightY - m_logLeftY);
159 171 qreal x = point.x() / deltaX + m_minX;
160 172 qreal y = qPow(m_logBaseY, m_logLeftY + (m_size.height() - point.y()) / deltaY);
161 173 return QPointF(x, y);
162 174 }
163 175
164 176 bool XLogYDomain::attachAxis(QAbstractAxis* axis)
165 177 {
166 178 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
167 179
168 180 if(logAxis && logAxis->orientation()==Qt::Vertical){
169 181 QObject::connect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
170 182 handleVerticalAxisBaseChanged(logAxis->base());
171 }
183 }
172 184 return AbstractDomain::attachAxis(axis);
173 185 }
174 186
175 187 bool XLogYDomain::detachAxis(QAbstractAxis* axis)
176 188 {
177 189 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(axis);
178 190
179 191 if(logAxis && logAxis->orientation()==Qt::Vertical)
180 192 QObject::disconnect(logAxis, SIGNAL(baseChanged(qreal)), this, SLOT(handleVerticalAxisBaseChanged(qreal)));
181 193
182 194 return AbstractDomain::detachAxis(axis);
183 195 }
184 196
185 197 void XLogYDomain::handleVerticalAxisBaseChanged(qreal baseY)
186 198 {
187 199 m_logBaseY = baseY;
188 200 qreal logMinY = log10(m_minY) / log10(m_logBaseY);
189 201 qreal logMaxY = log10(m_maxY) / log10(m_logBaseY);
190 202 m_logLeftY = logMinY < logMaxY ? logMinY : logMaxY;
191 203 m_logRightY = logMinY > logMaxY ? logMinY : logMaxY;
192 204 emit updated();
193 205 }
194 206
195 207 // operators
196 208
197 209 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const XLogYDomain &domain1, const XLogYDomain &domain2)
198 210 {
199 211 return (qFuzzyIsNull(domain1.m_maxX - domain2.m_maxX) &&
200 212 qFuzzyIsNull(domain1.m_maxY - domain2.m_maxY) &&
201 213 qFuzzyIsNull(domain1.m_minX - domain2.m_minX) &&
202 214 qFuzzyIsNull(domain1.m_minY - domain2.m_minY));
203 215 }
204 216
205 217
206 218 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XLogYDomain &domain1, const XLogYDomain &domain2)
207 219 {
208 220 return !(domain1 == domain2);
209 221 }
210 222
211 223
212 224 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYDomain &domain)
213 225 {
214 226 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
215 227 return dbg.maybeSpace();
216 228 }
217 229
218 230 #include "moc_xlogydomain_p.cpp"
219 231
220 232 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,75 +1,75
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 XLOGYDOMAIN_H
31 31 #define XLOGYDOMAIN_H
32 32 #include "abstractdomain_p.h"
33 33 #include <QRectF>
34 34 #include <QSizeF>
35 35
36 36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 37
38 38 class QTCOMMERCIALCHART_AUTOTEST_EXPORT XLogYDomain: public AbstractDomain
39 39 {
40 40 Q_OBJECT
41 41 public:
42 42 explicit XLogYDomain(QObject *object = 0);
43 43 virtual ~XLogYDomain();
44 44
45 45 DomainType type(){ return AbstractDomain::XLogYDomain;};
46 46
47 47 void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
48 48
49 49 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const XLogYDomain &domain1, const XLogYDomain &domain2);
50 50 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XLogYDomain &domain1, const XLogYDomain &domain2);
51 51 friend QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYDomain &domain);
52 52
53 53 void zoomIn(const QRectF &rect);
54 54 void zoomOut(const QRectF &rect);
55 55 void move(qreal dx, qreal dy);
56 56
57 QPointF calculateGeometryPoint(const QPointF &point) const;
57 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
58 58 QPointF calculateDomainPoint(const QPointF &point) const;
59 59 QVector<QPointF> calculateGeometryPoints(const QList<QPointF>& vector) const;
60 60
61 61 bool attachAxis(QAbstractAxis* axis);
62 62 bool detachAxis(QAbstractAxis* axis);
63 63
64 64 public Q_SLOTS:
65 65 void handleVerticalAxisBaseChanged(qreal baseY);
66 66
67 67 private:
68 68 qreal m_logLeftY;
69 69 qreal m_logRightY;
70 70 qreal m_logBaseY;
71 71 };
72 72
73 73 QTCOMMERCIALCHART_END_NAMESPACE
74 74
75 75 #endif // XLOGYDOMAIN_H
@@ -1,179 +1,180
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 64 qreal dx = spanX() / m_size.width();
65 65 qreal dy = spanY() / m_size.height();
66 66
67 67 qreal maxX = m_maxX;
68 68 qreal minX = m_minX;
69 69 qreal minY = m_minY;
70 70 qreal maxY = m_maxY;
71 71
72 72 maxX = minX + dx * rect.right();
73 73 minX = minX + dx * rect.left();
74 74 minY = maxY - dy * rect.bottom();
75 75 maxY = maxY - dy * rect.top();
76 76
77 77 setRange(minX, maxX, minY, maxY);
78 78 }
79 79
80 80 void XYDomain::zoomOut(const QRectF &rect)
81 81 {
82 82 qreal dx = spanX() / rect.width();
83 83 qreal dy = spanY() / rect.height();
84 84
85 85 qreal maxX = m_maxX;
86 86 qreal minX = m_minX;
87 87 qreal minY = m_minY;
88 88 qreal maxY = m_maxY;
89 89
90 90 minX = maxX - dx * rect.right();
91 91 maxX = minX + dx * m_size.width();
92 92 maxY = minY + dy * rect.bottom();
93 93 minY = maxY - dy * m_size.height();
94 94
95 95 setRange(minX, maxX, minY, maxY);
96 96 }
97 97
98 98 void XYDomain::move(qreal dx, qreal dy)
99 99 {
100 100 qreal x = spanX() / m_size.width();
101 101 qreal y = spanY() / m_size.height();
102 102
103 103 qreal maxX = m_maxX;
104 104 qreal minX = m_minX;
105 105 qreal minY = m_minY;
106 106 qreal maxY = m_maxY;
107 107
108 108 if (dx != 0) {
109 109 minX = minX + x * dx;
110 110 maxX = maxX + x * dx;
111 111 }
112 112 if (dy != 0) {
113 113 minY = minY + y * dy;
114 114 maxY = maxY + y * dy;
115 115 }
116 116 setRange(minX, maxX, minY, maxY);
117 117 }
118 118
119 QPointF XYDomain::calculateGeometryPoint(const QPointF &point) const
119 QPointF XYDomain::calculateGeometryPoint(const QPointF &point, bool &ok) const
120 120 {
121 121 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
122 122 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
123 123 qreal x = (point.x() - m_minX) * deltaX;
124 124 qreal y = (point.y() - m_minY) * -deltaY + m_size.height();
125 ok = true;
125 126 return QPointF(x, y);
126 127 }
127 128
128 129 QVector<QPointF> XYDomain::calculateGeometryPoints(const QList<QPointF>& vector) const
129 130 {
130 131 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
131 132 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
132 133
133 134 QVector<QPointF> result;
134 135 result.resize(vector.count());
135 136
136 137 for (int i = 0; i < vector.count(); ++i) {
137 138 qreal x = (vector[i].x() - m_minX) * deltaX;
138 139 qreal y = (vector[i].y() - m_minY) * -deltaY + m_size.height();
139 140 result[i].setX(x);
140 141 result[i].setY(y);
141 142 }
142 143 return result;
143 144 }
144 145
145 146 QPointF XYDomain::calculateDomainPoint(const QPointF &point) const
146 147 {
147 148 const qreal deltaX = m_size.width() / (m_maxX - m_minX);
148 149 const qreal deltaY = m_size.height() / (m_maxY - m_minY);
149 150 qreal x = point.x() / deltaX + m_minX;
150 151 qreal y = (point.y() - m_size.height()) / (-deltaY) + m_minY;
151 152 return QPointF(x, y);
152 153 }
153 154
154 155 // operators
155 156
156 157 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const XYDomain &domain1, const XYDomain &domain2)
157 158 {
158 159 return (qFuzzyCompare(domain1.m_maxX, domain2.m_maxX) &&
159 160 qFuzzyCompare(domain1.m_maxY, domain2.m_maxY) &&
160 161 qFuzzyCompare(domain1.m_minX, domain2.m_minX) &&
161 162 qFuzzyCompare(domain1.m_minY, domain2.m_minY));
162 163 }
163 164
164 165
165 166 bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XYDomain &domain1, const XYDomain &domain2)
166 167 {
167 168 return !(domain1 == domain2);
168 169 }
169 170
170 171
171 172 QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYDomain &domain)
172 173 {
173 174 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
174 175 return dbg.maybeSpace();
175 176 }
176 177
177 178 #include "moc_xydomain_p.cpp"
178 179
179 180 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,64 +1,64
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 XYDOMAIN_H
31 31 #define XYDOMAIN_H
32 32 #include "abstractdomain_p.h"
33 33 #include <QRectF>
34 34 #include <QSizeF>
35 35
36 36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 37
38 38 class QTCOMMERCIALCHART_AUTOTEST_EXPORT XYDomain: public AbstractDomain
39 39 {
40 40 Q_OBJECT
41 41 public:
42 42 explicit XYDomain(QObject *object = 0);
43 43 virtual ~XYDomain();
44 44
45 45 DomainType type(){ return AbstractDomain::XYDomain;}
46 46
47 47 void setRange(qreal minX, qreal maxX, qreal minY, qreal maxY);
48 48
49 49 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator== (const XYDomain &Domain1, const XYDomain &Domain2);
50 50 friend bool QTCOMMERCIALCHART_AUTOTEST_EXPORT operator!= (const XYDomain &Domain1, const XYDomain &Domain2);
51 51 friend QDebug QTCOMMERCIALCHART_AUTOTEST_EXPORT operator<<(QDebug dbg, const XYDomain &AbstractDomain);
52 52
53 53 void zoomIn(const QRectF &rect);
54 54 void zoomOut(const QRectF &rect);
55 55 void move(qreal dx, qreal dy);
56 56
57 QPointF calculateGeometryPoint(const QPointF &point) const;
57 QPointF calculateGeometryPoint(const QPointF &point, bool &ok) const;
58 58 QPointF calculateDomainPoint(const QPointF &point) const;
59 59 QVector<QPointF> calculateGeometryPoints(const QList<QPointF>& vector) const;
60 60 };
61 61
62 62 QTCOMMERCIALCHART_END_NAMESPACE
63 63
64 64 #endif // XYDOMAIN_H
@@ -1,151 +1,151
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "linechartitem_p.h"
22 22 #include "qlineseries.h"
23 23 #include "qlineseries_p.h"
24 24 #include "chartpresenter_p.h"
25 25 #include "abstractdomain_p.h"
26 26 #include <QPainter>
27 27 #include <QGraphicsSceneMouseEvent>
28 28
29 29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 30
31 31 const qreal mouseEventMinWidth(12);
32 32
33 33 LineChartItem::LineChartItem(QLineSeries *series,QGraphicsItem* item)
34 34 : XYChart(series,item),
35 35 m_series(series),
36 36 m_pointsVisible(false)
37 37 {
38 38 setAcceptHoverEvents(true);
39 39 setZValue(ChartPresenter::LineChartZValue);
40 40 QObject::connect(series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdated()));
41 41 QObject::connect(series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
42 42 QObject::connect(series, SIGNAL(opacityChanged()), this, SLOT(handleUpdated()));
43 43 handleUpdated();
44 44 }
45 45
46 46 QRectF LineChartItem::boundingRect() const
47 47 {
48 48 return m_rect;
49 49 }
50 50
51 51 QPainterPath LineChartItem::shape() const
52 52 {
53 53 return m_path;
54 54 }
55 55
56 56 void LineChartItem::updateGeometry()
57 57 {
58 58 m_points = geometryPoints();
59 59
60 60 if (m_points.size() == 0) {
61 61 prepareGeometryChange();
62 62 m_path = QPainterPath();
63 63 m_rect = QRect();
64 64 return;
65 65 }
66 66
67 67 QPainterPath linePath(m_points.at(0));
68 68
69 69 if (m_pointsVisible) {
70 70
71 71 int size = m_linePen.width();
72 72 linePath.addEllipse(m_points.at(0), size, size);
73 73 for (int i = 1; i < m_points.size(); i++) {
74 74 linePath.lineTo(m_points.at(i));
75 75 linePath.addEllipse(m_points.at(i), size, size);
76 76 linePath.moveTo(m_points.at(i));
77 77 }
78 78
79 79 } else {
80 80 for (int i = 1; i < m_points.size(); i++)
81 81 linePath.lineTo(m_points.at(i));
82 82 }
83 83
84 84 m_linePath = linePath;
85 85
86 86 QPainterPathStroker stroker;
87 87 // QPainter::drawLine does not respect join styles, for example BevelJoin becomes MiterJoin.
88 88 // This is why we are prepared for the "worst case" scenario, i.e. use always MiterJoin and
89 89 // multiply line width with square root of two when defining shape and bounding rectangle.
90 90 stroker.setWidth(m_linePen.width() * 1.42);
91 91 stroker.setJoinStyle(Qt::MiterJoin);
92 92 stroker.setCapStyle(Qt::SquareCap);
93 93 stroker.setMiterLimit(m_linePen.miterLimit());
94 94
95 95 prepareGeometryChange();
96 96
97 97 m_path = stroker.createStroke(linePath);
98 98 m_rect = m_path.boundingRect();
99 99 }
100 100
101 101 void LineChartItem::handleUpdated()
102 102 {
103 103 setVisible(m_series->isVisible());
104 104 setOpacity(m_series->opacity());
105 105 m_pointsVisible = m_series->pointsVisible();
106 106 m_linePen = m_series->pen();
107 107 update();
108 108 }
109 109
110 110 void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
111 111 {
112 112 Q_UNUSED(widget)
113 113 Q_UNUSED(option)
114 114
115 115 painter->save();
116 116 painter->setPen(m_linePen);
117 117 painter->setBrush(m_linePen.color());
118 118 painter->setClipRect(QRectF(QPointF(0,0),domain()->size()));
119 119
120 120 if (m_pointsVisible) {
121 121 painter->drawPath(m_linePath);
122 122 } else {
123 123 for (int i(1); i < m_points.size(); i++)
124 124 painter->drawLine(m_points.at(i - 1), m_points.at(i));
125 125 }
126 126 painter->restore();
127 127 }
128 128
129 129 void LineChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
130 130 {
131 131 emit XYChart::clicked(domain()->calculateDomainPoint(event->pos()));
132 132 QGraphicsItem::mousePressEvent(event);
133 133 }
134 134
135 135 void LineChartItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
136 136 {
137 137 emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), true);
138 event->accept();
139 //QGraphicsItem::hoverEnterEvent(event);
138 // event->accept();
139 QGraphicsItem::hoverEnterEvent(event);
140 140 }
141 141
142 142 void LineChartItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
143 143 {
144 144 emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), false);
145 event->accept();
146 //QGraphicsItem::hoverEnterEvent(event);
145 // event->accept();
146 QGraphicsItem::hoverEnterEvent(event);
147 147 }
148 148
149 149 #include "moc_linechartitem_p.cpp"
150 150
151 151 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,190 +1,191
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "splinechartitem_p.h"
22 22 #include "qsplineseries_p.h"
23 23 #include "chartpresenter_p.h"
24 24 #include "splineanimation_p.h"
25 25 #include "abstractdomain_p.h"
26 26 #include <QPainter>
27 27 #include <QGraphicsSceneMouseEvent>
28 28
29 29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 30
31 31 SplineChartItem::SplineChartItem(QSplineSeries *series, QGraphicsItem* item)
32 32 : XYChart(series,item),
33 33 m_series(series),
34 34 m_pointsVisible(false),
35 35 m_animation(0)
36 36 {
37 37 setAcceptHoverEvents(true);
38 38 setZValue(ChartPresenter::SplineChartZValue);
39 39 QObject::connect(m_series->d_func(), SIGNAL(updated()), this, SLOT(handleUpdated()));
40 40 QObject::connect(series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
41 41 QObject::connect(series, SIGNAL(opacityChanged()), this, SLOT(handleUpdated()));
42 42 handleUpdated();
43 43 }
44 44
45 45 QRectF SplineChartItem::boundingRect() const
46 46 {
47 47 return m_rect;
48 48 }
49 49
50 50 QPainterPath SplineChartItem::shape() const
51 51 {
52 52 QPainterPathStroker stroker;
53 53 return stroker.createStroke(m_path);
54 54 }
55 55
56 56 void SplineChartItem::setAnimation(SplineAnimation *animation)
57 57 {
58 58 m_animation = animation;
59 59 XYChart::setAnimation(animation);
60 60 }
61 61
62 62 ChartAnimation *SplineChartItem::animation() const
63 63 {
64 64 return m_animation;
65 65 }
66 66
67 67 void SplineChartItem::setControlGeometryPoints(QVector<QPointF>& points)
68 68 {
69 69 m_controlPoints = points;
70 70 }
71 71
72 72 QVector<QPointF> SplineChartItem::controlGeometryPoints() const
73 73 {
74 74 return m_controlPoints;
75 75 }
76 76
77 77 void SplineChartItem::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
78 78 {
79 79 QVector<QPointF> controlPoints;
80 80
81 81 if (newPoints.count() >= 2)
82 82 controlPoints.resize(newPoints.count() * 2 - 2);
83 83
84 84 for (int i = 0; i < newPoints.size() - 1; i++) {
85 85 controlPoints[2 * i] = calculateGeometryControlPoint(2 * i);
86 86 controlPoints[2 * i + 1] = calculateGeometryControlPoint(2 * i + 1);
87 87 }
88 88
89 89 if (m_animation)
90 90 m_animation->setup(oldPoints, newPoints, m_controlPoints, controlPoints, index);
91 91
92 92 m_points = newPoints;
93 93 m_controlPoints = controlPoints;
94 94 setDirty(false);
95 95
96 96 if (m_animation)
97 97 presenter()->startAnimation(m_animation);
98 98 else
99 99 updateGeometry();
100 100 }
101 101
102 102 QPointF SplineChartItem::calculateGeometryControlPoint(int index) const
103 103 {
104 return domain()->calculateGeometryPoint(m_series->d_func()->controlPoint(index));
104 bool ok;
105 return domain()->calculateGeometryPoint(m_series->d_func()->controlPoint(index), ok);
105 106 }
106 107
107 108 void SplineChartItem::updateGeometry()
108 109 {
109 110 const QVector<QPointF> &points = m_points;
110 111 const QVector<QPointF> &controlPoints = m_controlPoints;
111 112
112 113 if ((points.size() < 2) || (controlPoints.size() < 2)) {
113 114 prepareGeometryChange();
114 115 m_path = QPainterPath();
115 116 m_rect = QRect();
116 117 return;
117 118 }
118 119
119 120 Q_ASSERT(points.count() * 2 - 2 == controlPoints.count());
120 121
121 122 QPainterPath splinePath(points.at(0));
122 123
123 124 for (int i = 0; i < points.size() - 1; i++) {
124 125 const QPointF &point = points.at(i + 1);
125 126 splinePath.cubicTo(controlPoints[2 * i], controlPoints[2 * i + 1], point);
126 127 }
127 128
128 129 prepareGeometryChange();
129 130 // QPainterPathStroker stroker;
130 131 // stroker.setWidth(m_linePen.width() / 2.0);
131 132 // m_path = stroker.createStroke(splinePath);
132 133 m_path = splinePath;
133 134 m_rect = splinePath.boundingRect();
134 135
135 136 }
136 137
137 138 //handlers
138 139
139 140 void SplineChartItem::handleUpdated()
140 141 {
141 142 setVisible(m_series->isVisible());
142 143 setOpacity(m_series->opacity());
143 144 m_pointsVisible = m_series->pointsVisible();
144 145 m_linePen = m_series->pen();
145 146 m_pointPen = m_series->pen();
146 147 m_pointPen.setWidthF(2 * m_pointPen.width());
147 148 update();
148 149 }
149 150
150 151 //painter
151 152
152 153 void SplineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
153 154 {
154 155 Q_UNUSED(widget)
155 156 Q_UNUSED(option)
156 157
157 158 painter->save();
158 159 painter->setClipRect(QRectF(QPointF(0,0),domain()->size()));
159 160 painter->setPen(m_linePen);
160 161 // painter->setBrush(m_linePen.color());
161 162
162 163 painter->drawPath(m_path);
163 164 if (m_pointsVisible) {
164 165 painter->setPen(m_pointPen);
165 166 painter->drawPoints(geometryPoints());
166 167 }
167 168 painter->restore();
168 169 }
169 170
170 171 void SplineChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
171 172 {
172 173 emit XYChart::clicked(domain()->calculateDomainPoint(event->pos()));
173 174 QGraphicsItem::mousePressEvent(event);
174 175 }
175 176
176 177 void SplineChartItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
177 178 {
178 179 emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), true);
179 event->accept();
180 QGraphicsItem::hoverEnterEvent(event);
180 181 }
181 182
182 183 void SplineChartItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
183 184 {
184 185 emit XYChart::hovered(domain()->calculateDomainPoint(event->pos()), false);
185 event->accept();
186 QGraphicsItem::hoverLeaveEvent(event);
186 187 }
187 188
188 189 #include "moc_splinechartitem_p.cpp"
189 190
190 191 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,154 +1,162
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "xychart_p.h"
22 22 #include "qxyseries.h"
23 23 #include "qxyseries_p.h"
24 24 #include "chartpresenter_p.h"
25 25 #include "abstractdomain_p.h"
26 26 #include "qxymodelmapper.h"
27 27 #include <QPainter>
28 28 #include <QAbstractItemModel>
29 29
30 30
31 31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 32
33 33 //TODO: optimize : remove points which are not visible
34 34
35 35 XYChart::XYChart(QXYSeries *series,QGraphicsItem* item):
36 36 ChartItem(series->d_func(),item),
37 37 m_series(series),
38 38 m_animation(0),
39 39 m_dirty(true)
40 40 {
41 41 QObject::connect(series, SIGNAL(pointReplaced(int)), this, SLOT(handlePointReplaced(int)));
42 42 QObject::connect(series, SIGNAL(pointsReplaced()), this, SLOT(handlePointsReplaced()));
43 43 QObject::connect(series, SIGNAL(pointAdded(int)), this, SLOT(handlePointAdded(int)));
44 44 QObject::connect(series, SIGNAL(pointRemoved(int)), this, SLOT(handlePointRemoved(int)));
45 45 QObject::connect(this, SIGNAL(clicked(QPointF)), series, SIGNAL(clicked(QPointF)));
46 46 QObject::connect(this, SIGNAL(hovered(QPointF,bool)), series, SIGNAL(hovered(QPointF,bool)));
47 47 }
48 48
49 49 void XYChart::setGeometryPoints(const QVector<QPointF>& points)
50 50 {
51 51 m_points = points;
52 52 }
53 53
54 54 void XYChart::setAnimation(XYAnimation *animation)
55 55 {
56 56 m_animation = animation;
57 57 }
58 58
59 59 void XYChart::setDirty(bool dirty)
60 60 {
61 61 m_dirty = dirty;
62 62 }
63 63
64 64 void XYChart::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
65 65 {
66 66
67 67 if (m_animation) {
68 68 m_animation->setup(oldPoints, newPoints, index);
69 69 m_points = newPoints;
70 70 setDirty(false);
71 71 presenter()->startAnimation(m_animation);
72 72 } else {
73 73 m_points = newPoints;
74 74 updateGeometry();
75 75 }
76 76 }
77 77
78 78 //handlers
79 79
80 80 void XYChart::handlePointAdded(int index)
81 81 {
82 82 Q_ASSERT(index < m_series->count());
83 83 Q_ASSERT(index >= 0);
84 84
85 85 QVector<QPointF> points;
86 86
87 87 if (m_dirty) {
88 88 points = domain()->calculateGeometryPoints(m_series->points());
89 89 } else {
90 90 points = m_points;
91 QPointF point = domain()->calculateGeometryPoint(m_series->points()[index]);
91 QPointF point = domain()->calculateGeometryPoint(m_series->points()[index], m_validData);
92 if (!m_validData) {
93 m_points.clear();
94 return;
95 }
92 96 points.insert(index, point);
93 97 }
94 98
95 99 updateChart(m_points, points, index);
96 100 }
97 101
98 102 void XYChart::handlePointRemoved(int index)
99 103 {
100 104 Q_ASSERT(index <= m_series->count());
101 105 Q_ASSERT(index >= 0);
102 106
103 107 QVector<QPointF> points;
104 108
105 109 if (m_dirty) {
106 110 points = domain()->calculateGeometryPoints(m_series->points());
107 111 } else {
108 112 points = m_points;
109 113 points.remove(index);
110 114 }
111 115
112 116 updateChart(m_points, points, index);
113 117 }
114 118
115 119 void XYChart::handlePointReplaced(int index)
116 120 {
117 121 Q_ASSERT(index < m_series->count());
118 122 Q_ASSERT(index >= 0);
119 123
120 124 QVector<QPointF> points;
121 125
122 126 if (m_dirty) {
123 127 points = domain()->calculateGeometryPoints(m_series->points());
124 128 } else {
125 QPointF point = domain()->calculateGeometryPoint(m_series->points()[index]);
129 QPointF point = domain()->calculateGeometryPoint(m_series->points()[index], m_validData);
130 if (!m_validData) {
131 m_points.clear();
132 return;
133 }
126 134 points = m_points;
127 135 points.replace(index, point);
128 136 }
129 137
130 138 updateChart(m_points, points, index);
131 139 }
132 140
133 141 void XYChart::handlePointsReplaced()
134 142 {
135 143 // All the points were replaced -> recalculate
136 144 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->points());
137 145 updateChart(m_points, points, -1);
138 146 }
139 147
140 148 void XYChart::handleDomainUpdated()
141 149 {
142 150 if (isEmpty()) return;
143 151 QVector<QPointF> points = domain()->calculateGeometryPoints(m_series->points());
144 152 updateChart(m_points, points);
145 153 }
146 154
147 155 bool XYChart::isEmpty()
148 156 {
149 157 return domain()->isEmpty() || m_series->points().isEmpty();
150 158 }
151 159
152 160 #include "moc_xychart_p.cpp"
153 161
154 162 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now