##// END OF EJS Templates
Fix multiline axis label positioning....
Miikka Heikkinen -
r2534:ec1756baf233
parent child
Show More
@@ -1,142 +1,138
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartbarcategoryaxisx_p.h"
21 #include "chartbarcategoryaxisx_p.h"
22 #include "chartpresenter_p.h"
22 #include "chartpresenter_p.h"
23 #include "qbarcategoryaxis_p.h"
23 #include "qbarcategoryaxis_p.h"
24 #include "abstractchartlayout_p.h"
24 #include "abstractchartlayout_p.h"
25 #include <QFontMetrics>
26 #include <QDebug>
25 #include <QDebug>
27 #include <qmath.h>
26 #include <qmath.h>
28
27
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30
29
31 ChartBarCategoryAxisX::ChartBarCategoryAxisX(QBarCategoryAxis *axis, QGraphicsItem* item)
30 ChartBarCategoryAxisX::ChartBarCategoryAxisX(QBarCategoryAxis *axis, QGraphicsItem* item)
32 : HorizontalAxis(axis, item, true),
31 : HorizontalAxis(axis, item, true),
33 m_categoriesAxis(axis)
32 m_categoriesAxis(axis)
34 {
33 {
35 QObject::connect(m_categoriesAxis,SIGNAL(categoriesChanged()),this, SLOT(handleCategoriesChanged()));
34 QObject::connect(m_categoriesAxis,SIGNAL(categoriesChanged()),this, SLOT(handleCategoriesChanged()));
36 handleCategoriesChanged();
35 handleCategoriesChanged();
37 }
36 }
38
37
39 ChartBarCategoryAxisX::~ChartBarCategoryAxisX()
38 ChartBarCategoryAxisX::~ChartBarCategoryAxisX()
40 {
39 {
41 }
40 }
42
41
43 QVector<qreal> ChartBarCategoryAxisX::calculateLayout() const
42 QVector<qreal> ChartBarCategoryAxisX::calculateLayout() const
44 {
43 {
45 QVector<qreal> points;
44 QVector<qreal> points;
46 const QRectF& gridRect = gridGeometry();
45 const QRectF& gridRect = gridGeometry();
47 qreal range = max() - min();
46 qreal range = max() - min();
48 const qreal delta = gridRect.width() / range;
47 const qreal delta = gridRect.width() / range;
49
48
50 if (delta < 2)
49 if (delta < 2)
51 return points;
50 return points;
52
51
53 qreal adjustedMin = min() + 0.5;
52 qreal adjustedMin = min() + 0.5;
54 qreal offset = (ceil(adjustedMin) - adjustedMin) * delta;
53 qreal offset = (ceil(adjustedMin) - adjustedMin) * delta;
55
54
56 int count = qFloor(range);
55 int count = qFloor(range);
57 if (count < 1)
56 if (count < 1)
58 return points;
57 return points;
59
58
60 points.resize(count + 2);
59 points.resize(count + 2);
61
60
62 for (int i = 0; i < count + 2; ++i)
61 for (int i = 0; i < count + 2; ++i)
63 points[i] = offset + (qreal(i) * delta) + gridRect.left();
62 points[i] = offset + (qreal(i) * delta) + gridRect.left();
64
63
65 return points;
64 return points;
66 }
65 }
67
66
68 QStringList ChartBarCategoryAxisX::createCategoryLabels(const QVector<qreal>& layout) const
67 QStringList ChartBarCategoryAxisX::createCategoryLabels(const QVector<qreal>& layout) const
69 {
68 {
70 QStringList result ;
69 QStringList result ;
71 const QRectF &gridRect = gridGeometry();
70 const QRectF &gridRect = gridGeometry();
72 qreal d = (max() - min()) / gridRect.width();
71 qreal d = (max() - min()) / gridRect.width();
73
72
74 for (int i = 0; i < layout.count() - 1; ++i) {
73 for (int i = 0; i < layout.count() - 1; ++i) {
75 qreal x = qFloor((((layout[i] + layout[i + 1]) / 2 - gridRect.left()) * d + min() + 0.5));
74 qreal x = qFloor((((layout[i] + layout[i + 1]) / 2 - gridRect.left()) * d + min() + 0.5));
76 if ((x < m_categoriesAxis->categories().count()) && (x >= 0)) {
75 if ((x < m_categoriesAxis->categories().count()) && (x >= 0)) {
77 result << m_categoriesAxis->categories().at(x);
76 result << m_categoriesAxis->categories().at(x);
78 } else {
77 } else {
79 // No label for x coordinate
78 // No label for x coordinate
80 result << "";
79 result << "";
81 }
80 }
82 }
81 }
83 result << "";
82 result << "";
84 return result;
83 return result;
85 }
84 }
86
85
87
86
88 void ChartBarCategoryAxisX::updateGeometry()
87 void ChartBarCategoryAxisX::updateGeometry()
89 {
88 {
90 const QVector<qreal>& layout = ChartAxisElement::layout();
89 const QVector<qreal>& layout = ChartAxisElement::layout();
91 if (layout.isEmpty())
90 if (layout.isEmpty())
92 return;
91 return;
93 setLabels(createCategoryLabels(layout));
92 setLabels(createCategoryLabels(layout));
94 HorizontalAxis::updateGeometry();
93 HorizontalAxis::updateGeometry();
95 }
94 }
96
95
97 void ChartBarCategoryAxisX::handleCategoriesChanged()
96 void ChartBarCategoryAxisX::handleCategoriesChanged()
98 {
97 {
99 QGraphicsLayoutItem::updateGeometry();
98 QGraphicsLayoutItem::updateGeometry();
100 if(presenter()) presenter()->layout()->invalidate();
99 if(presenter()) presenter()->layout()->invalidate();
101 }
100 }
102
101
103 QSizeF ChartBarCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
102 QSizeF ChartBarCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
104 {
103 {
105 Q_UNUSED(constraint)
104 Q_UNUSED(constraint)
106
105
107 QFontMetrics fn(axis()->labelsFont());
108 QSizeF sh;
106 QSizeF sh;
109 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
107 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
110 QStringList ticksList = m_categoriesAxis->categories();
108 QStringList ticksList = m_categoriesAxis->categories();
111
109
112 qreal width = 0; // Width is irrelevant for X axes with interval labels
110 qreal width = 0; // Width is irrelevant for X axes with interval labels
113 qreal height = 0;
111 qreal height = 0;
114
112
115 switch (which) {
113 switch (which) {
116 case Qt::MinimumSize: {
114 case Qt::MinimumSize: {
117 QRectF boundingRect = labelBoundingRect(fn, "...");
115 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle());
118 height = boundingRect.height() + labelPadding();
116 height = boundingRect.height() + labelPadding() + base.height() + 1.0;
119 height += base.height();
120 sh = QSizeF(width, height);
117 sh = QSizeF(width, height);
121 break;
118 break;
122 }
119 }
123 case Qt::PreferredSize:{
120 case Qt::PreferredSize:{
124 int labelHeight = 0;
121 qreal labelHeight = 0.0;
125 foreach (const QString& s, ticksList) {
122 foreach (const QString& s, ticksList) {
126 QRect rect = labelBoundingRect(fn, s);
123 QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
127 labelHeight = qMax(rect.height(), labelHeight);
124 labelHeight = qMax(rect.height(), labelHeight);
128 }
125 }
129 height = labelHeight + labelPadding();
126 height = labelHeight + labelPadding() + base.height() + 1.0;
130 height += base.height();
131 sh = QSizeF(width, height);
127 sh = QSizeF(width, height);
132 break;
128 break;
133 }
129 }
134 default:
130 default:
135 break;
131 break;
136 }
132 }
137 return sh;
133 return sh;
138 }
134 }
139
135
140 #include "moc_chartbarcategoryaxisx_p.cpp"
136 #include "moc_chartbarcategoryaxisx_p.cpp"
141
137
142 QTCOMMERCIALCHART_END_NAMESPACE
138 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,144 +1,140
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartbarcategoryaxisy_p.h"
21 #include "chartbarcategoryaxisy_p.h"
22 #include "chartpresenter_p.h"
22 #include "chartpresenter_p.h"
23 #include "qbarcategoryaxis_p.h"
23 #include "qbarcategoryaxis_p.h"
24 #include "abstractchartlayout_p.h"
24 #include "abstractchartlayout_p.h"
25 #include <qmath.h>
25 #include <qmath.h>
26 #include <QFontMetrics>
27 #include <QDebug>
26 #include <QDebug>
28
27
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30
29
31 ChartBarCategoryAxisY::ChartBarCategoryAxisY(QBarCategoryAxis *axis, QGraphicsItem* item)
30 ChartBarCategoryAxisY::ChartBarCategoryAxisY(QBarCategoryAxis *axis, QGraphicsItem* item)
32 : VerticalAxis(axis, item, true),
31 : VerticalAxis(axis, item, true),
33 m_categoriesAxis(axis)
32 m_categoriesAxis(axis)
34 {
33 {
35 QObject::connect( m_categoriesAxis,SIGNAL(categoriesChanged()),this, SLOT(handleCategoriesChanged()));
34 QObject::connect( m_categoriesAxis,SIGNAL(categoriesChanged()),this, SLOT(handleCategoriesChanged()));
36 handleCategoriesChanged();
35 handleCategoriesChanged();
37 }
36 }
38
37
39 ChartBarCategoryAxisY::~ChartBarCategoryAxisY()
38 ChartBarCategoryAxisY::~ChartBarCategoryAxisY()
40 {
39 {
41 }
40 }
42
41
43 QVector<qreal> ChartBarCategoryAxisY::calculateLayout() const
42 QVector<qreal> ChartBarCategoryAxisY::calculateLayout() const
44 {
43 {
45 QVector<qreal> points;
44 QVector<qreal> points;
46 const QRectF& gridRect = gridGeometry();
45 const QRectF& gridRect = gridGeometry();
47 qreal range = max() - min();
46 qreal range = max() - min();
48 const qreal delta = gridRect.height() / range;
47 const qreal delta = gridRect.height() / range;
49
48
50 if (delta < 2)
49 if (delta < 2)
51 return points;
50 return points;
52
51
53 qreal adjustedMin = min() + 0.5;
52 qreal adjustedMin = min() + 0.5;
54 qreal offset = (ceil(adjustedMin) - adjustedMin) * delta;
53 qreal offset = (ceil(adjustedMin) - adjustedMin) * delta;
55
54
56 int count = qFloor(range);
55 int count = qFloor(range);
57 if (count < 1)
56 if (count < 1)
58 return points;
57 return points;
59
58
60 points.resize(count + 2);
59 points.resize(count + 2);
61
60
62 for (int i = 0; i < count + 2; ++i)
61 for (int i = 0; i < count + 2; ++i)
63 points[i] = gridRect.bottom() - (qreal(i) * delta) - offset;
62 points[i] = gridRect.bottom() - (qreal(i) * delta) - offset;
64
63
65 return points;
64 return points;
66 }
65 }
67
66
68 QStringList ChartBarCategoryAxisY::createCategoryLabels(const QVector<qreal>& layout) const
67 QStringList ChartBarCategoryAxisY::createCategoryLabels(const QVector<qreal>& layout) const
69 {
68 {
70 QStringList result;
69 QStringList result;
71 const QRectF &gridRect = gridGeometry();
70 const QRectF &gridRect = gridGeometry();
72 qreal d = (max() - min()) / gridRect.height();
71 qreal d = (max() - min()) / gridRect.height();
73
72
74 for (int i = 0; i < layout.count() - 1; ++i) {
73 for (int i = 0; i < layout.count() - 1; ++i) {
75 qreal x = qFloor(((gridRect.height() - (layout[i + 1] + layout[i]) / 2 + gridRect.top()) * d + min() + 0.5));
74 qreal x = qFloor(((gridRect.height() - (layout[i + 1] + layout[i]) / 2 + gridRect.top()) * d + min() + 0.5));
76 if ((x < m_categoriesAxis->categories().count()) && (x >= 0)) {
75 if ((x < m_categoriesAxis->categories().count()) && (x >= 0)) {
77 result << m_categoriesAxis->categories().at(x);
76 result << m_categoriesAxis->categories().at(x);
78 } else {
77 } else {
79 // No label for x coordinate
78 // No label for x coordinate
80 result << "";
79 result << "";
81 }
80 }
82 }
81 }
83 result << "";
82 result << "";
84 return result;
83 return result;
85 }
84 }
86
85
87 void ChartBarCategoryAxisY::updateGeometry()
86 void ChartBarCategoryAxisY::updateGeometry()
88 {
87 {
89 const QVector<qreal>& layout = ChartAxisElement::layout();
88 const QVector<qreal>& layout = ChartAxisElement::layout();
90 if (layout.isEmpty())
89 if (layout.isEmpty())
91 return;
90 return;
92 setLabels(createCategoryLabels(layout));
91 setLabels(createCategoryLabels(layout));
93 VerticalAxis::updateGeometry();
92 VerticalAxis::updateGeometry();
94 }
93 }
95
94
96 void ChartBarCategoryAxisY::handleCategoriesChanged()
95 void ChartBarCategoryAxisY::handleCategoriesChanged()
97 {
96 {
98 QGraphicsLayoutItem::updateGeometry();
97 QGraphicsLayoutItem::updateGeometry();
99 if(presenter()) presenter()->layout()->invalidate();
98 if(presenter()) presenter()->layout()->invalidate();
100 }
99 }
101
100
102 QSizeF ChartBarCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
101 QSizeF ChartBarCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
103 {
102 {
104 Q_UNUSED(constraint)
103 Q_UNUSED(constraint)
105
104
106 QFontMetrics fn(axis()->labelsFont());
107 QSizeF sh;
105 QSizeF sh;
108 QSizeF base = VerticalAxis::sizeHint(which, constraint);
106 QSizeF base = VerticalAxis::sizeHint(which, constraint);
109 QStringList ticksList = m_categoriesAxis->categories();
107 QStringList ticksList = m_categoriesAxis->categories();
110 qreal width = 0;
108 qreal width = 0;
111 qreal height = 0; // Height is irrelevant for Y axes with interval labels
109 qreal height = 0; // Height is irrelevant for Y axes with interval labels
112
110
113 switch (which) {
111 switch (which) {
114 case Qt::MinimumSize: {
112 case Qt::MinimumSize: {
115 QRectF boundingRect = labelBoundingRect(fn, "...");
113 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle());
116 width = boundingRect.width() + labelPadding();
114 width = boundingRect.width() + labelPadding() + base.width() + 1.0;
117 width += base.width();
115 if (base.width() > 0.0)
118 if (base.width() > 0)
119 width += labelPadding();
116 width += labelPadding();
120 sh = QSizeF(width, height);
117 sh = QSizeF(width, height);
121 break;
118 break;
122 }
119 }
123 case Qt::PreferredSize:{
120 case Qt::PreferredSize:{
124 int labelWidth = 0;
121 qreal labelWidth = 0.0;
125 foreach (const QString& s, ticksList) {
122 foreach (const QString& s, ticksList) {
126 QRect rect = labelBoundingRect(fn, s);
123 QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
127 labelWidth = qMax(rect.width(), labelWidth);
124 labelWidth = qMax(rect.width(), labelWidth);
128 }
125 }
129 width = labelWidth + labelPadding() + 1;
126 width = labelWidth + labelPadding() + base.width() + 1.0;
130 width += base.width();
127 if (base.width() > 0.0)
131 if (base.width() > 0)
132 width += labelPadding();
128 width += labelPadding();
133 sh = QSizeF(width, height);
129 sh = QSizeF(width, height);
134 break;
130 break;
135 }
131 }
136 default:
132 default:
137 break;
133 break;
138 }
134 }
139 return sh;
135 return sh;
140 }
136 }
141
137
142 #include "moc_chartbarcategoryaxisy_p.cpp"
138 #include "moc_chartbarcategoryaxisy_p.cpp"
143
139
144 QTCOMMERCIALCHART_END_NAMESPACE
140 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,122 +1,118
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartcategoryaxisx_p.h"
21 #include "chartcategoryaxisx_p.h"
22 #include "qcategoryaxis.h"
22 #include "qcategoryaxis.h"
23 #include "qabstractaxis.h"
23 #include "qabstractaxis.h"
24 #include "chartpresenter_p.h"
24 #include "chartpresenter_p.h"
25 #include "abstractchartlayout_p.h"
25 #include "abstractchartlayout_p.h"
26 #include <QGraphicsLayout>
26 #include <QGraphicsLayout>
27 #include <QFontMetrics>
28 #include <qmath.h>
27 #include <qmath.h>
29
28
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
30
32 ChartCategoryAxisX::ChartCategoryAxisX(QCategoryAxis *axis, QGraphicsItem* item)
31 ChartCategoryAxisX::ChartCategoryAxisX(QCategoryAxis *axis, QGraphicsItem* item)
33 : HorizontalAxis(axis, item, true),
32 : HorizontalAxis(axis, item, true),
34 m_axis(axis)
33 m_axis(axis)
35 {
34 {
36 QObject::connect(axis, SIGNAL(categoriesChanged()), this, SLOT(handleCategoriesChanged()));
35 QObject::connect(axis, SIGNAL(categoriesChanged()), this, SLOT(handleCategoriesChanged()));
37 }
36 }
38
37
39 ChartCategoryAxisX::~ChartCategoryAxisX()
38 ChartCategoryAxisX::~ChartCategoryAxisX()
40 {
39 {
41 }
40 }
42
41
43 QVector<qreal> ChartCategoryAxisX::calculateLayout() const
42 QVector<qreal> ChartCategoryAxisX::calculateLayout() const
44 {
43 {
45 int tickCount = m_axis->categoriesLabels().count() + 1;
44 int tickCount = m_axis->categoriesLabels().count() + 1;
46 QVector<qreal> points;
45 QVector<qreal> points;
47
46
48 if (tickCount < 2)
47 if (tickCount < 2)
49 return points;
48 return points;
50
49
51 const QRectF &gridRect = gridGeometry();
50 const QRectF &gridRect = gridGeometry();
52 qreal range = max() - min();
51 qreal range = max() - min();
53 if (range > 0) {
52 if (range > 0) {
54 points.resize(tickCount);
53 points.resize(tickCount);
55 qreal scale = gridRect.width() / range;
54 qreal scale = gridRect.width() / range;
56 for (int i = 0; i < tickCount; ++i) {
55 for (int i = 0; i < tickCount; ++i) {
57 if (i < tickCount - 1) {
56 if (i < tickCount - 1) {
58 qreal x = (m_axis->startValue(m_axis->categoriesLabels().at(i)) - min()) * scale + gridRect.left();
57 qreal x = (m_axis->startValue(m_axis->categoriesLabels().at(i)) - min()) * scale + gridRect.left();
59 points[i] = x;
58 points[i] = x;
60 } else {
59 } else {
61 qreal x = (m_axis->endValue(m_axis->categoriesLabels().at(i - 1)) - min()) * scale + gridRect.left();
60 qreal x = (m_axis->endValue(m_axis->categoriesLabels().at(i - 1)) - min()) * scale + gridRect.left();
62 points[i] = x;
61 points[i] = x;
63 }
62 }
64 }
63 }
65 }
64 }
66
65
67 return points;
66 return points;
68 }
67 }
69
68
70 void ChartCategoryAxisX::updateGeometry()
69 void ChartCategoryAxisX::updateGeometry()
71 {
70 {
72 //TODO: this is not optimal when many categories :( , create only visible lables
71 //TODO: this is not optimal when many categories :( , create only visible lables
73 setLabels(m_axis->categoriesLabels() << "");
72 setLabels(m_axis->categoriesLabels() << "");
74 HorizontalAxis::updateGeometry();
73 HorizontalAxis::updateGeometry();
75 }
74 }
76
75
77 QSizeF ChartCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
76 QSizeF ChartCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
78 {
77 {
79 Q_UNUSED(constraint)
78 Q_UNUSED(constraint)
80
79
81 QFontMetrics fn(axis()->labelsFont());
82 QSizeF sh;
80 QSizeF sh;
83 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
81 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
84 QStringList ticksList = m_axis->categoriesLabels();
82 QStringList ticksList = m_axis->categoriesLabels();
85 qreal width = 0; // Width is irrelevant for X axes with interval labels
83 qreal width = 0; // Width is irrelevant for X axes with interval labels
86 qreal height = 0;
84 qreal height = 0;
87
85
88 switch (which) {
86 switch (which) {
89 case Qt::MinimumSize: {
87 case Qt::MinimumSize: {
90 QRectF boundingRect = labelBoundingRect(fn, "...");
88 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle());
91 height = boundingRect.height() + labelPadding();
89 height = boundingRect.height() + labelPadding() + base.height() + 1.0;
92 height += base.height();
93 sh = QSizeF(width, height);
90 sh = QSizeF(width, height);
94 break;
91 break;
95 }
92 }
96 case Qt::PreferredSize: {
93 case Qt::PreferredSize: {
97 int labelHeight = 0;
94 qreal labelHeight = 0.0;
98 foreach (const QString& s, ticksList) {
95 foreach (const QString& s, ticksList) {
99 QRect rect = labelBoundingRect(fn, s);
96 QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
100 labelHeight = qMax(rect.height(), labelHeight);
97 labelHeight = qMax(rect.height(), labelHeight);
101 }
98 }
102 height = labelHeight + labelPadding();
99 height = labelHeight + labelPadding() + base.height() + 1.0;
103 height += base.height();
104 sh = QSizeF(width, height);
100 sh = QSizeF(width, height);
105 break;
101 break;
106 }
102 }
107 default:
103 default:
108 break;
104 break;
109 }
105 }
110
106
111 return sh;
107 return sh;
112 }
108 }
113
109
114 void ChartCategoryAxisX::handleCategoriesChanged()
110 void ChartCategoryAxisX::handleCategoriesChanged()
115 {
111 {
116 QGraphicsLayoutItem::updateGeometry();
112 QGraphicsLayoutItem::updateGeometry();
117 presenter()->layout()->invalidate();
113 presenter()->layout()->invalidate();
118 }
114 }
119
115
120 #include "moc_chartcategoryaxisx_p.cpp"
116 #include "moc_chartcategoryaxisx_p.cpp"
121
117
122 QTCOMMERCIALCHART_END_NAMESPACE
118 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,121 +1,117
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartcategoryaxisy_p.h"
21 #include "chartcategoryaxisy_p.h"
22 #include "qcategoryaxis.h"
22 #include "qcategoryaxis.h"
23 #include "qabstractaxis.h"
23 #include "qabstractaxis.h"
24 #include "chartpresenter_p.h"
24 #include "chartpresenter_p.h"
25 #include "abstractchartlayout_p.h"
25 #include "abstractchartlayout_p.h"
26 #include <QGraphicsLayout>
26 #include <QGraphicsLayout>
27 #include <QFontMetrics>
28 #include <qmath.h>
27 #include <qmath.h>
29 #include <QDebug>
28 #include <QDebug>
30
29
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32
31
33 ChartCategoryAxisY::ChartCategoryAxisY(QCategoryAxis *axis, QGraphicsItem* item)
32 ChartCategoryAxisY::ChartCategoryAxisY(QCategoryAxis *axis, QGraphicsItem* item)
34 : VerticalAxis(axis, item, true),
33 : VerticalAxis(axis, item, true),
35 m_axis(axis)
34 m_axis(axis)
36 {
35 {
37 QObject::connect(axis, SIGNAL(categoriesChanged()), this, SLOT(handleCategoriesChanged()));
36 QObject::connect(axis, SIGNAL(categoriesChanged()), this, SLOT(handleCategoriesChanged()));
38 }
37 }
39
38
40 ChartCategoryAxisY::~ChartCategoryAxisY()
39 ChartCategoryAxisY::~ChartCategoryAxisY()
41 {
40 {
42 }
41 }
43
42
44 QVector<qreal> ChartCategoryAxisY::calculateLayout() const
43 QVector<qreal> ChartCategoryAxisY::calculateLayout() const
45 {
44 {
46 int tickCount = m_axis->categoriesLabels().count() + 1;
45 int tickCount = m_axis->categoriesLabels().count() + 1;
47 QVector<qreal> points;
46 QVector<qreal> points;
48
47
49 if (tickCount < 2)
48 if (tickCount < 2)
50 return points;
49 return points;
51
50
52 const QRectF &gridRect = gridGeometry();
51 const QRectF &gridRect = gridGeometry();
53 qreal range = max() - min();
52 qreal range = max() - min();
54 if (range > 0) {
53 if (range > 0) {
55 points.resize(tickCount);
54 points.resize(tickCount);
56 qreal scale = gridRect.height() / range;
55 qreal scale = gridRect.height() / range;
57 for (int i = 0; i < tickCount; ++i) {
56 for (int i = 0; i < tickCount; ++i) {
58 if (i < tickCount - 1) {
57 if (i < tickCount - 1) {
59 qreal y = -(m_axis->startValue(m_axis->categoriesLabels().at(i)) - min()) * scale + gridRect.bottom();
58 qreal y = -(m_axis->startValue(m_axis->categoriesLabels().at(i)) - min()) * scale + gridRect.bottom();
60 points[i] = y;
59 points[i] = y;
61 } else {
60 } else {
62 qreal y = -(m_axis->endValue(m_axis->categoriesLabels().at(i - 1)) - min()) * scale + gridRect.bottom();
61 qreal y = -(m_axis->endValue(m_axis->categoriesLabels().at(i - 1)) - min()) * scale + gridRect.bottom();
63 points[i] = y;
62 points[i] = y;
64 }
63 }
65 }
64 }
66 }
65 }
67
66
68 return points;
67 return points;
69 }
68 }
70
69
71 void ChartCategoryAxisY::updateGeometry()
70 void ChartCategoryAxisY::updateGeometry()
72 {
71 {
73 setLabels(m_axis->categoriesLabels() << "");
72 setLabels(m_axis->categoriesLabels() << "");
74 VerticalAxis::updateGeometry();
73 VerticalAxis::updateGeometry();
75 }
74 }
76
75
77 QSizeF ChartCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
76 QSizeF ChartCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
78 {
77 {
79 Q_UNUSED(constraint)
78 Q_UNUSED(constraint)
80
79
81 QFontMetrics fn(axis()->labelsFont());
82 QSizeF sh;
80 QSizeF sh;
83 QSizeF base = VerticalAxis::sizeHint(which, constraint);
81 QSizeF base = VerticalAxis::sizeHint(which, constraint);
84 QStringList ticksList = m_axis->categoriesLabels();
82 QStringList ticksList = m_axis->categoriesLabels();
85 qreal width = 0;
83 qreal width = 0;
86 qreal height = 0; // Height is irrelevant for Y axes with interval labels
84 qreal height = 0; // Height is irrelevant for Y axes with interval labels
87
85
88 switch (which) {
86 switch (which) {
89 case Qt::MinimumSize: {
87 case Qt::MinimumSize: {
90 QRectF boundingRect = labelBoundingRect(fn, "...");
88 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle());
91 width = boundingRect.width() + labelPadding();
89 width = boundingRect.width() + labelPadding() + base.width() + 1.0;
92 width += base.width();
93 sh = QSizeF(width, height);
90 sh = QSizeF(width, height);
94 break;
91 break;
95 }
92 }
96 case Qt::PreferredSize: {
93 case Qt::PreferredSize: {
97 int labelWidth = 0;
94 qreal labelWidth = 0.0;
98 foreach (const QString& s, ticksList) {
95 foreach (const QString& s, ticksList) {
99 QRect rect = labelBoundingRect(fn, s);
96 QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
100 labelWidth = qMax(rect.width(), labelWidth);
97 labelWidth = qMax(rect.width(), labelWidth);
101 }
98 }
102 width = labelWidth + labelPadding() + 1;
99 width = labelWidth + labelPadding() + base.width() + 1.0;
103 width += base.width();
104 sh = QSizeF(width, height);
100 sh = QSizeF(width, height);
105 break;
101 break;
106 }
102 }
107 default:
103 default:
108 break;
104 break;
109 }
105 }
110 return sh;
106 return sh;
111 }
107 }
112
108
113 void ChartCategoryAxisY::handleCategoriesChanged()
109 void ChartCategoryAxisY::handleCategoriesChanged()
114 {
110 {
115 QGraphicsLayoutItem::updateGeometry();
111 QGraphicsLayoutItem::updateGeometry();
116 presenter()->layout()->invalidate();
112 presenter()->layout()->invalidate();
117 }
113 }
118
114
119 #include "moc_chartcategoryaxisy_p.cpp"
115 #include "moc_chartcategoryaxisy_p.cpp"
120
116
121 QTCOMMERCIALCHART_END_NAMESPACE
117 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,349 +1,384
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartaxiselement_p.h"
21 #include "chartaxiselement_p.h"
22 #include "qabstractaxis_p.h"
22 #include "qabstractaxis_p.h"
23 #include "chartpresenter_p.h"
23 #include "chartpresenter_p.h"
24 #include "abstractchartlayout_p.h"
24 #include "abstractchartlayout_p.h"
25 #include <qmath.h>
25 #include <qmath.h>
26 #include <QDateTime>
26 #include <QDateTime>
27 #include <QFontMetrics>
28
27
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30
29
30 QGraphicsSimpleTextItem *dummyTextItem = 0;
31 class StaticDeleter
32 {
33 public:
34 StaticDeleter() {}
35 ~StaticDeleter() { delete dummyTextItem; }
36 };
37 StaticDeleter staticDeleter;
38
31 ChartAxisElement::ChartAxisElement(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
39 ChartAxisElement::ChartAxisElement(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
32 : ChartElement(item),
40 : ChartElement(item),
33 m_axis(axis),
41 m_axis(axis),
34 m_animation(0),
42 m_animation(0),
35 m_grid(new QGraphicsItemGroup(item)),
43 m_grid(new QGraphicsItemGroup(item)),
36 m_arrow(new QGraphicsItemGroup(item)),
44 m_arrow(new QGraphicsItemGroup(item)),
37 m_shades(new QGraphicsItemGroup(item)),
45 m_shades(new QGraphicsItemGroup(item)),
38 m_labels(new QGraphicsItemGroup(item)),
46 m_labels(new QGraphicsItemGroup(item)),
39 m_title(new QGraphicsSimpleTextItem(item)),
47 m_title(new QGraphicsSimpleTextItem(item)),
40 m_intervalAxis(intervalAxis)
48 m_intervalAxis(intervalAxis)
41
49
42 {
50 {
43 //initial initialization
51 //initial initialization
52 if (!dummyTextItem)
53 dummyTextItem = new QGraphicsSimpleTextItem;
44 m_arrow->setHandlesChildEvents(false);
54 m_arrow->setHandlesChildEvents(false);
45 m_arrow->setZValue(ChartPresenter::AxisZValue);
55 m_arrow->setZValue(ChartPresenter::AxisZValue);
46 m_labels->setZValue(ChartPresenter::AxisZValue);
56 m_labels->setZValue(ChartPresenter::AxisZValue);
47 m_shades->setZValue(ChartPresenter::ShadesZValue);
57 m_shades->setZValue(ChartPresenter::ShadesZValue);
48 m_grid->setZValue(ChartPresenter::GridZValue);
58 m_grid->setZValue(ChartPresenter::GridZValue);
49 m_title->setZValue(ChartPresenter::GridZValue);
59 m_title->setZValue(ChartPresenter::GridZValue);
50 handleVisibleChanged(axis->isVisible());
60 handleVisibleChanged(axis->isVisible());
51 connectSlots();
61 connectSlots();
52
62
53 setFlag(QGraphicsItem::ItemHasNoContents, true);
63 setFlag(QGraphicsItem::ItemHasNoContents, true);
54 }
64 }
55
65
56 ChartAxisElement::~ChartAxisElement()
66 ChartAxisElement::~ChartAxisElement()
57 {
67 {
58 }
68 }
59
69
60 void ChartAxisElement::connectSlots()
70 void ChartAxisElement::connectSlots()
61 {
71 {
62 QObject::connect(axis(), SIGNAL(visibleChanged(bool)), this, SLOT(handleVisibleChanged(bool)));
72 QObject::connect(axis(), SIGNAL(visibleChanged(bool)), this, SLOT(handleVisibleChanged(bool)));
63 QObject::connect(axis(), SIGNAL(lineVisibleChanged(bool)), this, SLOT(handleArrowVisibleChanged(bool)));
73 QObject::connect(axis(), SIGNAL(lineVisibleChanged(bool)), this, SLOT(handleArrowVisibleChanged(bool)));
64 QObject::connect(axis(), SIGNAL(gridVisibleChanged(bool)), this, SLOT(handleGridVisibleChanged(bool)));
74 QObject::connect(axis(), SIGNAL(gridVisibleChanged(bool)), this, SLOT(handleGridVisibleChanged(bool)));
65 QObject::connect(axis(), SIGNAL(labelsVisibleChanged(bool)), this, SLOT(handleLabelsVisibleChanged(bool)));
75 QObject::connect(axis(), SIGNAL(labelsVisibleChanged(bool)), this, SLOT(handleLabelsVisibleChanged(bool)));
66 QObject::connect(axis(), SIGNAL(shadesVisibleChanged(bool)), this, SLOT(handleShadesVisibleChanged(bool)));
76 QObject::connect(axis(), SIGNAL(shadesVisibleChanged(bool)), this, SLOT(handleShadesVisibleChanged(bool)));
67 QObject::connect(axis(), SIGNAL(labelsAngleChanged(int)), this, SLOT(handleLabelsAngleChanged(int)));
77 QObject::connect(axis(), SIGNAL(labelsAngleChanged(int)), this, SLOT(handleLabelsAngleChanged(int)));
68 QObject::connect(axis(), SIGNAL(linePenChanged(const QPen&)), this, SLOT(handleArrowPenChanged(const QPen&)));
78 QObject::connect(axis(), SIGNAL(linePenChanged(const QPen&)), this, SLOT(handleArrowPenChanged(const QPen&)));
69 QObject::connect(axis(), SIGNAL(labelsPenChanged(const QPen&)), this, SLOT(handleLabelsPenChanged(const QPen&)));
79 QObject::connect(axis(), SIGNAL(labelsPenChanged(const QPen&)), this, SLOT(handleLabelsPenChanged(const QPen&)));
70 QObject::connect(axis(), SIGNAL(labelsBrushChanged(const QBrush&)), this, SLOT(handleLabelsBrushChanged(const QBrush&)));
80 QObject::connect(axis(), SIGNAL(labelsBrushChanged(const QBrush&)), this, SLOT(handleLabelsBrushChanged(const QBrush&)));
71 QObject::connect(axis(), SIGNAL(labelsFontChanged(const QFont&)), this, SLOT(handleLabelsFontChanged(const QFont&)));
81 QObject::connect(axis(), SIGNAL(labelsFontChanged(const QFont&)), this, SLOT(handleLabelsFontChanged(const QFont&)));
72 QObject::connect(axis(), SIGNAL(gridLinePenChanged(const QPen&)), this, SLOT(handleGridPenChanged(const QPen&)));
82 QObject::connect(axis(), SIGNAL(gridLinePenChanged(const QPen&)), this, SLOT(handleGridPenChanged(const QPen&)));
73 QObject::connect(axis(), SIGNAL(shadesPenChanged(const QPen&)), this, SLOT(handleShadesPenChanged(const QPen&)));
83 QObject::connect(axis(), SIGNAL(shadesPenChanged(const QPen&)), this, SLOT(handleShadesPenChanged(const QPen&)));
74 QObject::connect(axis(), SIGNAL(shadesBrushChanged(const QBrush&)), this, SLOT(handleShadesBrushChanged(const QBrush&)));
84 QObject::connect(axis(), SIGNAL(shadesBrushChanged(const QBrush&)), this, SLOT(handleShadesBrushChanged(const QBrush&)));
75 QObject::connect(axis(), SIGNAL(titleTextChanged(const QString&)), this, SLOT(handleTitleTextChanged(const QString&)));
85 QObject::connect(axis(), SIGNAL(titleTextChanged(const QString&)), this, SLOT(handleTitleTextChanged(const QString&)));
76 QObject::connect(axis(), SIGNAL(titleFontChanged(const QFont&)), this, SLOT(handleTitleFontChanged(const QFont&)));
86 QObject::connect(axis(), SIGNAL(titleFontChanged(const QFont&)), this, SLOT(handleTitleFontChanged(const QFont&)));
77 QObject::connect(axis(), SIGNAL(titlePenChanged(const QPen&)), this, SLOT(handleTitlePenChanged(const QPen&)));
87 QObject::connect(axis(), SIGNAL(titlePenChanged(const QPen&)), this, SLOT(handleTitlePenChanged(const QPen&)));
78 QObject::connect(axis(), SIGNAL(titleBrushChanged(const QBrush&)), this, SLOT(handleTitleBrushChanged(const QBrush&)));
88 QObject::connect(axis(), SIGNAL(titleBrushChanged(const QBrush&)), this, SLOT(handleTitleBrushChanged(const QBrush&)));
79 QObject::connect(axis(), SIGNAL(titleVisibleChanged(bool)), this, SLOT(handleTitleVisibleChanged(bool)));
89 QObject::connect(axis(), SIGNAL(titleVisibleChanged(bool)), this, SLOT(handleTitleVisibleChanged(bool)));
80 QObject::connect(axis()->d_ptr.data(), SIGNAL(rangeChanged(qreal, qreal)), this, SLOT(handleRangeChanged(qreal, qreal)));
90 QObject::connect(axis()->d_ptr.data(), SIGNAL(rangeChanged(qreal, qreal)), this, SLOT(handleRangeChanged(qreal, qreal)));
81 }
91 }
82
92
83 void ChartAxisElement::handleArrowVisibleChanged(bool visible)
93 void ChartAxisElement::handleArrowVisibleChanged(bool visible)
84 {
94 {
85 m_arrow->setVisible(visible);
95 m_arrow->setVisible(visible);
86 }
96 }
87
97
88 void ChartAxisElement::handleGridVisibleChanged(bool visible)
98 void ChartAxisElement::handleGridVisibleChanged(bool visible)
89 {
99 {
90 m_grid->setVisible(visible);
100 m_grid->setVisible(visible);
91 }
101 }
92
102
93 void ChartAxisElement::handleLabelsVisibleChanged(bool visible)
103 void ChartAxisElement::handleLabelsVisibleChanged(bool visible)
94 {
104 {
95 QGraphicsLayoutItem::updateGeometry();
105 QGraphicsLayoutItem::updateGeometry();
96 presenter()->layout()->invalidate();
106 presenter()->layout()->invalidate();
97 m_labels->setVisible(visible);
107 m_labels->setVisible(visible);
98 }
108 }
99
109
100 void ChartAxisElement::handleShadesVisibleChanged(bool visible)
110 void ChartAxisElement::handleShadesVisibleChanged(bool visible)
101 {
111 {
102 m_shades->setVisible(visible);
112 m_shades->setVisible(visible);
103 }
113 }
104
114
105 void ChartAxisElement::handleTitleVisibleChanged(bool visible)
115 void ChartAxisElement::handleTitleVisibleChanged(bool visible)
106 {
116 {
107 QGraphicsLayoutItem::updateGeometry();
117 QGraphicsLayoutItem::updateGeometry();
108 presenter()->layout()->invalidate();
118 presenter()->layout()->invalidate();
109 m_title->setVisible(visible);
119 m_title->setVisible(visible);
110 }
120 }
111
121
112 void ChartAxisElement::handleLabelsAngleChanged(int angle)
122 void ChartAxisElement::handleLabelsAngleChanged(int angle)
113 {
123 {
114 foreach (QGraphicsItem *item, m_labels->childItems())
124 foreach (QGraphicsItem *item, m_labels->childItems())
115 item->setRotation(angle);
125 item->setRotation(angle);
116
126
117 QGraphicsLayoutItem::updateGeometry();
127 QGraphicsLayoutItem::updateGeometry();
118 presenter()->layout()->invalidate();
128 presenter()->layout()->invalidate();
119 }
129 }
120
130
121 void ChartAxisElement::handleLabelsPenChanged(const QPen &pen)
131 void ChartAxisElement::handleLabelsPenChanged(const QPen &pen)
122 {
132 {
123 foreach (QGraphicsItem *item, m_labels->childItems())
133 foreach (QGraphicsItem *item, m_labels->childItems())
124 static_cast<QGraphicsSimpleTextItem *>(item)->setPen(pen);
134 static_cast<QGraphicsSimpleTextItem *>(item)->setPen(pen);
125 }
135 }
126
136
127 void ChartAxisElement::handleLabelsBrushChanged(const QBrush &brush)
137 void ChartAxisElement::handleLabelsBrushChanged(const QBrush &brush)
128 {
138 {
129 foreach (QGraphicsItem *item, m_labels->childItems())
139 foreach (QGraphicsItem *item, m_labels->childItems())
130 static_cast<QGraphicsSimpleTextItem *>(item)->setBrush(brush);
140 static_cast<QGraphicsSimpleTextItem *>(item)->setBrush(brush);
131 }
141 }
132
142
133 void ChartAxisElement::handleLabelsFontChanged(const QFont &font)
143 void ChartAxisElement::handleLabelsFontChanged(const QFont &font)
134 {
144 {
135 foreach (QGraphicsItem *item, m_labels->childItems())
145 foreach (QGraphicsItem *item, m_labels->childItems())
136 static_cast<QGraphicsSimpleTextItem *>(item)->setFont(font);
146 static_cast<QGraphicsSimpleTextItem *>(item)->setFont(font);
137 QGraphicsLayoutItem::updateGeometry();
147 QGraphicsLayoutItem::updateGeometry();
138 presenter()->layout()->invalidate();
148 presenter()->layout()->invalidate();
139 }
149 }
140
150
141 void ChartAxisElement::handleTitleTextChanged(const QString &title)
151 void ChartAxisElement::handleTitleTextChanged(const QString &title)
142 {
152 {
143 QGraphicsLayoutItem::updateGeometry();
153 QGraphicsLayoutItem::updateGeometry();
144 presenter()->layout()->invalidate();
154 presenter()->layout()->invalidate();
145 m_title->setText(title);
155 m_title->setText(title);
146 }
156 }
147
157
148 void ChartAxisElement::handleTitlePenChanged(const QPen &pen)
158 void ChartAxisElement::handleTitlePenChanged(const QPen &pen)
149 {
159 {
150 m_title->setPen(pen);
160 m_title->setPen(pen);
151 }
161 }
152
162
153 void ChartAxisElement::handleTitleBrushChanged(const QBrush &brush)
163 void ChartAxisElement::handleTitleBrushChanged(const QBrush &brush)
154 {
164 {
155 m_title->setBrush(brush);
165 m_title->setBrush(brush);
156 }
166 }
157
167
158 void ChartAxisElement::handleTitleFontChanged(const QFont &font)
168 void ChartAxisElement::handleTitleFontChanged(const QFont &font)
159 {
169 {
160 if (m_title->font() != font) {
170 if (m_title->font() != font) {
161 m_title->setFont(font);
171 m_title->setFont(font);
162 QGraphicsLayoutItem::updateGeometry();
172 QGraphicsLayoutItem::updateGeometry();
163 presenter()->layout()->invalidate();
173 presenter()->layout()->invalidate();
164 }
174 }
165 }
175 }
166
176
167 void ChartAxisElement::handleVisibleChanged(bool visible)
177 void ChartAxisElement::handleVisibleChanged(bool visible)
168 {
178 {
169 setVisible(visible);
179 setVisible(visible);
170 if (!visible) {
180 if (!visible) {
171 m_grid->setVisible(visible);
181 m_grid->setVisible(visible);
172 m_arrow->setVisible(visible);
182 m_arrow->setVisible(visible);
173 m_shades->setVisible(visible);
183 m_shades->setVisible(visible);
174 m_labels->setVisible(visible);
184 m_labels->setVisible(visible);
175 m_title->setVisible(visible);
185 m_title->setVisible(visible);
176 } else {
186 } else {
177 m_grid->setVisible(axis()->isGridLineVisible());
187 m_grid->setVisible(axis()->isGridLineVisible());
178 m_arrow->setVisible(axis()->isLineVisible());
188 m_arrow->setVisible(axis()->isLineVisible());
179 m_shades->setVisible(axis()->shadesVisible());
189 m_shades->setVisible(axis()->shadesVisible());
180 m_labels->setVisible(axis()->labelsVisible());
190 m_labels->setVisible(axis()->labelsVisible());
181 m_title->setVisible(axis()->isTitleVisible());
191 m_title->setVisible(axis()->isTitleVisible());
182 }
192 }
183
193
184 if (presenter()) presenter()->layout()->invalidate();
194 if (presenter()) presenter()->layout()->invalidate();
185 }
195 }
186
196
187 QRect ChartAxisElement::labelBoundingRect(const QFontMetrics &fn, const QString &label) const
197 QRectF ChartAxisElement::textBoundingRect(const QFont &font, const QString &text, qreal angle) const
188 {
198 {
189 QRect boundingRect = fn.boundingRect(label);
199 dummyTextItem->setFont(font);
190 // Take label rotation into account
200 dummyTextItem->setText(text);
191 if (axis()->labelsAngle()) {
201 QRectF boundingRect = dummyTextItem->boundingRect();
202
203 // Take rotation into account
204 if (angle) {
192 QTransform transform;
205 QTransform transform;
193 transform.rotate(axis()->labelsAngle());
206 transform.rotate(angle);
194 boundingRect = transform.mapRect(boundingRect);
207 boundingRect = transform.mapRect(boundingRect);
195 }
208 }
196
209
197 return boundingRect;
210 return boundingRect;
198 }
211 }
199
212
213 // boundingRect parameter returns the rotated bounding rect of the text
214 QString ChartAxisElement::truncatedText(const QFont &font, const QString &text, qreal angle,
215 qreal maxSize, Qt::Orientation constraintOrientation,
216 QRectF &boundingRect) const
217 {
218 QString truncatedString(text);
219 boundingRect = textBoundingRect(font, truncatedString, angle);
220 qreal checkDimension = ((constraintOrientation == Qt::Horizontal)
221 ? boundingRect.width() : boundingRect.height());
222 if (checkDimension > maxSize) {
223 truncatedString.append("...");
224 while (checkDimension > maxSize && truncatedString.length() > 3) {
225 truncatedString.remove(truncatedString.length() - 4, 1);
226 boundingRect = textBoundingRect(font, truncatedString, angle);
227 checkDimension = ((constraintOrientation == Qt::Horizontal)
228 ? boundingRect.width() : boundingRect.height());
229 }
230 }
231
232 return truncatedString;
233 }
234
200 void ChartAxisElement::handleRangeChanged(qreal min, qreal max)
235 void ChartAxisElement::handleRangeChanged(qreal min, qreal max)
201 {
236 {
202 Q_UNUSED(min);
237 Q_UNUSED(min);
203 Q_UNUSED(max);
238 Q_UNUSED(max);
204
239
205 if (!isEmpty()) {
240 if (!isEmpty()) {
206 QVector<qreal> layout = calculateLayout();
241 QVector<qreal> layout = calculateLayout();
207 updateLayout(layout);
242 updateLayout(layout);
208 QSizeF before = effectiveSizeHint(Qt::PreferredSize);
243 QSizeF before = effectiveSizeHint(Qt::PreferredSize);
209 QSizeF after = sizeHint(Qt::PreferredSize);
244 QSizeF after = sizeHint(Qt::PreferredSize);
210
245
211 if (before != after) {
246 if (before != after) {
212 QGraphicsLayoutItem::updateGeometry();
247 QGraphicsLayoutItem::updateGeometry();
213 // We don't want to call invalidate on layout, since it will change minimum size of
248 // We don't want to call invalidate on layout, since it will change minimum size of
214 // component, which we would like to avoid since it causes nasty flips when scrolling
249 // component, which we would like to avoid since it causes nasty flips when scrolling
215 // or zooming, instead recalculate layout and use plotArea for extra space.
250 // or zooming, instead recalculate layout and use plotArea for extra space.
216 presenter()->layout()->setGeometry(presenter()->layout()->geometry());
251 presenter()->layout()->setGeometry(presenter()->layout()->geometry());
217 }
252 }
218 }
253 }
219 }
254 }
220
255
221 bool ChartAxisElement::isEmpty()
256 bool ChartAxisElement::isEmpty()
222 {
257 {
223 return axisGeometry().isEmpty()
258 return axisGeometry().isEmpty()
224 || gridGeometry().isEmpty()
259 || gridGeometry().isEmpty()
225 || qFuzzyCompare(min(), max());
260 || qFuzzyCompare(min(), max());
226 }
261 }
227
262
228 qreal ChartAxisElement::min() const
263 qreal ChartAxisElement::min() const
229 {
264 {
230 return m_axis->d_ptr->min();
265 return m_axis->d_ptr->min();
231 }
266 }
232
267
233 qreal ChartAxisElement::max() const
268 qreal ChartAxisElement::max() const
234 {
269 {
235 return m_axis->d_ptr->max();
270 return m_axis->d_ptr->max();
236 }
271 }
237
272
238 QStringList ChartAxisElement::createValueLabels(qreal min, qreal max, int ticks, const QString &format)
273 QStringList ChartAxisElement::createValueLabels(qreal min, qreal max, int ticks, const QString &format)
239 {
274 {
240 QStringList labels;
275 QStringList labels;
241
276
242 if (max <= min || ticks < 1)
277 if (max <= min || ticks < 1)
243 return labels;
278 return labels;
244
279
245 int n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0);
280 int n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0);
246 n++;
281 n++;
247
282
248 if (format.isNull()) {
283 if (format.isNull()) {
249 for (int i = 0; i < ticks; i++) {
284 for (int i = 0; i < ticks; i++) {
250 qreal value = min + (i * (max - min) / (ticks - 1));
285 qreal value = min + (i * (max - min) / (ticks - 1));
251 labels << QString::number(value, 'f', n);
286 labels << QString::number(value, 'f', n);
252 }
287 }
253 } else {
288 } else {
254 QByteArray array = format.toLatin1();
289 QByteArray array = format.toLatin1();
255 for (int i = 0; i < ticks; i++) {
290 for (int i = 0; i < ticks; i++) {
256 qreal value = min + (i * (max - min) / (ticks - 1));
291 qreal value = min + (i * (max - min) / (ticks - 1));
257 if (format.contains("d")
292 if (format.contains("d")
258 || format.contains("i")
293 || format.contains("i")
259 || format.contains("c")) {
294 || format.contains("c")) {
260 labels << QString().sprintf(array, (qint64)value);
295 labels << QString().sprintf(array, (qint64)value);
261 } else if (format.contains("u")
296 } else if (format.contains("u")
262 || format.contains("o")
297 || format.contains("o")
263 || format.contains("x", Qt::CaseInsensitive)) {
298 || format.contains("x", Qt::CaseInsensitive)) {
264 labels << QString().sprintf(array, (quint64)value);
299 labels << QString().sprintf(array, (quint64)value);
265 } else if (format.contains("f", Qt::CaseInsensitive)
300 } else if (format.contains("f", Qt::CaseInsensitive)
266 || format.contains("e", Qt::CaseInsensitive)
301 || format.contains("e", Qt::CaseInsensitive)
267 || format.contains("g", Qt::CaseInsensitive)) {
302 || format.contains("g", Qt::CaseInsensitive)) {
268 labels << QString().sprintf(array, value);
303 labels << QString().sprintf(array, value);
269 } else {
304 } else {
270 labels << QString();
305 labels << QString();
271 }
306 }
272 }
307 }
273 }
308 }
274
309
275 return labels;
310 return labels;
276 }
311 }
277
312
278 QStringList ChartAxisElement::createLogValueLabels(qreal min, qreal max, qreal base, int ticks, const QString &format)
313 QStringList ChartAxisElement::createLogValueLabels(qreal min, qreal max, qreal base, int ticks, const QString &format)
279 {
314 {
280 QStringList labels;
315 QStringList labels;
281
316
282 if (max <= min || ticks < 1)
317 if (max <= min || ticks < 1)
283 return labels;
318 return labels;
284
319
285 int n = 0;
320 int n = 0;
286 if (ticks > 1)
321 if (ticks > 1)
287 n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0);
322 n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0);
288 n++;
323 n++;
289
324
290 int firstTick;
325 int firstTick;
291 if (base > 1)
326 if (base > 1)
292 firstTick = ceil(log10(min) / log10(base));
327 firstTick = ceil(log10(min) / log10(base));
293 else
328 else
294 firstTick = ceil(log10(max) / log10(base));
329 firstTick = ceil(log10(max) / log10(base));
295
330
296 if (format.isNull()) {
331 if (format.isNull()) {
297 for (int i = firstTick; i < ticks + firstTick; i++) {
332 for (int i = firstTick; i < ticks + firstTick; i++) {
298 qreal value = qPow(base, i);
333 qreal value = qPow(base, i);
299 labels << QString::number(value, 'f', n);
334 labels << QString::number(value, 'f', n);
300 }
335 }
301 } else {
336 } else {
302 QByteArray array = format.toLatin1();
337 QByteArray array = format.toLatin1();
303 for (int i = firstTick; i < ticks + firstTick; i++) {
338 for (int i = firstTick; i < ticks + firstTick; i++) {
304 qreal value = qPow(base, i);
339 qreal value = qPow(base, i);
305 if (format.contains("d")
340 if (format.contains("d")
306 || format.contains("i")
341 || format.contains("i")
307 || format.contains("c")) {
342 || format.contains("c")) {
308 labels << QString().sprintf(array, (qint64)value);
343 labels << QString().sprintf(array, (qint64)value);
309 } else if (format.contains("u")
344 } else if (format.contains("u")
310 || format.contains("o")
345 || format.contains("o")
311 || format.contains("x", Qt::CaseInsensitive)) {
346 || format.contains("x", Qt::CaseInsensitive)) {
312 labels << QString().sprintf(array, (quint64)value);
347 labels << QString().sprintf(array, (quint64)value);
313 } else if (format.contains("f", Qt::CaseInsensitive)
348 } else if (format.contains("f", Qt::CaseInsensitive)
314 || format.contains("e", Qt::CaseInsensitive)
349 || format.contains("e", Qt::CaseInsensitive)
315 || format.contains("g", Qt::CaseInsensitive)) {
350 || format.contains("g", Qt::CaseInsensitive)) {
316 labels << QString().sprintf(array, value);
351 labels << QString().sprintf(array, value);
317 } else {
352 } else {
318 labels << QString();
353 labels << QString();
319 }
354 }
320 }
355 }
321 }
356 }
322
357
323 return labels;
358 return labels;
324 }
359 }
325
360
326 QStringList ChartAxisElement::createDateTimeLabels(qreal min, qreal max,int ticks,const QString &format)
361 QStringList ChartAxisElement::createDateTimeLabels(qreal min, qreal max,int ticks,const QString &format)
327 {
362 {
328 QStringList labels;
363 QStringList labels;
329
364
330 if (max <= min || ticks < 1)
365 if (max <= min || ticks < 1)
331 return labels;
366 return labels;
332
367
333 int n = qMax(int(-floor(log10((max - min) / (ticks - 1)))), 0);
368 int n = qMax(int(-floor(log10((max - min) / (ticks - 1)))), 0);
334 n++;
369 n++;
335 for (int i = 0; i < ticks; i++) {
370 for (int i = 0; i < ticks; i++) {
336 qreal value = min + (i * (max - min) / (ticks - 1));
371 qreal value = min + (i * (max - min) / (ticks - 1));
337 labels << QDateTime::fromMSecsSinceEpoch(value).toString(format);
372 labels << QDateTime::fromMSecsSinceEpoch(value).toString(format);
338 }
373 }
339 return labels;
374 return labels;
340 }
375 }
341
376
342 void ChartAxisElement::axisSelected()
377 void ChartAxisElement::axisSelected()
343 {
378 {
344 emit clicked();
379 emit clicked();
345 }
380 }
346
381
347 #include "moc_chartaxiselement_p.cpp"
382 #include "moc_chartaxiselement_p.cpp"
348
383
349 QTCOMMERCIALCHART_END_NAMESPACE
384 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,151 +1,153
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 // W A R N I N G
21 // W A R N I N G
22 // -------------
22 // -------------
23 //
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 // implementation detail. This header file may change from version to
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
26 // version without notice, or even be removed.
27 //
27 //
28 // We mean it.
28 // We mean it.
29
29
30 #ifndef CHARTAXISELEMENT_H
30 #ifndef CHARTAXISELEMENT_H
31 #define CHARTAXISELEMENT_H
31 #define CHARTAXISELEMENT_H
32
32
33 #include "qchartglobal.h"
33 #include "qchartglobal.h"
34 #include "chartelement_p.h"
34 #include "chartelement_p.h"
35 #include "axisanimation_p.h"
35 #include "axisanimation_p.h"
36 #include <QGraphicsItem>
36 #include <QGraphicsItem>
37 #include <QGraphicsLayoutItem>
37 #include <QGraphicsLayoutItem>
38 #include <QFont>
38 #include <QFont>
39
39
40 QTCOMMERCIALCHART_BEGIN_NAMESPACE
40 QTCOMMERCIALCHART_BEGIN_NAMESPACE
41
41
42 class ChartPresenter;
42 class ChartPresenter;
43 class QAbstractAxis;
43 class QAbstractAxis;
44
44
45 class ChartAxisElement : public ChartElement, public QGraphicsLayoutItem
45 class ChartAxisElement : public ChartElement, public QGraphicsLayoutItem
46 {
46 {
47 Q_OBJECT
47 Q_OBJECT
48 public:
48 public:
49 ChartAxisElement(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis = false);
49 ChartAxisElement(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis = false);
50 ~ChartAxisElement();
50 ~ChartAxisElement();
51
51
52 virtual QRectF gridGeometry() const = 0;
52 virtual QRectF gridGeometry() const = 0;
53 virtual void setGeometry(const QRectF &axis, const QRectF &grid) = 0;
53 virtual void setGeometry(const QRectF &axis, const QRectF &grid) = 0;
54 virtual bool isEmpty() = 0;
54 virtual bool isEmpty() = 0;
55
55
56 void setAnimation(AxisAnimation *animation) { m_animation = animation; }
56 void setAnimation(AxisAnimation *animation) { m_animation = animation; }
57 AxisAnimation *animation() const { return m_animation; }
57 AxisAnimation *animation() const { return m_animation; }
58
58
59 QAbstractAxis *axis() const { return m_axis; }
59 QAbstractAxis *axis() const { return m_axis; }
60 void setLayout(QVector<qreal> &layout) { m_layout = layout; }
60 void setLayout(QVector<qreal> &layout) { m_layout = layout; }
61 QVector<qreal> &layout() { return m_layout; } // Modifiable reference
61 QVector<qreal> &layout() { return m_layout; } // Modifiable reference
62 int labelPadding() const { return 5; }
62 int labelPadding() const { return 5; }
63 int titlePadding() const { return 3; }
63 int titlePadding() const { return 3; }
64 void setLabels(const QStringList &labels) { m_labelsList = labels; }
64 void setLabels(const QStringList &labels) { m_labelsList = labels; }
65 QStringList labels() const { return m_labelsList; }
65 QStringList labels() const { return m_labelsList; }
66
66
67 qreal min() const;
67 qreal min() const;
68 qreal max() const;
68 qreal max() const;
69
69
70 QRectF axisGeometry() const { return m_axisRect; }
70 QRectF axisGeometry() const { return m_axisRect; }
71 void setAxisGeometry(const QRectF &axisGeometry) { m_axisRect = axisGeometry; }
71 void setAxisGeometry(const QRectF &axisGeometry) { m_axisRect = axisGeometry; }
72
72
73 QRect labelBoundingRect(const QFontMetrics &fn, const QString &label) const;
73 QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0) const;
74 QString truncatedText(const QFont &font, const QString &text, qreal angle, qreal maxSize,
75 Qt::Orientation constraintOrientation, QRectF &boundingRect) const;
74
76
75 void axisSelected();
77 void axisSelected();
76
78
77 //this flag indicates that axis is used to show intervals it means labels are in between ticks
79 //this flag indicates that axis is used to show intervals it means labels are in between ticks
78 bool intervalAxis() const { return m_intervalAxis; }
80 bool intervalAxis() const { return m_intervalAxis; }
79
81
80 static QStringList createValueLabels(qreal max, qreal min, int ticks, const QString &format);
82 static QStringList createValueLabels(qreal max, qreal min, int ticks, const QString &format);
81 static QStringList createLogValueLabels(qreal min, qreal max, qreal base, int ticks, const QString &format);
83 static QStringList createLogValueLabels(qreal min, qreal max, qreal base, int ticks, const QString &format);
82 static QStringList createDateTimeLabels(qreal max, qreal min, int ticks, const QString &format);
84 static QStringList createDateTimeLabels(qreal max, qreal min, int ticks, const QString &format);
83
85
84 // from QGraphicsLayoutItem
86 // from QGraphicsLayoutItem
85 QRectF boundingRect() const
87 QRectF boundingRect() const
86 {
88 {
87 return QRectF();
89 return QRectF();
88 }
90 }
89
91
90 // from QGraphicsLayoutItem
92 // from QGraphicsLayoutItem
91 void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
93 void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
92 {
94 {
93 }
95 }
94
96
95 protected:
97 protected:
96 virtual QVector<qreal> calculateLayout() const = 0;
98 virtual QVector<qreal> calculateLayout() const = 0;
97 virtual void updateLayout(QVector<qreal> &layout) = 0;
99 virtual void updateLayout(QVector<qreal> &layout) = 0;
98
100
99 QList<QGraphicsItem *> gridItems() { return m_grid->childItems(); }
101 QList<QGraphicsItem *> gridItems() { return m_grid->childItems(); }
100 QList<QGraphicsItem *> labelItems() { return m_labels->childItems(); }
102 QList<QGraphicsItem *> labelItems() { return m_labels->childItems(); }
101 QList<QGraphicsItem *> shadeItems() { return m_shades->childItems(); }
103 QList<QGraphicsItem *> shadeItems() { return m_shades->childItems(); }
102 QList<QGraphicsItem *> arrowItems() { return m_arrow->childItems(); }
104 QList<QGraphicsItem *> arrowItems() { return m_arrow->childItems(); }
103 QGraphicsSimpleTextItem *titleItem() const { return m_title.data(); }
105 QGraphicsSimpleTextItem *titleItem() const { return m_title.data(); }
104 QGraphicsItemGroup *gridGroup() { return m_grid.data(); }
106 QGraphicsItemGroup *gridGroup() { return m_grid.data(); }
105 QGraphicsItemGroup *labelGroup() { return m_labels.data(); }
107 QGraphicsItemGroup *labelGroup() { return m_labels.data(); }
106 QGraphicsItemGroup *shadeGroup() { return m_shades.data(); }
108 QGraphicsItemGroup *shadeGroup() { return m_shades.data(); }
107 QGraphicsItemGroup *arrowGroup() { return m_arrow.data(); }
109 QGraphicsItemGroup *arrowGroup() { return m_arrow.data(); }
108
110
109 public Q_SLOTS:
111 public Q_SLOTS:
110 void handleVisibleChanged(bool visible);
112 void handleVisibleChanged(bool visible);
111 void handleArrowVisibleChanged(bool visible);
113 void handleArrowVisibleChanged(bool visible);
112 void handleGridVisibleChanged(bool visible);
114 void handleGridVisibleChanged(bool visible);
113 void handleLabelsVisibleChanged(bool visible);
115 void handleLabelsVisibleChanged(bool visible);
114 void handleShadesVisibleChanged(bool visible);
116 void handleShadesVisibleChanged(bool visible);
115 void handleLabelsAngleChanged(int angle);
117 void handleLabelsAngleChanged(int angle);
116 virtual void handleShadesBrushChanged(const QBrush &brush) = 0;
118 virtual void handleShadesBrushChanged(const QBrush &brush) = 0;
117 virtual void handleShadesPenChanged(const QPen &pen) = 0;
119 virtual void handleShadesPenChanged(const QPen &pen) = 0;
118 virtual void handleArrowPenChanged(const QPen &pen) = 0;
120 virtual void handleArrowPenChanged(const QPen &pen) = 0;
119 virtual void handleGridPenChanged(const QPen &pen) = 0;
121 virtual void handleGridPenChanged(const QPen &pen) = 0;
120 void handleLabelsPenChanged(const QPen &pen);
122 void handleLabelsPenChanged(const QPen &pen);
121 void handleLabelsBrushChanged(const QBrush &brush);
123 void handleLabelsBrushChanged(const QBrush &brush);
122 void handleLabelsFontChanged(const QFont &font);
124 void handleLabelsFontChanged(const QFont &font);
123 void handleTitlePenChanged(const QPen &pen);
125 void handleTitlePenChanged(const QPen &pen);
124 void handleTitleBrushChanged(const QBrush &brush);
126 void handleTitleBrushChanged(const QBrush &brush);
125 void handleTitleFontChanged(const QFont &font);
127 void handleTitleFontChanged(const QFont &font);
126 void handleTitleTextChanged(const QString &title);
128 void handleTitleTextChanged(const QString &title);
127 void handleTitleVisibleChanged(bool visible);
129 void handleTitleVisibleChanged(bool visible);
128 void handleRangeChanged(qreal min, qreal max);
130 void handleRangeChanged(qreal min, qreal max);
129
131
130 Q_SIGNALS:
132 Q_SIGNALS:
131 void clicked();
133 void clicked();
132
134
133 private:
135 private:
134 void connectSlots();
136 void connectSlots();
135
137
136 QAbstractAxis *m_axis;
138 QAbstractAxis *m_axis;
137 AxisAnimation *m_animation;
139 AxisAnimation *m_animation;
138 QVector<qreal> m_layout;
140 QVector<qreal> m_layout;
139 QStringList m_labelsList;
141 QStringList m_labelsList;
140 QRectF m_axisRect;
142 QRectF m_axisRect;
141 QScopedPointer<QGraphicsItemGroup> m_grid;
143 QScopedPointer<QGraphicsItemGroup> m_grid;
142 QScopedPointer<QGraphicsItemGroup> m_arrow;
144 QScopedPointer<QGraphicsItemGroup> m_arrow;
143 QScopedPointer<QGraphicsItemGroup> m_shades;
145 QScopedPointer<QGraphicsItemGroup> m_shades;
144 QScopedPointer<QGraphicsItemGroup> m_labels;
146 QScopedPointer<QGraphicsItemGroup> m_labels;
145 QScopedPointer<QGraphicsSimpleTextItem> m_title;
147 QScopedPointer<QGraphicsSimpleTextItem> m_title;
146 bool m_intervalAxis;
148 bool m_intervalAxis;
147 };
149 };
148
150
149 QTCOMMERCIALCHART_END_NAMESPACE
151 QTCOMMERCIALCHART_END_NAMESPACE
150
152
151 #endif /* CHARTAXISELEMENT_H */
153 #endif /* CHARTAXISELEMENT_H */
@@ -1,135 +1,131
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartdatetimeaxisx_p.h"
21 #include "chartdatetimeaxisx_p.h"
22 #include "chartpresenter_p.h"
22 #include "chartpresenter_p.h"
23 #include "qdatetimeaxis.h"
23 #include "qdatetimeaxis.h"
24 #include "abstractchartlayout_p.h"
24 #include "abstractchartlayout_p.h"
25 #include <QGraphicsLayout>
25 #include <QGraphicsLayout>
26 #include <QDateTime>
26 #include <QDateTime>
27 #include <QFontMetrics>
28 #include <qmath.h>
27 #include <qmath.h>
29
28
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
30
32 ChartDateTimeAxisX::ChartDateTimeAxisX(QDateTimeAxis *axis, QGraphicsItem *item)
31 ChartDateTimeAxisX::ChartDateTimeAxisX(QDateTimeAxis *axis, QGraphicsItem *item)
33 : HorizontalAxis(axis, item),
32 : HorizontalAxis(axis, item),
34 m_axis(axis)
33 m_axis(axis)
35 {
34 {
36 QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
35 QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
37 QObject::connect(m_axis, SIGNAL(formatChanged(QString)), this, SLOT(handleFormatChanged(QString)));
36 QObject::connect(m_axis, SIGNAL(formatChanged(QString)), this, SLOT(handleFormatChanged(QString)));
38 }
37 }
39
38
40 ChartDateTimeAxisX::~ChartDateTimeAxisX()
39 ChartDateTimeAxisX::~ChartDateTimeAxisX()
41 {
40 {
42 }
41 }
43
42
44 QVector<qreal> ChartDateTimeAxisX::calculateLayout() const
43 QVector<qreal> ChartDateTimeAxisX::calculateLayout() const
45 {
44 {
46 int tickCount = m_axis->tickCount();
45 int tickCount = m_axis->tickCount();
47
46
48 Q_ASSERT(tickCount >= 2);
47 Q_ASSERT(tickCount >= 2);
49
48
50 QVector<qreal> points;
49 QVector<qreal> points;
51 points.resize(tickCount);
50 points.resize(tickCount);
52 const QRectF &gridRect = gridGeometry();
51 const QRectF &gridRect = gridGeometry();
53 const qreal deltaX = gridRect.width() / (qreal(tickCount) - 1.0);
52 const qreal deltaX = gridRect.width() / (qreal(tickCount) - 1.0);
54 for (int i = 0; i < tickCount; ++i)
53 for (int i = 0; i < tickCount; ++i)
55 points[i] = qreal(i) * deltaX + gridRect.left();
54 points[i] = qreal(i) * deltaX + gridRect.left();
56 return points;
55 return points;
57 }
56 }
58
57
59 void ChartDateTimeAxisX::updateGeometry()
58 void ChartDateTimeAxisX::updateGeometry()
60 {
59 {
61 const QVector<qreal>& layout = ChartAxisElement::layout();
60 const QVector<qreal>& layout = ChartAxisElement::layout();
62 if (layout.isEmpty())
61 if (layout.isEmpty())
63 return;
62 return;
64 setLabels(createDateTimeLabels(min(), max(), layout.size(), m_axis->format()));
63 setLabels(createDateTimeLabels(min(), max(), layout.size(), m_axis->format()));
65 HorizontalAxis::updateGeometry();
64 HorizontalAxis::updateGeometry();
66 }
65 }
67
66
68 void ChartDateTimeAxisX::handleTickCountChanged(int tick)
67 void ChartDateTimeAxisX::handleTickCountChanged(int tick)
69 {
68 {
70 Q_UNUSED(tick)
69 Q_UNUSED(tick)
71 QGraphicsLayoutItem::updateGeometry();
70 QGraphicsLayoutItem::updateGeometry();
72 if (presenter())
71 if (presenter())
73 presenter()->layout()->invalidate();
72 presenter()->layout()->invalidate();
74 }
73 }
75
74
76 void ChartDateTimeAxisX::handleFormatChanged(const QString &format)
75 void ChartDateTimeAxisX::handleFormatChanged(const QString &format)
77 {
76 {
78 Q_UNUSED(format);
77 Q_UNUSED(format);
79 QGraphicsLayoutItem::updateGeometry();
78 QGraphicsLayoutItem::updateGeometry();
80 if (presenter())
79 if (presenter())
81 presenter()->layout()->invalidate();
80 presenter()->layout()->invalidate();
82 }
81 }
83
82
84 QSizeF ChartDateTimeAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
83 QSizeF ChartDateTimeAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
85 {
84 {
86 Q_UNUSED(constraint)
85 Q_UNUSED(constraint)
87
86
88 QFontMetrics fn(axis()->labelsFont());
89 QSizeF sh;
87 QSizeF sh;
90
88
91 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
89 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
92 QStringList ticksList = createDateTimeLabels(min(), max(), m_axis->tickCount(), m_axis->format());
90 QStringList ticksList = createDateTimeLabels(min(), max(), m_axis->tickCount(), m_axis->format());
93 // Width of horizontal axis sizeHint indicates the maximum distance labels can extend past
91 // Width of horizontal axis sizeHint indicates the maximum distance labels can extend past
94 // first and last ticks. Base width is irrelevant.
92 // first and last ticks. Base width is irrelevant.
95 qreal width = 0;
93 qreal width = 0;
96 qreal height = 0;
94 qreal height = 0;
97
95
98 if (ticksList.empty())
96 if (ticksList.empty())
99 return sh;
97 return sh;
100
98
101 switch (which) {
99 switch (which) {
102 case Qt::MinimumSize: {
100 case Qt::MinimumSize: {
103 QRectF boundingRect = labelBoundingRect(fn, "...");
101 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle());
104 width = boundingRect.width() / 2.0;
102 width = boundingRect.width() / 2.0;
105 height = boundingRect.height() + labelPadding();
103 height = boundingRect.height() + labelPadding() + base.height() + 1.0;
106 height += base.height();
107 sh = QSizeF(width, height);
104 sh = QSizeF(width, height);
108 break;
105 break;
109 }
106 }
110 case Qt::PreferredSize: {
107 case Qt::PreferredSize: {
111 int labelHeight = 0;
108 qreal labelHeight = 0.0;
112 int firstWidth = -1;
109 qreal firstWidth = -1.0;
113 foreach (const QString& s, ticksList) {
110 foreach (const QString& s, ticksList) {
114 QRect rect = labelBoundingRect(fn, s);
111 QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
115 labelHeight = qMax(rect.height(), labelHeight);
112 labelHeight = qMax(rect.height(), labelHeight);
116 width = rect.width();
113 width = rect.width();
117 if (firstWidth < 0)
114 if (firstWidth < 0.0)
118 firstWidth = width;
115 firstWidth = width;
119 }
116 }
120 height = labelHeight + labelPadding();
117 height = labelHeight + labelPadding() + base.height() + 1.0;
121 height += base.height();
118 width = qMax(width, firstWidth) / 2.0;
122 width = qMax(width, qreal(firstWidth)) / 2.0;
123 sh = QSizeF(width, height);
119 sh = QSizeF(width, height);
124 break;
120 break;
125 }
121 }
126 default:
122 default:
127 break;
123 break;
128 }
124 }
129
125
130 return sh;
126 return sh;
131 }
127 }
132
128
133 #include "moc_chartdatetimeaxisx_p.cpp"
129 #include "moc_chartdatetimeaxisx_p.cpp"
134
130
135 QTCOMMERCIALCHART_END_NAMESPACE
131 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,136 +1,132
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartdatetimeaxisy_p.h"
21 #include "chartdatetimeaxisy_p.h"
22 #include "chartpresenter_p.h"
22 #include "chartpresenter_p.h"
23 #include "qdatetimeaxis.h"
23 #include "qdatetimeaxis.h"
24 #include "abstractchartlayout_p.h"
24 #include "abstractchartlayout_p.h"
25 #include <QGraphicsLayout>
25 #include <QGraphicsLayout>
26 #include <QFontMetrics>
27 #include <QDateTime>
26 #include <QDateTime>
28 #include <qmath.h>
27 #include <qmath.h>
29
28
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
30
32 ChartDateTimeAxisY::ChartDateTimeAxisY(QDateTimeAxis *axis, QGraphicsItem *item)
31 ChartDateTimeAxisY::ChartDateTimeAxisY(QDateTimeAxis *axis, QGraphicsItem *item)
33 : VerticalAxis(axis, item),
32 : VerticalAxis(axis, item),
34 m_axis(axis)
33 m_axis(axis)
35 {
34 {
36 QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
35 QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
37 QObject::connect(m_axis, SIGNAL(formatChanged(QString)), this, SLOT(handleFormatChanged(QString)));
36 QObject::connect(m_axis, SIGNAL(formatChanged(QString)), this, SLOT(handleFormatChanged(QString)));
38 }
37 }
39
38
40 ChartDateTimeAxisY::~ChartDateTimeAxisY()
39 ChartDateTimeAxisY::~ChartDateTimeAxisY()
41 {
40 {
42 }
41 }
43
42
44 QVector<qreal> ChartDateTimeAxisY::calculateLayout() const
43 QVector<qreal> ChartDateTimeAxisY::calculateLayout() const
45 {
44 {
46 int tickCount = m_axis->tickCount();
45 int tickCount = m_axis->tickCount();
47
46
48 Q_ASSERT(tickCount >= 2);
47 Q_ASSERT(tickCount >= 2);
49
48
50 QVector<qreal> points;
49 QVector<qreal> points;
51 points.resize(tickCount);
50 points.resize(tickCount);
52 const QRectF &gridRect = gridGeometry();
51 const QRectF &gridRect = gridGeometry();
53 const qreal deltaY = gridRect.height() / (qreal(tickCount) - 1.0);
52 const qreal deltaY = gridRect.height() / (qreal(tickCount) - 1.0);
54 for (int i = 0; i < tickCount; ++i)
53 for (int i = 0; i < tickCount; ++i)
55 points[i] = qreal(i) * -deltaY + gridRect.bottom();
54 points[i] = qreal(i) * -deltaY + gridRect.bottom();
56
55
57 return points;
56 return points;
58 }
57 }
59
58
60 void ChartDateTimeAxisY::updateGeometry()
59 void ChartDateTimeAxisY::updateGeometry()
61 {
60 {
62 const QVector<qreal> &layout = ChartAxisElement::layout();
61 const QVector<qreal> &layout = ChartAxisElement::layout();
63 if (layout.isEmpty())
62 if (layout.isEmpty())
64 return;
63 return;
65 setLabels(createDateTimeLabels(min(), max(), layout.size(), m_axis->format()));
64 setLabels(createDateTimeLabels(min(), max(), layout.size(), m_axis->format()));
66 VerticalAxis::updateGeometry();
65 VerticalAxis::updateGeometry();
67 }
66 }
68
67
69 void ChartDateTimeAxisY::handleTickCountChanged(int tick)
68 void ChartDateTimeAxisY::handleTickCountChanged(int tick)
70 {
69 {
71 Q_UNUSED(tick)
70 Q_UNUSED(tick)
72 QGraphicsLayoutItem::updateGeometry();
71 QGraphicsLayoutItem::updateGeometry();
73 if (presenter())
72 if (presenter())
74 presenter()->layout()->invalidate();
73 presenter()->layout()->invalidate();
75 }
74 }
76
75
77 void ChartDateTimeAxisY::handleFormatChanged(const QString &format)
76 void ChartDateTimeAxisY::handleFormatChanged(const QString &format)
78 {
77 {
79 Q_UNUSED(format);
78 Q_UNUSED(format);
80 QGraphicsLayoutItem::updateGeometry();
79 QGraphicsLayoutItem::updateGeometry();
81 if (presenter())
80 if (presenter())
82 presenter()->layout()->invalidate();
81 presenter()->layout()->invalidate();
83 }
82 }
84
83
85 QSizeF ChartDateTimeAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
84 QSizeF ChartDateTimeAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
86 {
85 {
87 Q_UNUSED(constraint)
86 Q_UNUSED(constraint)
88
87
89 QFontMetrics fn(axis()->labelsFont());
90 QSizeF sh;
88 QSizeF sh;
91
89
92 QSizeF base = VerticalAxis::sizeHint(which, constraint);
90 QSizeF base = VerticalAxis::sizeHint(which, constraint);
93 QStringList ticksList = createDateTimeLabels(min(), max(), m_axis->tickCount(), m_axis->format());
91 QStringList ticksList = createDateTimeLabels(min(), max(), m_axis->tickCount(), m_axis->format());
94 qreal width = 0;
92 qreal width = 0;
95 // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
93 // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
96 // first and last ticks. Base height is irrelevant.
94 // first and last ticks. Base height is irrelevant.
97 qreal height = 0;
95 qreal height = 0;
98
96
99 if (ticksList.empty())
97 if (ticksList.empty())
100 return sh;
98 return sh;
101
99
102 switch (which) {
100 switch (which) {
103 case Qt::MinimumSize: {
101 case Qt::MinimumSize: {
104 QRectF boundingRect = labelBoundingRect(fn, "...");
102 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle());
105 width = boundingRect.width() + labelPadding();
103 width = boundingRect.width() + labelPadding() + base.width() + 1.0;
106 width += base.width();
107 height = boundingRect.height() / 2.0;
104 height = boundingRect.height() / 2.0;
108 sh = QSizeF(width, height);
105 sh = QSizeF(width, height);
109 break;
106 break;
110 }
107 }
111 case Qt::PreferredSize: {
108 case Qt::PreferredSize: {
112 int labelWidth = 0;
109 qreal labelWidth = 0.0;
113 int firstHeight = -1;
110 qreal firstHeight = -1.0;
114 foreach (const QString& s, ticksList) {
111 foreach (const QString& s, ticksList) {
115 QRect rect = labelBoundingRect(fn, s);
112 QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
116 labelWidth = qMax(rect.width(), labelWidth);
113 labelWidth = qMax(rect.width(), labelWidth);
117 height = rect.height();
114 height = rect.height();
118 if (firstHeight < 0)
115 if (firstHeight < 0.0)
119 firstHeight = height;
116 firstHeight = height;
120 }
117 }
121 width = labelWidth + labelPadding() + 2; //two pixels of tolerance
118 width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance
122 width += base.width();
119 height = qMax(height, firstHeight) / 2.0;
123 height = qMax(height, qreal(firstHeight)) / 2.0;
124 sh = QSizeF(width, height);
120 sh = QSizeF(width, height);
125 break;
121 break;
126 }
122 }
127 default:
123 default:
128 break;
124 break;
129 }
125 }
130
126
131 return sh;
127 return sh;
132 }
128 }
133
129
134 #include "moc_chartdatetimeaxisy_p.cpp"
130 #include "moc_chartdatetimeaxisy_p.cpp"
135
131
136 QTCOMMERCIALCHART_END_NAMESPACE
132 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,237 +1,205
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "horizontalaxis_p.h"
21 #include "horizontalaxis_p.h"
22 #include "qabstractaxis_p.h"
22 #include "qabstractaxis_p.h"
23 #include <QFontMetrics>
24 #include <qmath.h>
23 #include <qmath.h>
25 #include <QDebug>
24 #include <QDebug>
26
25
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28
27
29 HorizontalAxis::HorizontalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
28 HorizontalAxis::HorizontalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
30 : CartesianChartAxis(axis, item, intervalAxis)
29 : CartesianChartAxis(axis, item, intervalAxis)
31 {
30 {
32 }
31 }
33
32
34 HorizontalAxis::~HorizontalAxis()
33 HorizontalAxis::~HorizontalAxis()
35 {
34 {
36 }
35 }
37
36
38 void HorizontalAxis::updateGeometry()
37 void HorizontalAxis::updateGeometry()
39 {
38 {
40 const QVector<qreal> &layout = ChartAxisElement::layout();
39 const QVector<qreal> &layout = ChartAxisElement::layout();
41
40
42 if (layout.isEmpty())
41 if (layout.isEmpty())
43 return;
42 return;
44
43
45 QStringList labelList = labels();
44 QStringList labelList = labels();
46
45
47 QList<QGraphicsItem *> lines = gridItems();
46 QList<QGraphicsItem *> lines = gridItems();
48 QList<QGraphicsItem *> labels = labelItems();
47 QList<QGraphicsItem *> labels = labelItems();
49 QList<QGraphicsItem *> shades = shadeItems();
48 QList<QGraphicsItem *> shades = shadeItems();
50 QList<QGraphicsItem *> arrow = arrowItems();
49 QList<QGraphicsItem *> arrow = arrowItems();
51 QGraphicsSimpleTextItem *title = titleItem();
50 QGraphicsSimpleTextItem *title = titleItem();
52
51
53 Q_ASSERT(labels.size() == labelList.size());
52 Q_ASSERT(labels.size() == labelList.size());
54 Q_ASSERT(layout.size() == labelList.size());
53 Q_ASSERT(layout.size() == labelList.size());
55
54
56 const QRectF &axisRect = axisGeometry();
55 const QRectF &axisRect = axisGeometry();
57 const QRectF &gridRect = gridGeometry();
56 const QRectF &gridRect = gridGeometry();
58
57
59 //arrow
58 //arrow
60 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem *>(arrow.at(0));
59 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem *>(arrow.at(0));
61
60
62 if (axis()->alignment() == Qt::AlignTop)
61 if (axis()->alignment() == Qt::AlignTop)
63 arrowItem->setLine(gridRect.left(), axisRect.bottom(), gridRect.right(), axisRect.bottom());
62 arrowItem->setLine(gridRect.left(), axisRect.bottom(), gridRect.right(), axisRect.bottom());
64 else if (axis()->alignment() == Qt::AlignBottom)
63 else if (axis()->alignment() == Qt::AlignBottom)
65 arrowItem->setLine(gridRect.left(), axisRect.top(), gridRect.right(), axisRect.top());
64 arrowItem->setLine(gridRect.left(), axisRect.top(), gridRect.right(), axisRect.top());
66
65
67 qreal width = 0;
66 qreal width = 0;
68 QFontMetrics fn(axis()->labelsFont());
69
67
70 //title
68 //title
71 int titlePad = 0;
69 int titlePad = 0;
72 QRectF titleBoundingRect;
70 QRectF titleBoundingRect;
73 QString titleText = axis()->titleText();
71 QString titleText = axis()->titleText();
74 if (!titleText.isEmpty() && titleItem()->isVisible()) {
72 if (!titleText.isEmpty() && titleItem()->isVisible()) {
75 int size(0);
73 title->setText(truncatedText(axis()->titleFont(), titleText, 0.0, gridRect.width(), Qt::Horizontal, QRectF()));
76 size = gridRect.width();
77
78 QGraphicsSimpleTextItem dummyTitle;
79 dummyTitle.setFont(axis()->titleFont());
80 dummyTitle.setText(axis()->titleText());
81 QRectF dummyRect = dummyTitle.boundingRect();
82
83 if (dummyRect.width() > size) {
84 QString string = titleText + "...";
85 while (dummyRect.width() > size && string.length() > 3) {
86 string.remove(string.length() - 4, 1);
87 dummyTitle.setText(string);
88 dummyRect = dummyTitle.boundingRect();
89 }
90 title->setText(string);
91 } else {
92 title->setText(titleText);
93 }
94
74
95 titlePad = titlePadding();
75 titlePad = titlePadding();
96 titleBoundingRect = title->boundingRect();
76 titleBoundingRect = title->boundingRect();
97
77
98 QPointF center = gridRect.center() - titleBoundingRect.center();
78 QPointF center = gridRect.center() - titleBoundingRect.center();
99 if (axis()->alignment() == Qt::AlignTop) {
79 if (axis()->alignment() == Qt::AlignTop) {
100 title->setPos(center.x(), axisRect.top() + titlePad);
80 title->setPos(center.x(), axisRect.top() + titlePad);
101 } else if (axis()->alignment() == Qt::AlignBottom) {
81 } else if (axis()->alignment() == Qt::AlignBottom) {
102 title->setPos(center.x(), axisRect.bottom() - titleBoundingRect.height() - titlePad);
82 title->setPos(center.x(), axisRect.bottom() - titleBoundingRect.height() - titlePad);
103 }
83 }
104 }
84 }
105
85
106 for (int i = 0; i < layout.size(); ++i) {
86 for (int i = 0; i < layout.size(); ++i) {
107
108 //items
87 //items
109 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem*>(lines.at(i));
88 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem*>(lines.at(i));
110 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem*>(arrow.at(i + 1));
89 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem*>(arrow.at(i + 1));
111 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labels.at(i));
90 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labels.at(i));
112
91
113 //grid line
92 //grid line
114 gridItem->setLine(layout[i], gridRect.top(), layout[i], gridRect.bottom());
93 gridItem->setLine(layout[i], gridRect.top(), layout[i], gridRect.bottom());
115
94
116 //label text wrapping
95 //label text wrapping
117 QString text = labelList.at(i);
96 QString text = labelList.at(i);
118 QRectF boundingRect = labelBoundingRect(fn, text);
97 QRectF boundingRect;
119 qreal size = axisRect.bottom() - axisRect.top() - labelPadding() - titleBoundingRect.height() - (titlePad * 2);
98 qreal size = axisRect.bottom() - axisRect.top() - labelPadding() - titleBoundingRect.height() - (titlePad * 2);
120 if (boundingRect.height() > size) {
99 labelItem->setText(truncatedText(axis()->labelsFont(), text, axis()->labelsAngle(),
121 QString label = text + "...";
100 size, Qt::Vertical, boundingRect));
122 while (boundingRect.height() >= size && label.length() > 3) {
123 label.remove(label.length() - 4, 1);
124 boundingRect = labelBoundingRect(fn, label);
125 }
126 labelItem->setText(label);
127 } else {
128 labelItem->setText(text);
129 }
130
101
131 //label transformation origin point
102 //label transformation origin point
132 const QRectF& rect = labelItem->boundingRect();
103 const QRectF& rect = labelItem->boundingRect();
133 QPointF center = rect.center();
104 QPointF center = rect.center();
134 labelItem->setTransformOriginPoint(center.x(), center.y());
105 labelItem->setTransformOriginPoint(center.x(), center.y());
135 int heightDiff = rect.height() - boundingRect.height();
106 int heightDiff = rect.height() - boundingRect.height();
136
107
137 //ticks and label position
108 //ticks and label position
138 if (axis()->alignment() == Qt::AlignTop) {
109 if (axis()->alignment() == Qt::AlignTop) {
139 labelItem->setPos(layout[i] - center.x(), axisRect.bottom() - rect.height() + (heightDiff / 2) - labelPadding());
110 labelItem->setPos(layout[i] - center.x(), axisRect.bottom() - rect.height() + (heightDiff / 2) - labelPadding());
140 tickItem->setLine(layout[i], axisRect.bottom(), layout[i], axisRect.bottom() - labelPadding());
111 tickItem->setLine(layout[i], axisRect.bottom(), layout[i], axisRect.bottom() - labelPadding());
141 } else if (axis()->alignment() == Qt::AlignBottom) {
112 } else if (axis()->alignment() == Qt::AlignBottom) {
142 labelItem->setPos(layout[i] - center.x(), axisRect.top() - (heightDiff / 2) + labelPadding());
113 labelItem->setPos(layout[i] - center.x(), axisRect.top() - (heightDiff / 2) + labelPadding());
143 tickItem->setLine(layout[i], axisRect.top(), layout[i], axisRect.top() + labelPadding());
114 tickItem->setLine(layout[i], axisRect.top(), layout[i], axisRect.top() + labelPadding());
144 }
115 }
145
116
146 //label in between
117 //label in between
147 bool forceHide = false;
118 bool forceHide = false;
148 if (intervalAxis() && (i + 1) != layout.size()) {
119 if (intervalAxis() && (i + 1) != layout.size()) {
149 qreal leftBound = qMax(layout[i], gridRect.left());
120 qreal leftBound = qMax(layout[i], gridRect.left());
150 qreal rightBound = qMin(layout[i + 1], gridRect.right());
121 qreal rightBound = qMin(layout[i + 1], gridRect.right());
151 const qreal delta = rightBound - leftBound;
122 const qreal delta = rightBound - leftBound;
152 // Hide label in case visible part of the category at the grid edge is too narrow
123 // Hide label in case visible part of the category at the grid edge is too narrow
153 if (delta < boundingRect.width()
124 if (delta < boundingRect.width()
154 && (leftBound == gridRect.left() || rightBound == gridRect.right())) {
125 && (leftBound == gridRect.left() || rightBound == gridRect.right())) {
155 forceHide = true;
126 forceHide = true;
156 } else {
127 } else {
157 labelItem->setPos(leftBound + (delta / 2.0) - center.x(), labelItem->pos().y());
128 labelItem->setPos(leftBound + (delta / 2.0) - center.x(), labelItem->pos().y());
158 }
129 }
159 }
130 }
160
131
161 //label overlap detection - compensate one pixel for rounding errors
132 //label overlap detection - compensate one pixel for rounding errors
162 if (labelItem->pos().x() < width || forceHide ||
133 if (labelItem->pos().x() < width || forceHide ||
163 labelItem->pos().x() < (axisRect.left() - 1.0) ||
134 labelItem->pos().x() < (axisRect.left() - 1.0) ||
164 (labelItem->pos().x() + boundingRect.width() - 1.0) > axisRect.right()){
135 (labelItem->pos().x() + boundingRect.width() - 1.0) > axisRect.right()){
165 labelItem->setVisible(false);
136 labelItem->setVisible(false);
166 } else {
137 } else {
167 labelItem->setVisible(true);
138 labelItem->setVisible(true);
168 width = boundingRect.width() + labelItem->pos().x();
139 width = boundingRect.width() + labelItem->pos().x();
169 }
140 }
170
141
171 //shades
142 //shades
172 if ((i + 1) % 2 && i > 1) {
143 if ((i + 1) % 2 && i > 1) {
173 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem *>(shades.at(i / 2 - 1));
144 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem *>(shades.at(i / 2 - 1));
174 qreal leftBound = qMax(layout[i - 1], gridRect.left());
145 qreal leftBound = qMax(layout[i - 1], gridRect.left());
175 qreal rightBound = qMin(layout[i], gridRect.right());
146 qreal rightBound = qMin(layout[i], gridRect.right());
176 rectItem->setRect(leftBound, gridRect.top(), rightBound - leftBound, gridRect.height());
147 rectItem->setRect(leftBound, gridRect.top(), rightBound - leftBound, gridRect.height());
177 if (rectItem->rect().width() <= 0.0)
148 if (rectItem->rect().width() <= 0.0)
178 rectItem->setVisible(false);
149 rectItem->setVisible(false);
179 else
150 else
180 rectItem->setVisible(true);
151 rectItem->setVisible(true);
181 }
152 }
182
153
183 // check if the grid line and the axis tick should be shown
154 // check if the grid line and the axis tick should be shown
184 qreal x = gridItem->line().p1().x();
155 qreal x = gridItem->line().p1().x();
185 if (x < gridRect.left() || x > gridRect.right()) {
156 if (x < gridRect.left() || x > gridRect.right()) {
186 gridItem->setVisible(false);
157 gridItem->setVisible(false);
187 tickItem->setVisible(false);
158 tickItem->setVisible(false);
188 } else {
159 } else {
189 gridItem->setVisible(true);
160 gridItem->setVisible(true);
190 tickItem->setVisible(true);
161 tickItem->setVisible(true);
191 }
162 }
192
163
193 }
164 }
194
165
195 //begin/end grid line in case labels between
166 //begin/end grid line in case labels between
196 if (intervalAxis()) {
167 if (intervalAxis()) {
197 QGraphicsLineItem *gridLine;
168 QGraphicsLineItem *gridLine;
198 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
169 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
199 gridLine->setLine(gridRect.right(), gridRect.top(), gridRect.right(), gridRect.bottom());
170 gridLine->setLine(gridRect.right(), gridRect.top(), gridRect.right(), gridRect.bottom());
200 gridLine->setVisible(true);
171 gridLine->setVisible(true);
201 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size()+1));
172 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size()+1));
202 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.left(), gridRect.bottom());
173 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.left(), gridRect.bottom());
203 gridLine->setVisible(true);
174 gridLine->setVisible(true);
204 }
175 }
205 }
176 }
206
177
207 QSizeF HorizontalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
178 QSizeF HorizontalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
208 {
179 {
209 Q_UNUSED(constraint);
180 Q_UNUSED(constraint);
210 QSizeF sh(0,0);
181 QSizeF sh(0,0);
211
182
212 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
183 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
213 return sh;
184 return sh;
214
185
215 switch (which) {
186 switch (which) {
216 case Qt::MinimumSize: {
187 case Qt::MinimumSize: {
217 QFontMetrics fn(axis()->titleFont());
188 QRectF titleRect = textBoundingRect(axis()->titleFont(), "...");
218 sh = QSizeF(fn.boundingRect("...").width(), fn.height() + (titlePadding() * 2));
189 sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2));
219 break;
190 break;
220 }
191 }
221 case Qt::MaximumSize:
192 case Qt::MaximumSize:
222 case Qt::PreferredSize: {
193 case Qt::PreferredSize: {
223 QGraphicsSimpleTextItem dummyTitle;
194 QRectF titleRect = textBoundingRect(axis()->titleFont(), axis()->titleText());
224 dummyTitle.setFont(axis()->titleFont());
225 dummyTitle.setText(axis()->titleText());
226 QRectF titleRect = dummyTitle.boundingRect();
227 sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2));
195 sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2));
228 break;
196 break;
229 }
197 }
230 default:
198 default:
231 break;
199 break;
232 }
200 }
233
201
234 return sh;
202 return sh;
235 }
203 }
236
204
237 QTCOMMERCIALCHART_END_NAMESPACE
205 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,141 +1,137
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartlogvalueaxisx_p.h"
21 #include "chartlogvalueaxisx_p.h"
22 #include "chartpresenter_p.h"
22 #include "chartpresenter_p.h"
23 #include "qlogvalueaxis.h"
23 #include "qlogvalueaxis.h"
24 #include "abstractchartlayout_p.h"
24 #include "abstractchartlayout_p.h"
25 #include <QGraphicsLayout>
25 #include <QGraphicsLayout>
26 #include <QFontMetrics>
27 #include <qmath.h>
26 #include <qmath.h>
28 #include <QDebug>
27 #include <QDebug>
29
28
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
30
32 ChartLogValueAxisX::ChartLogValueAxisX(QLogValueAxis *axis, QGraphicsItem *item)
31 ChartLogValueAxisX::ChartLogValueAxisX(QLogValueAxis *axis, QGraphicsItem *item)
33 : HorizontalAxis(axis, item),
32 : HorizontalAxis(axis, item),
34 m_axis(axis)
33 m_axis(axis)
35 {
34 {
36 QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
35 QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
37 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
36 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
38 }
37 }
39
38
40 ChartLogValueAxisX::~ChartLogValueAxisX()
39 ChartLogValueAxisX::~ChartLogValueAxisX()
41 {
40 {
42 }
41 }
43
42
44 QVector<qreal> ChartLogValueAxisX::calculateLayout() const
43 QVector<qreal> ChartLogValueAxisX::calculateLayout() const
45 {
44 {
46 QVector<qreal> points;
45 QVector<qreal> points;
47
46
48 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
47 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
49 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
48 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
50 qreal leftEdge = logMin < logMax ? logMin : logMax;
49 qreal leftEdge = logMin < logMax ? logMin : logMax;
51 qreal ceilEdge = ceil(leftEdge);
50 qreal ceilEdge = ceil(leftEdge);
52 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
51 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
53
52
54 points.resize(tickCount);
53 points.resize(tickCount);
55 const QRectF &gridRect = gridGeometry();
54 const QRectF &gridRect = gridGeometry();
56 const qreal deltaX = gridRect.width() / qAbs(logMax - logMin);
55 const qreal deltaX = gridRect.width() / qAbs(logMax - logMin);
57 for (int i = 0; i < tickCount; ++i)
56 for (int i = 0; i < tickCount; ++i)
58 points[i] = (ceilEdge + qreal(i)) * deltaX - leftEdge * deltaX + gridRect.left();
57 points[i] = (ceilEdge + qreal(i)) * deltaX - leftEdge * deltaX + gridRect.left();
59
58
60 return points;
59 return points;
61 }
60 }
62
61
63 void ChartLogValueAxisX::updateGeometry()
62 void ChartLogValueAxisX::updateGeometry()
64 {
63 {
65 const QVector<qreal>& layout = ChartAxisElement::layout();
64 const QVector<qreal>& layout = ChartAxisElement::layout();
66 if (layout.isEmpty())
65 if (layout.isEmpty())
67 return;
66 return;
68 setLabels(createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), layout.size(), m_axis->labelFormat()));
67 setLabels(createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), layout.size(), m_axis->labelFormat()));
69 HorizontalAxis::updateGeometry();
68 HorizontalAxis::updateGeometry();
70 }
69 }
71
70
72 void ChartLogValueAxisX::handleBaseChanged(qreal base)
71 void ChartLogValueAxisX::handleBaseChanged(qreal base)
73 {
72 {
74 Q_UNUSED(base);
73 Q_UNUSED(base);
75 QGraphicsLayoutItem::updateGeometry();
74 QGraphicsLayoutItem::updateGeometry();
76 if(presenter()) presenter()->layout()->invalidate();
75 if(presenter()) presenter()->layout()->invalidate();
77 }
76 }
78
77
79 void ChartLogValueAxisX::handleLabelFormatChanged(const QString &format)
78 void ChartLogValueAxisX::handleLabelFormatChanged(const QString &format)
80 {
79 {
81 Q_UNUSED(format);
80 Q_UNUSED(format);
82 QGraphicsLayoutItem::updateGeometry();
81 QGraphicsLayoutItem::updateGeometry();
83 if(presenter()) presenter()->layout()->invalidate();
82 if(presenter()) presenter()->layout()->invalidate();
84 }
83 }
85
84
86 QSizeF ChartLogValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
85 QSizeF ChartLogValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
87 {
86 {
88 Q_UNUSED(constraint)
87 Q_UNUSED(constraint)
89
88
90 QFontMetrics fn(axis()->labelsFont());
91 QSizeF sh;
89 QSizeF sh;
92
90
93 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
91 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
94 QStringList ticksList;
92 QStringList ticksList;
95 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
93 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
96 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
94 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
97 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
95 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
98 if (m_axis->max() > m_axis->min() && tickCount > 0)
96 if (m_axis->max() > m_axis->min() && tickCount > 0)
99 ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
97 ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
100 else
98 else
101 ticksList.append(QString(" "));
99 ticksList.append(QString(" "));
102 // Width of horizontal axis sizeHint indicates the maximum distance labels can extend past
100 // Width of horizontal axis sizeHint indicates the maximum distance labels can extend past
103 // first and last ticks. Base width is irrelevant.
101 // first and last ticks. Base width is irrelevant.
104 qreal width = 0;
102 qreal width = 0;
105 qreal height = 0;
103 qreal height = 0;
106
104
107 switch (which) {
105 switch (which) {
108 case Qt::MinimumSize:{
106 case Qt::MinimumSize:{
109 QRectF boundingRect = labelBoundingRect(fn, "...");
107 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle());
110 width = boundingRect.width() / 2.0;
108 width = boundingRect.width() / 2.0;
111 height = boundingRect.height() + labelPadding();
109 height = boundingRect.height() + labelPadding() + base.height() + 1.0;
112 height += base.height();
113 sh = QSizeF(width, height);
110 sh = QSizeF(width, height);
114 break;
111 break;
115 }
112 }
116 case Qt::PreferredSize: {
113 case Qt::PreferredSize: {
117 int labelHeight = 0;
114 qreal labelHeight = 0.0;
118 int firstWidth = -1;
115 qreal firstWidth = -1.0;
119 foreach (const QString& s, ticksList) {
116 foreach (const QString& s, ticksList) {
120 QRect rect = labelBoundingRect(fn, s);
117 QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
121 labelHeight = qMax(rect.height(), labelHeight);
118 labelHeight = qMax(rect.height(), labelHeight);
122 width = rect.width();
119 width = rect.width();
123 if (firstWidth < 0)
120 if (firstWidth < 0.0)
124 firstWidth = width;
121 firstWidth = width;
125 }
122 }
126 height = labelHeight + labelPadding();
123 height = labelHeight + labelPadding() + base.height() + 1.0;
127 height += base.height();
124 width = qMax(width, firstWidth) / 2.0;
128 width = qMax(width, qreal(firstWidth)) / 2.0;
129 sh = QSizeF(width, height);
125 sh = QSizeF(width, height);
130 break;
126 break;
131 }
127 }
132 default:
128 default:
133 break;
129 break;
134 }
130 }
135
131
136 return sh;
132 return sh;
137 }
133 }
138
134
139 #include "moc_chartlogvalueaxisx_p.cpp"
135 #include "moc_chartlogvalueaxisx_p.cpp"
140
136
141 QTCOMMERCIALCHART_END_NAMESPACE
137 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,141 +1,137
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartlogvalueaxisy_p.h"
21 #include "chartlogvalueaxisy_p.h"
22 #include "chartpresenter_p.h"
22 #include "chartpresenter_p.h"
23 #include "qlogvalueaxis.h"
23 #include "qlogvalueaxis.h"
24 #include "abstractchartlayout_p.h"
24 #include "abstractchartlayout_p.h"
25 #include <QGraphicsLayout>
25 #include <QGraphicsLayout>
26 #include <QFontMetrics>
27 #include <qmath.h>
26 #include <qmath.h>
28 #include <QDebug>
27 #include <QDebug>
29
28
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
30
32 ChartLogValueAxisY::ChartLogValueAxisY(QLogValueAxis *axis, QGraphicsItem *item)
31 ChartLogValueAxisY::ChartLogValueAxisY(QLogValueAxis *axis, QGraphicsItem *item)
33 : VerticalAxis(axis, item),
32 : VerticalAxis(axis, item),
34 m_axis(axis)
33 m_axis(axis)
35 {
34 {
36 QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
35 QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
37 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
36 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
38 }
37 }
39
38
40 ChartLogValueAxisY::~ChartLogValueAxisY()
39 ChartLogValueAxisY::~ChartLogValueAxisY()
41 {
40 {
42 }
41 }
43
42
44 QVector<qreal> ChartLogValueAxisY::calculateLayout() const
43 QVector<qreal> ChartLogValueAxisY::calculateLayout() const
45 {
44 {
46 QVector<qreal> points;
45 QVector<qreal> points;
47 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
46 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
48 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
47 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
49 qreal leftEdge = logMin < logMax ? logMin : logMax;
48 qreal leftEdge = logMin < logMax ? logMin : logMax;
50 qreal ceilEdge = ceil(leftEdge);
49 qreal ceilEdge = ceil(leftEdge);
51 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
50 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
52
51
53 points.resize(tickCount);
52 points.resize(tickCount);
54 const QRectF &gridRect = gridGeometry();
53 const QRectF &gridRect = gridGeometry();
55 const qreal deltaY = gridRect.height() / qAbs(logMax - logMin);
54 const qreal deltaY = gridRect.height() / qAbs(logMax - logMin);
56 for (int i = 0; i < tickCount; ++i)
55 for (int i = 0; i < tickCount; ++i)
57 points[i] = (ceilEdge + qreal(i)) * -deltaY - leftEdge * -deltaY + gridRect.bottom();
56 points[i] = (ceilEdge + qreal(i)) * -deltaY - leftEdge * -deltaY + gridRect.bottom();
58
57
59 return points;
58 return points;
60 }
59 }
61
60
62
61
63 void ChartLogValueAxisY::updateGeometry()
62 void ChartLogValueAxisY::updateGeometry()
64 {
63 {
65 const QVector<qreal> &layout = ChartAxisElement::layout();
64 const QVector<qreal> &layout = ChartAxisElement::layout();
66 if (layout.isEmpty())
65 if (layout.isEmpty())
67 return;
66 return;
68 setLabels(createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), layout.size(), m_axis->labelFormat()));
67 setLabels(createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), layout.size(), m_axis->labelFormat()));
69 VerticalAxis::updateGeometry();
68 VerticalAxis::updateGeometry();
70 }
69 }
71
70
72 void ChartLogValueAxisY::handleBaseChanged(qreal base)
71 void ChartLogValueAxisY::handleBaseChanged(qreal base)
73 {
72 {
74 Q_UNUSED(base);
73 Q_UNUSED(base);
75 QGraphicsLayoutItem::updateGeometry();
74 QGraphicsLayoutItem::updateGeometry();
76 if(presenter()) presenter()->layout()->invalidate();
75 if(presenter()) presenter()->layout()->invalidate();
77 }
76 }
78
77
79 void ChartLogValueAxisY::handleLabelFormatChanged(const QString &format)
78 void ChartLogValueAxisY::handleLabelFormatChanged(const QString &format)
80 {
79 {
81 Q_UNUSED(format);
80 Q_UNUSED(format);
82 QGraphicsLayoutItem::updateGeometry();
81 QGraphicsLayoutItem::updateGeometry();
83 if(presenter()) presenter()->layout()->invalidate();
82 if(presenter()) presenter()->layout()->invalidate();
84 }
83 }
85
84
86 QSizeF ChartLogValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
85 QSizeF ChartLogValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
87 {
86 {
88 Q_UNUSED(constraint)
87 Q_UNUSED(constraint)
89
88
90 QFontMetrics fn(axis()->labelsFont());
91 QSizeF sh;
89 QSizeF sh;
92
90
93 QSizeF base = VerticalAxis::sizeHint(which, constraint);
91 QSizeF base = VerticalAxis::sizeHint(which, constraint);
94 QStringList ticksList;
92 QStringList ticksList;
95 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
93 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
96 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
94 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
97 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
95 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
98 if (m_axis->max() > m_axis->min() && tickCount > 0)
96 if (m_axis->max() > m_axis->min() && tickCount > 0)
99 ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
97 ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
100 else
98 else
101 ticksList.append(QString(" "));
99 ticksList.append(QString(" "));
102 qreal width = 0;
100 qreal width = 0;
103 // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
101 // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
104 // first and last ticks. Base height is irrelevant.
102 // first and last ticks. Base height is irrelevant.
105 qreal height = 0;
103 qreal height = 0;
106
104
107 switch (which) {
105 switch (which) {
108 case Qt::MinimumSize: {
106 case Qt::MinimumSize: {
109 QRectF boundingRect = labelBoundingRect(fn, "...");
107 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle());
110 width = boundingRect.width() + labelPadding();
108 width = boundingRect.width() + labelPadding() + base.width() + 1.0;
111 width += base.width();
112 height = boundingRect.height() / 2.0;
109 height = boundingRect.height() / 2.0;
113 sh = QSizeF(width, height);
110 sh = QSizeF(width, height);
114 break;
111 break;
115 }
112 }
116 case Qt::PreferredSize: {
113 case Qt::PreferredSize: {
117 int labelWidth = 0;
114 qreal labelWidth = 0.0;
118 int firstHeight = -1;
115 qreal firstHeight = -1.0;
119 foreach (const QString& s, ticksList) {
116 foreach (const QString& s, ticksList) {
120 QRect rect = labelBoundingRect(fn, s);
117 QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
121 labelWidth = qMax(rect.width(), labelWidth);
118 labelWidth = qMax(rect.width(), labelWidth);
122 height = rect.height();
119 height = rect.height();
123 if (firstHeight < 0)
120 if (firstHeight < 0.0)
124 firstHeight = height;
121 firstHeight = height;
125 }
122 }
126 width = labelWidth + labelPadding() + 2; //two pixels of tolerance
123 width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance
127 width += base.width();
124 height = qMax(height, firstHeight) / 2.0;
128 height = qMax(height, qreal(firstHeight)) / 2.0;
129 sh = QSizeF(width, height);
125 sh = QSizeF(width, height);
130 break;
126 break;
131 }
127 }
132 default:
128 default:
133 break;
129 break;
134 }
130 }
135
131
136 return sh;
132 return sh;
137 }
133 }
138
134
139 #include "moc_chartlogvalueaxisy_p.cpp"
135 #include "moc_chartlogvalueaxisy_p.cpp"
140
136
141 QTCOMMERCIALCHART_END_NAMESPACE
137 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,435 +1,410
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "polarchartaxisangular_p.h"
21 #include "polarchartaxisangular_p.h"
22 #include "chartpresenter_p.h"
22 #include "chartpresenter_p.h"
23 #include "abstractchartlayout_p.h"
23 #include "abstractchartlayout_p.h"
24 #include "qabstractaxis.h"
24 #include "qabstractaxis.h"
25 #include "qabstractaxis_p.h"
25 #include "qabstractaxis_p.h"
26 #include <QFontMetrics>
27 #include <QDebug>
26 #include <QDebug>
28
27
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30
29
31 PolarChartAxisAngular::PolarChartAxisAngular(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
30 PolarChartAxisAngular::PolarChartAxisAngular(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
32 : PolarChartAxis(axis, item, intervalAxis)
31 : PolarChartAxis(axis, item, intervalAxis)
33 {
32 {
34 }
33 }
35
34
36 PolarChartAxisAngular::~PolarChartAxisAngular()
35 PolarChartAxisAngular::~PolarChartAxisAngular()
37 {
36 {
38 }
37 }
39
38
40 void PolarChartAxisAngular::updateGeometry()
39 void PolarChartAxisAngular::updateGeometry()
41 {
40 {
42 QGraphicsLayoutItem::updateGeometry();
41 QGraphicsLayoutItem::updateGeometry();
43
42
44 const QVector<qreal> &layout = this->layout();
43 const QVector<qreal> &layout = this->layout();
45 if (layout.isEmpty())
44 if (layout.isEmpty())
46 return;
45 return;
47
46
48 createAxisLabels(layout);
47 createAxisLabels(layout);
49 QStringList labelList = labels();
48 QStringList labelList = labels();
50 QPointF center = axisGeometry().center();
49 QPointF center = axisGeometry().center();
51 QList<QGraphicsItem *> arrowItemList = arrowItems();
50 QList<QGraphicsItem *> arrowItemList = arrowItems();
52 QList<QGraphicsItem *> gridItemList = gridItems();
51 QList<QGraphicsItem *> gridItemList = gridItems();
53 QList<QGraphicsItem *> labelItemList = labelItems();
52 QList<QGraphicsItem *> labelItemList = labelItems();
54 QList<QGraphicsItem *> shadeItemList = shadeItems();
53 QList<QGraphicsItem *> shadeItemList = shadeItems();
55 QGraphicsSimpleTextItem *title = titleItem();
54 QGraphicsSimpleTextItem *title = titleItem();
56
55
57 QGraphicsEllipseItem *axisLine = static_cast<QGraphicsEllipseItem *>(arrowItemList.at(0));
56 QGraphicsEllipseItem *axisLine = static_cast<QGraphicsEllipseItem *>(arrowItemList.at(0));
58 axisLine->setRect(axisGeometry());
57 axisLine->setRect(axisGeometry());
59
58
60 qreal radius = axisGeometry().height() / 2.0;
59 qreal radius = axisGeometry().height() / 2.0;
61
60
62 QFontMetrics fn(axis()->labelsFont());
63 QRectF previousLabelRect;
61 QRectF previousLabelRect;
64 QRectF firstLabelRect;
62 QRectF firstLabelRect;
65
63
66 qreal labelHeight = 0;
64 qreal labelHeight = 0;
67
65
68 bool firstShade = true;
66 bool firstShade = true;
69 bool nextTickVisible = false;
67 bool nextTickVisible = false;
70 if (layout.size())
68 if (layout.size())
71 nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > 360.0);
69 nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > 360.0);
72
70
73 for (int i = 0; i < layout.size(); ++i) {
71 for (int i = 0; i < layout.size(); ++i) {
74 qreal angularCoordinate = layout.at(i);
72 qreal angularCoordinate = layout.at(i);
75
73
76 QGraphicsLineItem *gridLineItem = static_cast<QGraphicsLineItem *>(gridItemList.at(i));
74 QGraphicsLineItem *gridLineItem = static_cast<QGraphicsLineItem *>(gridItemList.at(i));
77 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1));
75 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1));
78 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labelItemList.at(i));
76 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labelItemList.at(i));
79 QGraphicsPathItem *shadeItem = 0;
77 QGraphicsPathItem *shadeItem = 0;
80 if (i == 0)
78 if (i == 0)
81 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
79 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
82 else if (i % 2)
80 else if (i % 2)
83 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1));
81 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1));
84
82
85 // Ignore ticks outside valid range
83 // Ignore ticks outside valid range
86 bool currentTickVisible = nextTickVisible;
84 bool currentTickVisible = nextTickVisible;
87 if ((i == layout.size() - 1)
85 if ((i == layout.size() - 1)
88 || layout.at(i + 1) < 0.0
86 || layout.at(i + 1) < 0.0
89 || layout.at(i + 1) > 360.0) {
87 || layout.at(i + 1) > 360.0) {
90 nextTickVisible = false;
88 nextTickVisible = false;
91 } else {
89 } else {
92 nextTickVisible = true;
90 nextTickVisible = true;
93 }
91 }
94
92
95 qreal labelCoordinate = angularCoordinate;
93 qreal labelCoordinate = angularCoordinate;
96 qreal labelVisible = currentTickVisible;
94 qreal labelVisible = currentTickVisible;
97 if (intervalAxis()) {
95 if (intervalAxis()) {
98 qreal farEdge;
96 qreal farEdge;
99 if (i == (layout.size() - 1))
97 if (i == (layout.size() - 1))
100 farEdge = 360.0;
98 farEdge = 360.0;
101 else
99 else
102 farEdge = qMin(qreal(360.0), layout.at(i + 1));
100 farEdge = qMin(qreal(360.0), layout.at(i + 1));
103
101
104 // Adjust the labelCoordinate to show it if next tick is visible
102 // Adjust the labelCoordinate to show it if next tick is visible
105 if (nextTickVisible)
103 if (nextTickVisible)
106 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
104 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
107
105
108 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
106 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
109 // Don't display label once the category gets too small near the axis
107 // Don't display label once the category gets too small near the axis
110 if (labelCoordinate < 5.0 || labelCoordinate > 355.0)
108 if (labelCoordinate < 5.0 || labelCoordinate > 355.0)
111 labelVisible = false;
109 labelVisible = false;
112 else
110 else
113 labelVisible = true;
111 labelVisible = true;
114 }
112 }
115
113
116 // Need this also in label calculations, so determine it first
114 // Need this also in label calculations, so determine it first
117 QLineF tickLine(QLineF::fromPolar(radius - tickWidth(), 90.0 - angularCoordinate).p2(),
115 QLineF tickLine(QLineF::fromPolar(radius - tickWidth(), 90.0 - angularCoordinate).p2(),
118 QLineF::fromPolar(radius + tickWidth(), 90.0 - angularCoordinate).p2());
116 QLineF::fromPolar(radius + tickWidth(), 90.0 - angularCoordinate).p2());
119 tickLine.translate(center);
117 tickLine.translate(center);
120
118
121 // Angular axis label
119 // Angular axis label
122 if (axis()->labelsVisible() && labelVisible) {
120 if (axis()->labelsVisible() && labelVisible) {
123 labelItem->setText(labelList.at(i));
121 labelItem->setText(labelList.at(i));
124 const QRectF &rect = labelItem->boundingRect();
122 const QRectF &rect = labelItem->boundingRect();
125 QPointF labelCenter = rect.center();
123 QPointF labelCenter = rect.center();
126 labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
124 labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
127 QRectF boundingRect = labelBoundingRect(fn, labelList.at(i));
125 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), labelList.at(i), axis()->labelsAngle());
128 boundingRect.moveCenter(labelCenter);
126 boundingRect.moveCenter(labelCenter);
129 QPointF positionDiff(rect.topLeft() - boundingRect.topLeft());
127 QPointF positionDiff(rect.topLeft() - boundingRect.topLeft());
130
128
131 QPointF labelPoint;
129 QPointF labelPoint;
132 if (intervalAxis()) {
130 if (intervalAxis()) {
133 QLineF labelLine = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate);
131 QLineF labelLine = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate);
134 labelLine.translate(center);
132 labelLine.translate(center);
135 labelPoint = labelLine.p2();
133 labelPoint = labelLine.p2();
136 } else {
134 } else {
137 labelPoint = tickLine.p2();
135 labelPoint = tickLine.p2();
138 }
136 }
139
137
140 QRectF labelRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
138 QRectF labelRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
141 labelItem->setPos(labelRect.topLeft() + positionDiff);
139 labelItem->setPos(labelRect.topLeft() + positionDiff);
142
140
143 // Store height for title calculations
141 // Store height for title calculations
144 qreal labelClearance = axisGeometry().top() - labelRect.top();
142 qreal labelClearance = axisGeometry().top() - labelRect.top();
145 labelHeight = qMax(labelHeight, labelClearance);
143 labelHeight = qMax(labelHeight, labelClearance);
146
144
147 // Label overlap detection
145 // Label overlap detection
148 if (i && (previousLabelRect.intersects(labelRect) || firstLabelRect.intersects(labelRect))) {
146 if (i && (previousLabelRect.intersects(labelRect) || firstLabelRect.intersects(labelRect))) {
149 labelVisible = false;
147 labelVisible = false;
150 } else {
148 } else {
151 // Store labelRect for future comparison. Some area is deducted to make things look
149 // Store labelRect for future comparison. Some area is deducted to make things look
152 // little nicer, as usually intersection happens at label corner with angular labels.
150 // little nicer, as usually intersection happens at label corner with angular labels.
153 labelRect.adjust(-2.0, -4.0, -2.0, -4.0);
151 labelRect.adjust(-2.0, -4.0, -2.0, -4.0);
154 if (firstLabelRect.isEmpty())
152 if (firstLabelRect.isEmpty())
155 firstLabelRect = labelRect;
153 firstLabelRect = labelRect;
156
154
157 previousLabelRect = labelRect;
155 previousLabelRect = labelRect;
158 labelVisible = true;
156 labelVisible = true;
159 }
157 }
160 }
158 }
161
159
162 labelItem->setVisible(labelVisible);
160 labelItem->setVisible(labelVisible);
163 if (!currentTickVisible) {
161 if (!currentTickVisible) {
164 gridLineItem->setVisible(false);
162 gridLineItem->setVisible(false);
165 tickItem->setVisible(false);
163 tickItem->setVisible(false);
166 if (shadeItem)
164 if (shadeItem)
167 shadeItem->setVisible(false);
165 shadeItem->setVisible(false);
168 continue;
166 continue;
169 }
167 }
170
168
171 // Angular grid line
169 // Angular grid line
172 QLineF gridLine = QLineF::fromPolar(radius, 90.0 - angularCoordinate);
170 QLineF gridLine = QLineF::fromPolar(radius, 90.0 - angularCoordinate);
173 gridLine.translate(center);
171 gridLine.translate(center);
174 gridLineItem->setLine(gridLine);
172 gridLineItem->setLine(gridLine);
175 gridLineItem->setVisible(true);
173 gridLineItem->setVisible(true);
176
174
177 // Tick
175 // Tick
178 tickItem->setLine(tickLine);
176 tickItem->setLine(tickLine);
179 tickItem->setVisible(true);
177 tickItem->setVisible(true);
180
178
181 // Shades
179 // Shades
182 if (i % 2 || (i == 0 && !nextTickVisible)) {
180 if (i % 2 || (i == 0 && !nextTickVisible)) {
183 QPainterPath path;
181 QPainterPath path;
184 path.moveTo(center);
182 path.moveTo(center);
185 if (i == 0) {
183 if (i == 0) {
186 // If first tick is also the last, we need to custom fill the first partial arc
184 // If first tick is also the last, we need to custom fill the first partial arc
187 // or it won't get filled.
185 // or it won't get filled.
188 path.arcTo(axisGeometry(), 90.0 - layout.at(0), layout.at(0));
186 path.arcTo(axisGeometry(), 90.0 - layout.at(0), layout.at(0));
189 path.closeSubpath();
187 path.closeSubpath();
190 } else {
188 } else {
191 qreal nextCoordinate;
189 qreal nextCoordinate;
192 if (!nextTickVisible) // Last visible tick
190 if (!nextTickVisible) // Last visible tick
193 nextCoordinate = 360.0;
191 nextCoordinate = 360.0;
194 else
192 else
195 nextCoordinate = layout.at(i + 1);
193 nextCoordinate = layout.at(i + 1);
196 qreal arcSpan = angularCoordinate - nextCoordinate;
194 qreal arcSpan = angularCoordinate - nextCoordinate;
197 path.arcTo(axisGeometry(), 90.0 - angularCoordinate, arcSpan);
195 path.arcTo(axisGeometry(), 90.0 - angularCoordinate, arcSpan);
198 path.closeSubpath();
196 path.closeSubpath();
199
197
200 // Add additional arc for first shade item if there is a partial arc to be filled
198 // Add additional arc for first shade item if there is a partial arc to be filled
201 if (firstShade) {
199 if (firstShade) {
202 QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
200 QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
203 if (layout.at(i - 1) > 0.0) {
201 if (layout.at(i - 1) > 0.0) {
204 QPainterPath specialPath;
202 QPainterPath specialPath;
205 specialPath.moveTo(center);
203 specialPath.moveTo(center);
206 specialPath.arcTo(axisGeometry(), 90.0 - layout.at(i - 1), layout.at(i - 1));
204 specialPath.arcTo(axisGeometry(), 90.0 - layout.at(i - 1), layout.at(i - 1));
207 specialPath.closeSubpath();
205 specialPath.closeSubpath();
208 specialShadeItem->setPath(specialPath);
206 specialShadeItem->setPath(specialPath);
209 specialShadeItem->setVisible(true);
207 specialShadeItem->setVisible(true);
210 } else {
208 } else {
211 specialShadeItem->setVisible(false);
209 specialShadeItem->setVisible(false);
212 }
210 }
213 }
211 }
214 }
212 }
215 shadeItem->setPath(path);
213 shadeItem->setPath(path);
216 shadeItem->setVisible(true);
214 shadeItem->setVisible(true);
217 firstShade = false;
215 firstShade = false;
218 }
216 }
219 }
217 }
220
218
221 // Title, centered above the chart
219 // Title, centered above the chart
222 QString titleText = axis()->titleText();
220 QString titleText = axis()->titleText();
223 if (!titleText.isEmpty() && axis()->isTitleVisible()) {
221 if (!titleText.isEmpty() && axis()->isTitleVisible()) {
224 int size(0);
222 title->setText(truncatedText(axis()->titleFont(), titleText, 0.0, axisGeometry().width(), Qt::Horizontal, QRectF()));
225 size = axisGeometry().width();
226
227 QGraphicsSimpleTextItem dummyTitle;
228 dummyTitle.setFont(axis()->titleFont());
229 dummyTitle.setText(titleText);
230 QRectF dummyRect = dummyTitle.boundingRect();
231
232 if (dummyRect.width() > size) {
233 QString string = titleText + "...";
234 while (dummyRect.width() > size && string.length() > 3) {
235 string.remove(string.length() - 4, 1);
236 dummyTitle.setText(string);
237 dummyRect = dummyTitle.boundingRect();
238 }
239 title->setText(string);
240 } else {
241 title->setText(titleText);
242 }
243
223
244 QRectF titleBoundingRect;
224 QRectF titleBoundingRect = title->boundingRect();
245 titleBoundingRect = title->boundingRect();
246 QPointF titleCenter = center - titleBoundingRect.center();
225 QPointF titleCenter = center - titleBoundingRect.center();
247 title->setPos(titleCenter.x(), axisGeometry().top() - qreal(titlePadding()) * 2.0 - titleBoundingRect.height() - labelHeight);
226 title->setPos(titleCenter.x(), axisGeometry().top() - qreal(titlePadding()) * 2.0 - titleBoundingRect.height() - labelHeight);
248 }
227 }
249 }
228 }
250
229
251 Qt::Orientation PolarChartAxisAngular::orientation() const
230 Qt::Orientation PolarChartAxisAngular::orientation() const
252 {
231 {
253 return Qt::Horizontal;
232 return Qt::Horizontal;
254 }
233 }
255
234
256 void PolarChartAxisAngular::createItems(int count)
235 void PolarChartAxisAngular::createItems(int count)
257 {
236 {
258 if (arrowItems().count() == 0) {
237 if (arrowItems().count() == 0) {
259 // angular axis line
238 // angular axis line
260 // TODO: need class similar to LineArrowItem for click handling?
239 // TODO: need class similar to LineArrowItem for click handling?
261 QGraphicsEllipseItem *arrow = new QGraphicsEllipseItem(presenter()->rootItem());
240 QGraphicsEllipseItem *arrow = new QGraphicsEllipseItem(presenter()->rootItem());
262 arrow->setPen(axis()->linePen());
241 arrow->setPen(axis()->linePen());
263 arrowGroup()->addToGroup(arrow);
242 arrowGroup()->addToGroup(arrow);
264 }
243 }
265
244
266 for (int i = 0; i < count; ++i) {
245 for (int i = 0; i < count; ++i) {
267 QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
246 QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
268 QGraphicsLineItem *grid = new QGraphicsLineItem(presenter()->rootItem());
247 QGraphicsLineItem *grid = new QGraphicsLineItem(presenter()->rootItem());
269 QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem(presenter()->rootItem());
248 QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem(presenter()->rootItem());
270 QGraphicsSimpleTextItem *title = titleItem();
249 QGraphicsSimpleTextItem *title = titleItem();
271 arrow->setPen(axis()->linePen());
250 arrow->setPen(axis()->linePen());
272 grid->setPen(axis()->gridLinePen());
251 grid->setPen(axis()->gridLinePen());
273 label->setFont(axis()->labelsFont());
252 label->setFont(axis()->labelsFont());
274 label->setPen(axis()->labelsPen());
253 label->setPen(axis()->labelsPen());
275 label->setBrush(axis()->labelsBrush());
254 label->setBrush(axis()->labelsBrush());
276 label->setRotation(axis()->labelsAngle());
255 label->setRotation(axis()->labelsAngle());
277 title->setFont(axis()->titleFont());
256 title->setFont(axis()->titleFont());
278 title->setPen(axis()->titlePen());
257 title->setPen(axis()->titlePen());
279 title->setBrush(axis()->titleBrush());
258 title->setBrush(axis()->titleBrush());
280 title->setText(axis()->titleText());
259 title->setText(axis()->titleText());
281 arrowGroup()->addToGroup(arrow);
260 arrowGroup()->addToGroup(arrow);
282 gridGroup()->addToGroup(grid);
261 gridGroup()->addToGroup(grid);
283 labelGroup()->addToGroup(label);
262 labelGroup()->addToGroup(label);
284 if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) {
263 if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) {
285 QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem());
264 QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem());
286 shade->setPen(axis()->shadesPen());
265 shade->setPen(axis()->shadesPen());
287 shade->setBrush(axis()->shadesBrush());
266 shade->setBrush(axis()->shadesBrush());
288 shadeGroup()->addToGroup(shade);
267 shadeGroup()->addToGroup(shade);
289 }
268 }
290 }
269 }
291 }
270 }
292
271
293 void PolarChartAxisAngular::handleArrowPenChanged(const QPen &pen)
272 void PolarChartAxisAngular::handleArrowPenChanged(const QPen &pen)
294 {
273 {
295 bool first = true;
274 bool first = true;
296 foreach (QGraphicsItem *item, arrowItems()) {
275 foreach (QGraphicsItem *item, arrowItems()) {
297 if (first) {
276 if (first) {
298 first = false;
277 first = false;
299 // First arrow item is the outer circle of axis
278 // First arrow item is the outer circle of axis
300 static_cast<QGraphicsEllipseItem *>(item)->setPen(pen);
279 static_cast<QGraphicsEllipseItem *>(item)->setPen(pen);
301 } else {
280 } else {
302 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
281 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
303 }
282 }
304 }
283 }
305 }
284 }
306
285
307 void PolarChartAxisAngular::handleGridPenChanged(const QPen &pen)
286 void PolarChartAxisAngular::handleGridPenChanged(const QPen &pen)
308 {
287 {
309 foreach (QGraphicsItem *item, gridItems())
288 foreach (QGraphicsItem *item, gridItems())
310 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
289 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
311 }
290 }
312
291
313 QSizeF PolarChartAxisAngular::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
292 QSizeF PolarChartAxisAngular::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
314 {
293 {
315 Q_UNUSED(which);
294 Q_UNUSED(which);
316 Q_UNUSED(constraint);
295 Q_UNUSED(constraint);
317 return QSizeF(-1, -1);
296 return QSizeF(-1, -1);
318 }
297 }
319
298
320 qreal PolarChartAxisAngular::preferredAxisRadius(const QSizeF &maxSize)
299 qreal PolarChartAxisAngular::preferredAxisRadius(const QSizeF &maxSize)
321 {
300 {
322 qreal radius = maxSize.height() / 2.0;
301 qreal radius = maxSize.height() / 2.0;
323 if (maxSize.width() < maxSize.height())
302 if (maxSize.width() < maxSize.height())
324 radius = maxSize.width() / 2.0;
303 radius = maxSize.width() / 2.0;
325
304
326 if (axis()->labelsVisible()) {
305 if (axis()->labelsVisible()) {
327 QVector<qreal> layout = calculateLayout();
306 QVector<qreal> layout = calculateLayout();
328 if (layout.isEmpty())
307 if (layout.isEmpty())
329 return radius;
308 return radius;
330
309
331 createAxisLabels(layout);
310 createAxisLabels(layout);
332 QStringList labelList = labels();
311 QStringList labelList = labels();
333 QFont font = axis()->labelsFont();
312 QFont font = axis()->labelsFont();
334
313
335 QRectF maxRect;
314 QRectF maxRect;
336 maxRect.setSize(maxSize);
315 maxRect.setSize(maxSize);
337 maxRect.moveCenter(QPointF(0.0, 0.0));
316 maxRect.moveCenter(QPointF(0.0, 0.0));
338
317
339 // This is a horrible way to find out the maximum radius for angular axis and its labels.
318 // This is a horrible way to find out the maximum radius for angular axis and its labels.
340 // It just increments the radius down until everyhing fits the constraint size.
319 // It just increments the radius down until everyhing fits the constraint size.
341 // Proper way would be to actually calculate it but this seems to work reasonably fast as it is.
320 // Proper way would be to actually calculate it but this seems to work reasonably fast as it is.
342 QFontMetrics fm(font);
343 bool nextTickVisible = false;
321 bool nextTickVisible = false;
344 for (int i = 0; i < layout.size(); ) {
322 for (int i = 0; i < layout.size(); ) {
345 if ((i == layout.size() - 1)
323 if ((i == layout.size() - 1)
346 || layout.at(i + 1) < 0.0
324 || layout.at(i + 1) < 0.0
347 || layout.at(i + 1) > 360.0) {
325 || layout.at(i + 1) > 360.0) {
348 nextTickVisible = false;
326 nextTickVisible = false;
349 } else {
327 } else {
350 nextTickVisible = true;
328 nextTickVisible = true;
351 }
329 }
352
330
353 qreal labelCoordinate = layout.at(i);
331 qreal labelCoordinate = layout.at(i);
354 qreal labelVisible;
332 qreal labelVisible;
355
333
356 if (intervalAxis()) {
334 if (intervalAxis()) {
357 qreal farEdge;
335 qreal farEdge;
358 if (i == (layout.size() - 1))
336 if (i == (layout.size() - 1))
359 farEdge = 360.0;
337 farEdge = 360.0;
360 else
338 else
361 farEdge = qMin(qreal(360.0), layout.at(i + 1));
339 farEdge = qMin(qreal(360.0), layout.at(i + 1));
362
340
363 // Adjust the labelCoordinate to show it if next tick is visible
341 // Adjust the labelCoordinate to show it if next tick is visible
364 if (nextTickVisible)
342 if (nextTickVisible)
365 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
343 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
366
344
367 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
345 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
368 }
346 }
369
347
370 if (labelCoordinate < 0.0 || labelCoordinate > 360.0)
348 if (labelCoordinate < 0.0 || labelCoordinate > 360.0)
371 labelVisible = false;
349 labelVisible = false;
372 else
350 else
373 labelVisible = true;
351 labelVisible = true;
374
352
375 if (!labelVisible) {
353 if (!labelVisible) {
376 i++;
354 i++;
377 continue;
355 continue;
378 }
356 }
379
357
380 QRectF boundingRect = labelBoundingRect(fm, labelList.at(i));
358 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), labelList.at(i), axis()->labelsAngle());
381 QPointF labelPoint = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate).p2();
359 QPointF labelPoint = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate).p2();
382
360
383 boundingRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
361 boundingRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
384 if (boundingRect.isEmpty() || maxRect.intersected(boundingRect) == boundingRect) {
362 if (boundingRect.isEmpty() || maxRect.intersected(boundingRect) == boundingRect) {
385 i++;
363 i++;
386 } else {
364 } else {
387 radius -= 1.0;
365 radius -= 1.0;
388 if (radius < 1.0) // safeguard
366 if (radius < 1.0) // safeguard
389 return 1.0;
367 return 1.0;
390 }
368 }
391 }
369 }
392 }
370 }
393
371
394 if (!axis()->titleText().isEmpty() && axis()->isTitleVisible()) {
372 if (!axis()->titleText().isEmpty() && axis()->isTitleVisible()) {
395 QGraphicsSimpleTextItem dummyTitle;
373 QRectF titleRect = textBoundingRect(axis()->titleFont(), axis()->titleText());
396 dummyTitle.setFont(axis()->titleFont());
397 dummyTitle.setText(axis()->titleText());
398 QRectF dummyRect = dummyTitle.boundingRect();
399
374
400 radius -= titlePadding() + (dummyRect.height() / 2.0);
375 radius -= titlePadding() + (titleRect.height() / 2.0);
401 if (radius < 1.0) // safeguard
376 if (radius < 1.0) // safeguard
402 return 1.0;
377 return 1.0;
403 }
378 }
404
379
405 return radius;
380 return radius;
406 }
381 }
407
382
408 QRectF PolarChartAxisAngular::moveLabelToPosition(qreal angularCoordinate, QPointF labelPoint, QRectF labelRect) const
383 QRectF PolarChartAxisAngular::moveLabelToPosition(qreal angularCoordinate, QPointF labelPoint, QRectF labelRect) const
409 {
384 {
410 // TODO use fuzzy compare for "==" cases?
385 // TODO use fuzzy compare for "==" cases?
411 // TODO Adjust the rect position near 0, 90, 180, and 270 angles for smoother animation?
386 // TODO Adjust the rect position near 0, 90, 180, and 270 angles for smoother animation?
412 if (angularCoordinate == 0.0)
387 if (angularCoordinate == 0.0)
413 labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0));
388 labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0));
414 else if (angularCoordinate < 90.0)
389 else if (angularCoordinate < 90.0)
415 labelRect.moveBottomLeft(labelPoint);
390 labelRect.moveBottomLeft(labelPoint);
416 else if (angularCoordinate == 90.0)
391 else if (angularCoordinate == 90.0)
417 labelRect.moveCenter(labelPoint + QPointF(labelRect.width() / 2.0 + 2.0, 0)); // +2 so that it does not hit the radial axis
392 labelRect.moveCenter(labelPoint + QPointF(labelRect.width() / 2.0 + 2.0, 0)); // +2 so that it does not hit the radial axis
418 else if (angularCoordinate < 180.0)
393 else if (angularCoordinate < 180.0)
419 labelRect.moveTopLeft(labelPoint);
394 labelRect.moveTopLeft(labelPoint);
420 else if (angularCoordinate == 180.0)
395 else if (angularCoordinate == 180.0)
421 labelRect.moveCenter(labelPoint + QPointF(0, labelRect.height() / 2.0));
396 labelRect.moveCenter(labelPoint + QPointF(0, labelRect.height() / 2.0));
422 else if (angularCoordinate < 270.0)
397 else if (angularCoordinate < 270.0)
423 labelRect.moveTopRight(labelPoint);
398 labelRect.moveTopRight(labelPoint);
424 else if (angularCoordinate == 270.0)
399 else if (angularCoordinate == 270.0)
425 labelRect.moveCenter(labelPoint + QPointF(-labelRect.width() / 2.0 - 2.0, 0)); // -2 so that it does not hit the radial axis
400 labelRect.moveCenter(labelPoint + QPointF(-labelRect.width() / 2.0 - 2.0, 0)); // -2 so that it does not hit the radial axis
426 else if (angularCoordinate < 360.0)
401 else if (angularCoordinate < 360.0)
427 labelRect.moveBottomRight(labelPoint);
402 labelRect.moveBottomRight(labelPoint);
428 else
403 else
429 labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0));
404 labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0));
430 return labelRect;
405 return labelRect;
431 }
406 }
432
407
433 #include "moc_polarchartaxisangular_p.cpp"
408 #include "moc_polarchartaxisangular_p.cpp"
434
409
435 QTCOMMERCIALCHART_END_NAMESPACE
410 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,308 +1,290
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "polarchartaxisradial_p.h"
21 #include "polarchartaxisradial_p.h"
22 #include "chartpresenter_p.h"
22 #include "chartpresenter_p.h"
23 #include "abstractchartlayout_p.h"
23 #include "abstractchartlayout_p.h"
24 #include "qabstractaxis_p.h"
24 #include "qabstractaxis_p.h"
25 #include "linearrowitem_p.h"
25 #include "linearrowitem_p.h"
26 #include <QFontMetrics>
27
26
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29
28
30 PolarChartAxisRadial::PolarChartAxisRadial(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
29 PolarChartAxisRadial::PolarChartAxisRadial(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
31 : PolarChartAxis(axis, item, intervalAxis)
30 : PolarChartAxis(axis, item, intervalAxis)
32 {
31 {
33 }
32 }
34
33
35 PolarChartAxisRadial::~PolarChartAxisRadial()
34 PolarChartAxisRadial::~PolarChartAxisRadial()
36 {
35 {
37 }
36 }
38
37
39 void PolarChartAxisRadial::updateGeometry()
38 void PolarChartAxisRadial::updateGeometry()
40 {
39 {
41 const QVector<qreal> &layout = this->layout();
40 const QVector<qreal> &layout = this->layout();
42 if (layout.isEmpty())
41 if (layout.isEmpty())
43 return;
42 return;
44
43
45 createAxisLabels(layout);
44 createAxisLabels(layout);
46 QStringList labelList = labels();
45 QStringList labelList = labels();
47 QPointF center = axisGeometry().center();
46 QPointF center = axisGeometry().center();
48 QList<QGraphicsItem *> arrowItemList = arrowItems();
47 QList<QGraphicsItem *> arrowItemList = arrowItems();
49 QList<QGraphicsItem *> gridItemList = gridItems();
48 QList<QGraphicsItem *> gridItemList = gridItems();
50 QList<QGraphicsItem *> labelItemList = labelItems();
49 QList<QGraphicsItem *> labelItemList = labelItems();
51 QList<QGraphicsItem *> shadeItemList = shadeItems();
50 QList<QGraphicsItem *> shadeItemList = shadeItems();
52 QGraphicsSimpleTextItem* title = titleItem();
51 QGraphicsSimpleTextItem* title = titleItem();
53 qreal radius = axisGeometry().height() / 2.0;
52 qreal radius = axisGeometry().height() / 2.0;
54
53
55 QLineF line(center, center + QPointF(0, -radius));
54 QLineF line(center, center + QPointF(0, -radius));
56 QGraphicsLineItem *axisLine = static_cast<QGraphicsLineItem *>(arrowItemList.at(0));
55 QGraphicsLineItem *axisLine = static_cast<QGraphicsLineItem *>(arrowItemList.at(0));
57 axisLine->setLine(line);
56 axisLine->setLine(line);
58
57
59 QFontMetrics fn(axis()->labelsFont());
60 QRectF previousLabelRect;
58 QRectF previousLabelRect;
61 bool firstShade = true;
59 bool firstShade = true;
62 bool nextTickVisible = false;
60 bool nextTickVisible = false;
63 if (layout.size())
61 if (layout.size())
64 nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > radius);
62 nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > radius);
65
63
66 for (int i = 0; i < layout.size(); ++i) {
64 for (int i = 0; i < layout.size(); ++i) {
67 qreal radialCoordinate = layout.at(i);
65 qreal radialCoordinate = layout.at(i);
68
66
69 QGraphicsEllipseItem *gridItem = static_cast<QGraphicsEllipseItem *>(gridItemList.at(i));
67 QGraphicsEllipseItem *gridItem = static_cast<QGraphicsEllipseItem *>(gridItemList.at(i));
70 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1));
68 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1));
71 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labelItemList.at(i));
69 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labelItemList.at(i));
72 QGraphicsPathItem *shadeItem = 0;
70 QGraphicsPathItem *shadeItem = 0;
73 if (i == 0)
71 if (i == 0)
74 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
72 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
75 else if (i % 2)
73 else if (i % 2)
76 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1));
74 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1));
77
75
78 // Ignore ticks outside valid range
76 // Ignore ticks outside valid range
79 bool currentTickVisible = nextTickVisible;
77 bool currentTickVisible = nextTickVisible;
80 if ((i == layout.size() - 1)
78 if ((i == layout.size() - 1)
81 || layout.at(i + 1) < 0.0
79 || layout.at(i + 1) < 0.0
82 || layout.at(i + 1) > radius) {
80 || layout.at(i + 1) > radius) {
83 nextTickVisible = false;
81 nextTickVisible = false;
84 } else {
82 } else {
85 nextTickVisible = true;
83 nextTickVisible = true;
86 }
84 }
87
85
88 qreal labelCoordinate = radialCoordinate;
86 qreal labelCoordinate = radialCoordinate;
89 qreal labelVisible = currentTickVisible;
87 qreal labelVisible = currentTickVisible;
90 qreal labelPad = labelPadding() / 2.0;
88 qreal labelPad = labelPadding() / 2.0;
91 if (intervalAxis()) {
89 if (intervalAxis()) {
92 qreal farEdge;
90 qreal farEdge;
93 if (i == (layout.size() - 1))
91 if (i == (layout.size() - 1))
94 farEdge = radius;
92 farEdge = radius;
95 else
93 else
96 farEdge = qMin(radius, layout.at(i + 1));
94 farEdge = qMin(radius, layout.at(i + 1));
97
95
98 // Adjust the labelCoordinate to show it if next tick is visible
96 // Adjust the labelCoordinate to show it if next tick is visible
99 if (nextTickVisible)
97 if (nextTickVisible)
100 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
98 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
101
99
102 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
100 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
103 if (labelCoordinate > 0.0 && labelCoordinate < radius)
101 if (labelCoordinate > 0.0 && labelCoordinate < radius)
104 labelVisible = true;
102 labelVisible = true;
105 else
103 else
106 labelVisible = false;
104 labelVisible = false;
107 }
105 }
108
106
109 // Radial axis label
107 // Radial axis label
110 if (axis()->labelsVisible() && labelVisible) {
108 if (axis()->labelsVisible() && labelVisible) {
111 labelItem->setText(labelList.at(i));
109 labelItem->setText(labelList.at(i));
112 QRectF labelRect = labelItem->boundingRect();
110 QRectF labelRect = labelItem->boundingRect();
113 QPointF labelCenter = labelRect.center();
111 QPointF labelCenter = labelRect.center();
114 labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
112 labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
115 QRectF boundingRect = labelBoundingRect(fn, labelList.at(i));
113 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), labelList.at(i), axis()->labelsAngle());
116 boundingRect.moveCenter(labelCenter);
114 boundingRect.moveCenter(labelCenter);
117 QPointF positionDiff(labelRect.topLeft() - boundingRect.topLeft());
115 QPointF positionDiff(labelRect.topLeft() - boundingRect.topLeft());
118 QPointF labelPoint = center;
116 QPointF labelPoint = center;
119 if (intervalAxis())
117 if (intervalAxis())
120 labelPoint += QPointF(labelPad, -labelCoordinate - (boundingRect.height() / 2.0));
118 labelPoint += QPointF(labelPad, -labelCoordinate - (boundingRect.height() / 2.0));
121 else
119 else
122 labelPoint += QPointF(labelPad, labelPad - labelCoordinate);
120 labelPoint += QPointF(labelPad, labelPad - labelCoordinate);
123 labelRect.moveTopLeft(labelPoint);
121 labelRect.moveTopLeft(labelPoint);
124 labelItem->setPos(labelRect.topLeft() + positionDiff);
122 labelItem->setPos(labelRect.topLeft() + positionDiff);
125
123
126 // Label overlap detection
124 // Label overlap detection
127 labelRect.setSize(boundingRect.size());
125 labelRect.setSize(boundingRect.size());
128 if ((i && previousLabelRect.intersects(labelRect))
126 if ((i && previousLabelRect.intersects(labelRect))
129 || !axisGeometry().contains(labelRect)) {
127 || !axisGeometry().contains(labelRect)) {
130 labelVisible = false;
128 labelVisible = false;
131 } else {
129 } else {
132 previousLabelRect = labelRect;
130 previousLabelRect = labelRect;
133 labelVisible = true;
131 labelVisible = true;
134 }
132 }
135 }
133 }
136
134
137 labelItem->setVisible(labelVisible);
135 labelItem->setVisible(labelVisible);
138 if (!currentTickVisible) {
136 if (!currentTickVisible) {
139 gridItem->setVisible(false);
137 gridItem->setVisible(false);
140 tickItem->setVisible(false);
138 tickItem->setVisible(false);
141 if (shadeItem)
139 if (shadeItem)
142 shadeItem->setVisible(false);
140 shadeItem->setVisible(false);
143 continue;
141 continue;
144 }
142 }
145
143
146 // Radial grid line
144 // Radial grid line
147 QRectF gridRect;
145 QRectF gridRect;
148 gridRect.setWidth(radialCoordinate * 2.0);
146 gridRect.setWidth(radialCoordinate * 2.0);
149 gridRect.setHeight(radialCoordinate * 2.0);
147 gridRect.setHeight(radialCoordinate * 2.0);
150 gridRect.moveCenter(center);
148 gridRect.moveCenter(center);
151
149
152 gridItem->setRect(gridRect);
150 gridItem->setRect(gridRect);
153 gridItem->setVisible(true);
151 gridItem->setVisible(true);
154
152
155 // Tick
153 // Tick
156 QLineF tickLine(-tickWidth(), 0.0, tickWidth(), 0.0);
154 QLineF tickLine(-tickWidth(), 0.0, tickWidth(), 0.0);
157 tickLine.translate(center.rx(), gridRect.top());
155 tickLine.translate(center.rx(), gridRect.top());
158 tickItem->setLine(tickLine);
156 tickItem->setLine(tickLine);
159 tickItem->setVisible(true);
157 tickItem->setVisible(true);
160
158
161 // Shades
159 // Shades
162 if (i % 2 || (i == 0 && !nextTickVisible)) {
160 if (i % 2 || (i == 0 && !nextTickVisible)) {
163 QPainterPath path;
161 QPainterPath path;
164 if (i == 0) {
162 if (i == 0) {
165 // If first tick is also the last, we need to custom fill the inner circle
163 // If first tick is also the last, we need to custom fill the inner circle
166 // or it won't get filled.
164 // or it won't get filled.
167 QRectF innerCircle(0.0, 0.0, layout.at(0) * 2.0, layout.at(0) * 2.0);
165 QRectF innerCircle(0.0, 0.0, layout.at(0) * 2.0, layout.at(0) * 2.0);
168 innerCircle.moveCenter(center);
166 innerCircle.moveCenter(center);
169 path.addEllipse(innerCircle);
167 path.addEllipse(innerCircle);
170 } else {
168 } else {
171 QRectF otherGridRect;
169 QRectF otherGridRect;
172 if (!nextTickVisible) { // Last visible tick
170 if (!nextTickVisible) { // Last visible tick
173 otherGridRect = axisGeometry();
171 otherGridRect = axisGeometry();
174 } else {
172 } else {
175 qreal otherGridRectDimension = layout.at(i + 1) * 2.0;
173 qreal otherGridRectDimension = layout.at(i + 1) * 2.0;
176 otherGridRect.setWidth(otherGridRectDimension);
174 otherGridRect.setWidth(otherGridRectDimension);
177 otherGridRect.setHeight(otherGridRectDimension);
175 otherGridRect.setHeight(otherGridRectDimension);
178 otherGridRect.moveCenter(center);
176 otherGridRect.moveCenter(center);
179 }
177 }
180 path.addEllipse(gridRect);
178 path.addEllipse(gridRect);
181 path.addEllipse(otherGridRect);
179 path.addEllipse(otherGridRect);
182
180
183 // Add additional shading in first visible shade item if there is a partial tick
181 // Add additional shading in first visible shade item if there is a partial tick
184 // to be filled at the center (log & category axes)
182 // to be filled at the center (log & category axes)
185 if (firstShade) {
183 if (firstShade) {
186 QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
184 QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
187 if (layout.at(i - 1) > 0.0) {
185 if (layout.at(i - 1) > 0.0) {
188 QRectF innerCircle(0.0, 0.0, layout.at(i - 1) * 2.0, layout.at(i - 1) * 2.0);
186 QRectF innerCircle(0.0, 0.0, layout.at(i - 1) * 2.0, layout.at(i - 1) * 2.0);
189 innerCircle.moveCenter(center);
187 innerCircle.moveCenter(center);
190 QPainterPath specialPath;
188 QPainterPath specialPath;
191 specialPath.addEllipse(innerCircle);
189 specialPath.addEllipse(innerCircle);
192 specialShadeItem->setPath(specialPath);
190 specialShadeItem->setPath(specialPath);
193 specialShadeItem->setVisible(true);
191 specialShadeItem->setVisible(true);
194 } else {
192 } else {
195 specialShadeItem->setVisible(false);
193 specialShadeItem->setVisible(false);
196 }
194 }
197 }
195 }
198 }
196 }
199 shadeItem->setPath(path);
197 shadeItem->setPath(path);
200 shadeItem->setVisible(true);
198 shadeItem->setVisible(true);
201 firstShade = false;
199 firstShade = false;
202 }
200 }
203 }
201 }
204
202
205 // Title, along the 0 axis
203 // Title, along the 0 axis
206 QString titleText = axis()->titleText();
204 QString titleText = axis()->titleText();
207 if (!titleText.isEmpty() && axis()->isTitleVisible()) {
205 if (!titleText.isEmpty() && axis()->isTitleVisible()) {
208 QGraphicsSimpleTextItem dummyTitle;
206 title->setText(truncatedText(axis()->titleFont(), titleText, 0.0, radius, Qt::Horizontal, QRectF()));
209 dummyTitle.setFont(axis()->titleFont());
210 dummyTitle.setText(titleText);
211 QRectF dummyRect = dummyTitle.boundingRect();
212
213 if (dummyRect.width() > radius) {
214 QString string = titleText + "...";
215 while (dummyRect.width() > radius && string.length() > 3) {
216 string.remove(string.length() - 4, 1);
217 dummyTitle.setText(string);
218 dummyRect = dummyTitle.boundingRect();
219 }
220 title->setText(string);
221 } else {
222 title->setText(titleText);
223 }
224
207
225 QRectF titleBoundingRect;
208 QRectF titleBoundingRect = title->boundingRect();
226 titleBoundingRect = title->boundingRect();
227 QPointF titleCenter = titleBoundingRect.center();
209 QPointF titleCenter = titleBoundingRect.center();
228 QPointF arrowCenter = axisLine->boundingRect().center();
210 QPointF arrowCenter = axisLine->boundingRect().center();
229 QPointF titleCenterDiff = arrowCenter - titleCenter;
211 QPointF titleCenterDiff = arrowCenter - titleCenter;
230 title->setPos(titleCenterDiff.x() - qreal(titlePadding()) - (titleBoundingRect.height() / 2.0), titleCenterDiff.y());
212 title->setPos(titleCenterDiff.x() - qreal(titlePadding()) - (titleBoundingRect.height() / 2.0), titleCenterDiff.y());
231 title->setTransformOriginPoint(titleCenter);
213 title->setTransformOriginPoint(titleCenter);
232 title->setRotation(270.0);
214 title->setRotation(270.0);
233 }
215 }
234
216
235 QGraphicsLayoutItem::updateGeometry();
217 QGraphicsLayoutItem::updateGeometry();
236 }
218 }
237
219
238 Qt::Orientation PolarChartAxisRadial::orientation() const
220 Qt::Orientation PolarChartAxisRadial::orientation() const
239 {
221 {
240 return Qt::Vertical;
222 return Qt::Vertical;
241 }
223 }
242
224
243 void PolarChartAxisRadial::createItems(int count)
225 void PolarChartAxisRadial::createItems(int count)
244 {
226 {
245 if (arrowItems().count() == 0) {
227 if (arrowItems().count() == 0) {
246 // radial axis center line
228 // radial axis center line
247 QGraphicsLineItem *arrow = new LineArrowItem(this, presenter()->rootItem());
229 QGraphicsLineItem *arrow = new LineArrowItem(this, presenter()->rootItem());
248 arrow->setPen(axis()->linePen());
230 arrow->setPen(axis()->linePen());
249 arrowGroup()->addToGroup(arrow);
231 arrowGroup()->addToGroup(arrow);
250 }
232 }
251
233
252 for (int i = 0; i < count; ++i) {
234 for (int i = 0; i < count; ++i) {
253 QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
235 QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
254 QGraphicsEllipseItem *grid = new QGraphicsEllipseItem(presenter()->rootItem());
236 QGraphicsEllipseItem *grid = new QGraphicsEllipseItem(presenter()->rootItem());
255 QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem(presenter()->rootItem());
237 QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem(presenter()->rootItem());
256 QGraphicsSimpleTextItem *title = titleItem();
238 QGraphicsSimpleTextItem *title = titleItem();
257 arrow->setPen(axis()->linePen());
239 arrow->setPen(axis()->linePen());
258 grid->setPen(axis()->gridLinePen());
240 grid->setPen(axis()->gridLinePen());
259 label->setFont(axis()->labelsFont());
241 label->setFont(axis()->labelsFont());
260 label->setPen(axis()->labelsPen());
242 label->setPen(axis()->labelsPen());
261 label->setBrush(axis()->labelsBrush());
243 label->setBrush(axis()->labelsBrush());
262 label->setRotation(axis()->labelsAngle());
244 label->setRotation(axis()->labelsAngle());
263 title->setFont(axis()->titleFont());
245 title->setFont(axis()->titleFont());
264 title->setPen(axis()->titlePen());
246 title->setPen(axis()->titlePen());
265 title->setBrush(axis()->titleBrush());
247 title->setBrush(axis()->titleBrush());
266 title->setText(axis()->titleText());
248 title->setText(axis()->titleText());
267 arrowGroup()->addToGroup(arrow);
249 arrowGroup()->addToGroup(arrow);
268 gridGroup()->addToGroup(grid);
250 gridGroup()->addToGroup(grid);
269 labelGroup()->addToGroup(label);
251 labelGroup()->addToGroup(label);
270 if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) {
252 if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) {
271 QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem());
253 QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem());
272 shade->setPen(axis()->shadesPen());
254 shade->setPen(axis()->shadesPen());
273 shade->setBrush(axis()->shadesBrush());
255 shade->setBrush(axis()->shadesBrush());
274 shadeGroup()->addToGroup(shade);
256 shadeGroup()->addToGroup(shade);
275 }
257 }
276 }
258 }
277 }
259 }
278
260
279 void PolarChartAxisRadial::handleArrowPenChanged(const QPen &pen)
261 void PolarChartAxisRadial::handleArrowPenChanged(const QPen &pen)
280 {
262 {
281 foreach (QGraphicsItem *item, arrowItems())
263 foreach (QGraphicsItem *item, arrowItems())
282 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
264 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
283 }
265 }
284
266
285 void PolarChartAxisRadial::handleGridPenChanged(const QPen &pen)
267 void PolarChartAxisRadial::handleGridPenChanged(const QPen &pen)
286 {
268 {
287 foreach (QGraphicsItem *item, gridItems())
269 foreach (QGraphicsItem *item, gridItems())
288 static_cast<QGraphicsEllipseItem *>(item)->setPen(pen);
270 static_cast<QGraphicsEllipseItem *>(item)->setPen(pen);
289 }
271 }
290
272
291 QSizeF PolarChartAxisRadial::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
273 QSizeF PolarChartAxisRadial::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
292 {
274 {
293 Q_UNUSED(which);
275 Q_UNUSED(which);
294 Q_UNUSED(constraint);
276 Q_UNUSED(constraint);
295 return QSizeF(-1.0, -1.0);
277 return QSizeF(-1.0, -1.0);
296 }
278 }
297
279
298 qreal PolarChartAxisRadial::preferredAxisRadius(const QSizeF &maxSize)
280 qreal PolarChartAxisRadial::preferredAxisRadius(const QSizeF &maxSize)
299 {
281 {
300 qreal radius = maxSize.height() / 2.0;
282 qreal radius = maxSize.height() / 2.0;
301 if (maxSize.width() < maxSize.height())
283 if (maxSize.width() < maxSize.height())
302 radius = maxSize.width() / 2.0;
284 radius = maxSize.width() / 2.0;
303 return radius;
285 return radius;
304 }
286 }
305
287
306 #include "moc_polarchartaxisradial_p.cpp"
288 #include "moc_polarchartaxisradial_p.cpp"
307
289
308 QTCOMMERCIALCHART_END_NAMESPACE
290 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,132 +1,128
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartvalueaxisx_p.h"
21 #include "chartvalueaxisx_p.h"
22 #include "qabstractaxis.h"
22 #include "qabstractaxis.h"
23 #include "chartpresenter_p.h"
23 #include "chartpresenter_p.h"
24 #include "qvalueaxis.h"
24 #include "qvalueaxis.h"
25 #include "abstractchartlayout_p.h"
25 #include "abstractchartlayout_p.h"
26 #include <QGraphicsLayout>
26 #include <QGraphicsLayout>
27 #include <QFontMetrics>
28 #include <qmath.h>
27 #include <qmath.h>
29 #include <QDebug>
28 #include <QDebug>
30
29
31
30
32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33
32
34 ChartValueAxisX::ChartValueAxisX(QValueAxis *axis, QGraphicsItem *item )
33 ChartValueAxisX::ChartValueAxisX(QValueAxis *axis, QGraphicsItem *item )
35 : HorizontalAxis(axis, item),
34 : HorizontalAxis(axis, item),
36 m_axis(axis)
35 m_axis(axis)
37 {
36 {
38 QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
37 QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
39 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
38 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
40 }
39 }
41
40
42 ChartValueAxisX::~ChartValueAxisX()
41 ChartValueAxisX::~ChartValueAxisX()
43 {
42 {
44 }
43 }
45
44
46 QVector<qreal> ChartValueAxisX::calculateLayout() const
45 QVector<qreal> ChartValueAxisX::calculateLayout() const
47 {
46 {
48 int tickCount = m_axis->tickCount();
47 int tickCount = m_axis->tickCount();
49
48
50 Q_ASSERT(tickCount >= 2);
49 Q_ASSERT(tickCount >= 2);
51
50
52 QVector<qreal> points;
51 QVector<qreal> points;
53 points.resize(tickCount);
52 points.resize(tickCount);
54
53
55 const QRectF &gridRect = gridGeometry();
54 const QRectF &gridRect = gridGeometry();
56 const qreal deltaX = gridRect.width() / (qreal(tickCount) - 1.0);
55 const qreal deltaX = gridRect.width() / (qreal(tickCount) - 1.0);
57 for (int i = 0; i < tickCount; ++i)
56 for (int i = 0; i < tickCount; ++i)
58 points[i] = qreal(i) * deltaX + gridRect.left();
57 points[i] = qreal(i) * deltaX + gridRect.left();
59 return points;
58 return points;
60 }
59 }
61
60
62 void ChartValueAxisX::updateGeometry()
61 void ChartValueAxisX::updateGeometry()
63 {
62 {
64 const QVector<qreal>& layout = ChartAxisElement::layout();
63 const QVector<qreal>& layout = ChartAxisElement::layout();
65 if (layout.isEmpty())
64 if (layout.isEmpty())
66 return;
65 return;
67 setLabels(createValueLabels(min(), max(), layout.size(), m_axis->labelFormat()));
66 setLabels(createValueLabels(min(), max(), layout.size(), m_axis->labelFormat()));
68 HorizontalAxis::updateGeometry();
67 HorizontalAxis::updateGeometry();
69 }
68 }
70
69
71 void ChartValueAxisX::handleTickCountChanged(int tick)
70 void ChartValueAxisX::handleTickCountChanged(int tick)
72 {
71 {
73 Q_UNUSED(tick);
72 Q_UNUSED(tick);
74 QGraphicsLayoutItem::updateGeometry();
73 QGraphicsLayoutItem::updateGeometry();
75 if(presenter()) presenter()->layout()->invalidate();
74 if(presenter()) presenter()->layout()->invalidate();
76 }
75 }
77
76
78 void ChartValueAxisX::handleLabelFormatChanged(const QString &format)
77 void ChartValueAxisX::handleLabelFormatChanged(const QString &format)
79 {
78 {
80 Q_UNUSED(format);
79 Q_UNUSED(format);
81 QGraphicsLayoutItem::updateGeometry();
80 QGraphicsLayoutItem::updateGeometry();
82 if(presenter()) presenter()->layout()->invalidate();
81 if(presenter()) presenter()->layout()->invalidate();
83 }
82 }
84
83
85 QSizeF ChartValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
84 QSizeF ChartValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
86 {
85 {
87 Q_UNUSED(constraint)
86 Q_UNUSED(constraint)
88
87
89 QFontMetrics fn(axis()->labelsFont());
90 QSizeF sh;
88 QSizeF sh;
91
89
92 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
90 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
93 QStringList ticksList = createValueLabels(min(),max(),m_axis->tickCount(),m_axis->labelFormat());
91 QStringList ticksList = createValueLabels(min(),max(),m_axis->tickCount(),m_axis->labelFormat());
94 // Width of horizontal axis sizeHint indicates the maximum distance labels can extend past
92 // Width of horizontal axis sizeHint indicates the maximum distance labels can extend past
95 // first and last ticks. Base width is irrelevant.
93 // first and last ticks. Base width is irrelevant.
96 qreal width = 0;
94 qreal width = 0;
97 qreal height = 0;
95 qreal height = 0;
98
96
99 switch (which) {
97 switch (which) {
100 case Qt::MinimumSize: {
98 case Qt::MinimumSize: {
101 QRectF boundingRect = labelBoundingRect(fn, "...");
99 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle());
102 width = boundingRect.width() / 2.0;
100 width = boundingRect.width() / 2.0;
103 height = boundingRect.height() + labelPadding();
101 height = boundingRect.height() + labelPadding() + base.height() + 1.0;
104 height += base.height();
105 sh = QSizeF(width, height);
102 sh = QSizeF(width, height);
106 break;
103 break;
107 }
104 }
108 case Qt::PreferredSize: {
105 case Qt::PreferredSize: {
109 int labelHeight = 0;
106 qreal labelHeight = 0.0;
110 int firstWidth = -1;
107 qreal firstWidth = -1.0;
111 foreach (const QString& s, ticksList) {
108 foreach (const QString& s, ticksList) {
112 QRect rect = labelBoundingRect(fn, s);
109 QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
113 labelHeight = qMax(rect.height(), labelHeight);
110 labelHeight = qMax(rect.height(), labelHeight);
114 width = rect.width();
111 width = rect.width();
115 if (firstWidth < 0)
112 if (firstWidth < 0.0)
116 firstWidth = width;
113 firstWidth = width;
117 }
114 }
118 height = labelHeight + labelPadding();
115 height = labelHeight + labelPadding() + base.height() + 1.0;
119 height += base.height();
116 width = qMax(width, firstWidth) / 2.0;
120 width = qMax(width, qreal(firstWidth)) / 2.0;
121 sh = QSizeF(width, height);
117 sh = QSizeF(width, height);
122 break;
118 break;
123 }
119 }
124 default:
120 default:
125 break;
121 break;
126 }
122 }
127 return sh;
123 return sh;
128 }
124 }
129
125
130 #include "moc_chartvalueaxisx_p.cpp"
126 #include "moc_chartvalueaxisx_p.cpp"
131
127
132 QTCOMMERCIALCHART_END_NAMESPACE
128 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,132 +1,128
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartvalueaxisy_p.h"
21 #include "chartvalueaxisy_p.h"
22 #include "qabstractaxis.h"
22 #include "qabstractaxis.h"
23 #include "chartpresenter_p.h"
23 #include "chartpresenter_p.h"
24 #include "qvalueaxis.h"
24 #include "qvalueaxis.h"
25 #include "abstractchartlayout_p.h"
25 #include "abstractchartlayout_p.h"
26 #include <QGraphicsLayout>
26 #include <QGraphicsLayout>
27 #include <QFontMetrics>
28 #include <qmath.h>
27 #include <qmath.h>
29 #include <QDebug>
28 #include <QDebug>
30
29
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32
31
33 ChartValueAxisY::ChartValueAxisY(QValueAxis *axis, QGraphicsItem *item)
32 ChartValueAxisY::ChartValueAxisY(QValueAxis *axis, QGraphicsItem *item)
34 : VerticalAxis(axis, item),
33 : VerticalAxis(axis, item),
35 m_axis(axis)
34 m_axis(axis)
36 {
35 {
37 QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
36 QObject::connect(m_axis, SIGNAL(tickCountChanged(int)), this, SLOT(handleTickCountChanged(int)));
38 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
37 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
39 }
38 }
40
39
41 ChartValueAxisY::~ChartValueAxisY()
40 ChartValueAxisY::~ChartValueAxisY()
42 {
41 {
43 }
42 }
44
43
45 QVector<qreal> ChartValueAxisY::calculateLayout() const
44 QVector<qreal> ChartValueAxisY::calculateLayout() const
46 {
45 {
47 int tickCount = m_axis->tickCount();
46 int tickCount = m_axis->tickCount();
48
47
49 Q_ASSERT(tickCount >= 2);
48 Q_ASSERT(tickCount >= 2);
50
49
51 QVector<qreal> points;
50 QVector<qreal> points;
52 points.resize(tickCount);
51 points.resize(tickCount);
53
52
54 const QRectF &gridRect = gridGeometry();
53 const QRectF &gridRect = gridGeometry();
55
54
56 const qreal deltaY = gridRect.height() / (qreal(tickCount) - 1.0);
55 const qreal deltaY = gridRect.height() / (qreal(tickCount) - 1.0);
57 for (int i = 0; i < tickCount; ++i)
56 for (int i = 0; i < tickCount; ++i)
58 points[i] = qreal(i) * -deltaY + gridRect.bottom();
57 points[i] = qreal(i) * -deltaY + gridRect.bottom();
59
58
60 return points;
59 return points;
61 }
60 }
62
61
63 void ChartValueAxisY::updateGeometry()
62 void ChartValueAxisY::updateGeometry()
64 {
63 {
65 const QVector<qreal> &layout = ChartAxisElement::layout();
64 const QVector<qreal> &layout = ChartAxisElement::layout();
66 if (layout.isEmpty())
65 if (layout.isEmpty())
67 return;
66 return;
68 setLabels(createValueLabels(min(),max(),layout.size(),m_axis->labelFormat()));
67 setLabels(createValueLabels(min(),max(),layout.size(),m_axis->labelFormat()));
69 VerticalAxis::updateGeometry();
68 VerticalAxis::updateGeometry();
70 }
69 }
71
70
72 void ChartValueAxisY::handleTickCountChanged(int tick)
71 void ChartValueAxisY::handleTickCountChanged(int tick)
73 {
72 {
74 Q_UNUSED(tick);
73 Q_UNUSED(tick);
75 QGraphicsLayoutItem::updateGeometry();
74 QGraphicsLayoutItem::updateGeometry();
76 if(presenter()) presenter()->layout()->invalidate();
75 if(presenter()) presenter()->layout()->invalidate();
77 }
76 }
78
77
79 void ChartValueAxisY::handleLabelFormatChanged(const QString &format)
78 void ChartValueAxisY::handleLabelFormatChanged(const QString &format)
80 {
79 {
81 Q_UNUSED(format);
80 Q_UNUSED(format);
82 QGraphicsLayoutItem::updateGeometry();
81 QGraphicsLayoutItem::updateGeometry();
83 if(presenter()) presenter()->layout()->invalidate();
82 if(presenter()) presenter()->layout()->invalidate();
84 }
83 }
85
84
86 QSizeF ChartValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
85 QSizeF ChartValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
87 {
86 {
88 Q_UNUSED(constraint)
87 Q_UNUSED(constraint)
89
88
90 QFontMetrics fn(axis()->labelsFont());
91 QSizeF sh;
89 QSizeF sh;
92 QSizeF base = VerticalAxis::sizeHint(which, constraint);
90 QSizeF base = VerticalAxis::sizeHint(which, constraint);
93 QStringList ticksList = createValueLabels(min(),max(),m_axis->tickCount(),m_axis->labelFormat());
91 QStringList ticksList = createValueLabels(min(),max(),m_axis->tickCount(),m_axis->labelFormat());
94 qreal width = 0;
92 qreal width = 0;
95 // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
93 // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
96 // first and last ticks. Base height is irrelevant.
94 // first and last ticks. Base height is irrelevant.
97 qreal height = 0;
95 qreal height = 0;
98
96
99 switch (which) {
97 switch (which) {
100 case Qt::MinimumSize: {
98 case Qt::MinimumSize: {
101 QRectF boundingRect = labelBoundingRect(fn, "...");
99 QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle());
102 width = boundingRect.width() + labelPadding();
100 width = boundingRect.width() + labelPadding() + base.width() + 1.0;
103 width += base.width();
104 height = boundingRect.height() / 2.0;
101 height = boundingRect.height() / 2.0;
105 sh = QSizeF(width, height);
102 sh = QSizeF(width, height);
106 break;
103 break;
107 }
104 }
108 case Qt::PreferredSize: {
105 case Qt::PreferredSize: {
109 int labelWidth = 0;
106 qreal labelWidth = 0.0;
110 int firstHeight = -1;
107 qreal firstHeight = -1.0;
111 foreach (const QString& s, ticksList) {
108 foreach (const QString& s, ticksList) {
112 QRect rect = labelBoundingRect(fn, s);
109 QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
113 labelWidth = qMax(rect.width(), labelWidth);
110 labelWidth = qMax(rect.width(), labelWidth);
114 height = rect.height();
111 height = rect.height();
115 if (firstHeight < 0)
112 if (firstHeight < 0.0)
116 firstHeight = height;
113 firstHeight = height;
117 }
114 }
118 width = labelWidth + labelPadding() + 2; //two pixels of tolerance
115 width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance
119 width += base.width();
116 height = qMax(height, firstHeight) / 2.0;
120 height = qMax(height, qreal(firstHeight)) / 2.0;
121 sh = QSizeF(width, height);
117 sh = QSizeF(width, height);
122 break;
118 break;
123 }
119 }
124 default:
120 default:
125 break;
121 break;
126 }
122 }
127 return sh;
123 return sh;
128 }
124 }
129
125
130 #include "moc_chartvalueaxisy_p.cpp"
126 #include "moc_chartvalueaxisy_p.cpp"
131
127
132 QTCOMMERCIALCHART_END_NAMESPACE
128 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,244 +1,210
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "verticalaxis_p.h"
21 #include "verticalaxis_p.h"
22 #include "qabstractaxis.h"
22 #include "qabstractaxis.h"
23 #include <QFontMetrics>
24 #include <QDebug>
23 #include <QDebug>
25
24
26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27
26
28 VerticalAxis::VerticalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
27 VerticalAxis::VerticalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
29 : CartesianChartAxis(axis, item, intervalAxis)
28 : CartesianChartAxis(axis, item, intervalAxis)
30 {
29 {
31 }
30 }
32
31
33 VerticalAxis::~VerticalAxis()
32 VerticalAxis::~VerticalAxis()
34 {
33 {
35 }
34 }
36
35
37 void VerticalAxis::updateGeometry()
36 void VerticalAxis::updateGeometry()
38 {
37 {
39 const QVector<qreal> &layout = ChartAxisElement::layout();
38 const QVector<qreal> &layout = ChartAxisElement::layout();
40
39
41 if (layout.isEmpty())
40 if (layout.isEmpty())
42 return;
41 return;
43
42
44 QStringList labelList = labels();
43 QStringList labelList = labels();
45
44
46 QList<QGraphicsItem *> lines = gridItems();
45 QList<QGraphicsItem *> lines = gridItems();
47 QList<QGraphicsItem *> labels = labelItems();
46 QList<QGraphicsItem *> labels = labelItems();
48 QList<QGraphicsItem *> shades = shadeItems();
47 QList<QGraphicsItem *> shades = shadeItems();
49 QList<QGraphicsItem *> arrow = arrowItems();
48 QList<QGraphicsItem *> arrow = arrowItems();
50 QGraphicsSimpleTextItem *title = titleItem();
49 QGraphicsSimpleTextItem *title = titleItem();
51
50
52 Q_ASSERT(labels.size() == labelList.size());
51 Q_ASSERT(labels.size() == labelList.size());
53 Q_ASSERT(layout.size() == labelList.size());
52 Q_ASSERT(layout.size() == labelList.size());
54
53
55 const QRectF &axisRect = axisGeometry();
54 const QRectF &axisRect = axisGeometry();
56 const QRectF &gridRect = gridGeometry();
55 const QRectF &gridRect = gridGeometry();
57
56
58 qreal height = axisRect.bottom();
57 qreal height = axisRect.bottom();
59
58
60
59
61 //arrow
60 //arrow
62 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem*>(arrow.at(0));
61 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem*>(arrow.at(0));
63
62
64 //arrow position
63 //arrow position
65 if (axis()->alignment() == Qt::AlignLeft)
64 if (axis()->alignment() == Qt::AlignLeft)
66 arrowItem->setLine(axisRect.right(), gridRect.top(), axisRect.right(), gridRect.bottom());
65 arrowItem->setLine(axisRect.right(), gridRect.top(), axisRect.right(), gridRect.bottom());
67 else if (axis()->alignment() == Qt::AlignRight)
66 else if (axis()->alignment() == Qt::AlignRight)
68 arrowItem->setLine(axisRect.left(), gridRect.top(), axisRect.left(), gridRect.bottom());
67 arrowItem->setLine(axisRect.left(), gridRect.top(), axisRect.left(), gridRect.bottom());
69
68
70 QFontMetrics fn(axis()->labelsFont());
71
72 //title
69 //title
73 int titlePad = 0;
70 int titlePad = 0;
74 QRectF titleBoundingRect;
71 QRectF titleBoundingRect;
75 QString titleText = axis()->titleText();
72 QString titleText = axis()->titleText();
76 if (!titleText.isEmpty() && titleItem()->isVisible()) {
73 if (!titleText.isEmpty() && titleItem()->isVisible()) {
77 int size(0);
74 title->setText(truncatedText(axis()->titleFont(), titleText, 0.0, gridRect.height(), Qt::Horizontal, QRectF()));
78 size = gridRect.height();
79
80 QGraphicsSimpleTextItem dummyTitle;
81 dummyTitle.setFont(axis()->titleFont());
82 dummyTitle.setText(axis()->titleText());
83 QRectF dummyRect = dummyTitle.boundingRect();
84
85 if (dummyRect.width() > size) {
86 QString string = titleText + "...";
87 while (dummyRect.width() > size && string.length() > 3) {
88 string.remove(string.length() - 4, 1);
89 dummyTitle.setText(string);
90 dummyRect = dummyTitle.boundingRect();
91 }
92 title->setText(string);
93 } else {
94 title->setText(titleText);
95 }
96
75
97 titlePad = titlePadding();
76 titlePad = titlePadding();
98 titleBoundingRect = title->boundingRect();
77 titleBoundingRect = title->boundingRect();
99
78
100 QPointF center = gridRect.center() - titleBoundingRect.center();
79 QPointF center = gridRect.center() - titleBoundingRect.center();
101 if (axis()->alignment() == Qt::AlignLeft) {
80 if (axis()->alignment() == Qt::AlignLeft) {
102 title->setPos(axisRect.left() - titleBoundingRect.width() / 2 + titleBoundingRect.height() / 2 + titlePad, center.y());
81 title->setPos(axisRect.left() - titleBoundingRect.width() / 2 + titleBoundingRect.height() / 2 + titlePad, center.y());
103 }
82 }
104 else if (axis()->alignment() == Qt::AlignRight) {
83 else if (axis()->alignment() == Qt::AlignRight) {
105 title->setPos(axisRect.right() - titleBoundingRect.width() / 2 - titleBoundingRect.height() / 2 - titlePad, center.y());
84 title->setPos(axisRect.right() - titleBoundingRect.width() / 2 - titleBoundingRect.height() / 2 - titlePad, center.y());
106 }
85 }
107 title->setTransformOriginPoint(titleBoundingRect.center());
86 title->setTransformOriginPoint(titleBoundingRect.center());
108 title->setRotation(270);
87 title->setRotation(270);
109 }
88 }
110
89
111 for (int i = 0; i < layout.size(); ++i) {
90 for (int i = 0; i < layout.size(); ++i) {
112 //items
91 //items
113 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem *>(lines.at(i));
92 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem *>(lines.at(i));
114 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrow.at(i + 1));
93 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrow.at(i + 1));
115 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labels.at(i));
94 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labels.at(i));
116
95
117 //grid line
96 //grid line
118 gridItem->setLine(gridRect.left(), layout[i], gridRect.right(), layout[i]);
97 gridItem->setLine(gridRect.left(), layout[i], gridRect.right(), layout[i]);
119
98
120 //label text wrapping
99 //label text wrapping
121 QString text = labelList.at(i);
100 QString text = labelList.at(i);
122 QRectF boundingRect = labelBoundingRect(fn, text);
101 QRectF boundingRect;
123
124 qreal size = axisRect.right() - axisRect.left() - labelPadding() - titleBoundingRect.height() - (titlePad * 2);
102 qreal size = axisRect.right() - axisRect.left() - labelPadding() - titleBoundingRect.height() - (titlePad * 2);
125 if (boundingRect.width() > size) {
103 labelItem->setText(truncatedText(axis()->labelsFont(), text, axis()->labelsAngle(),
126 QString label = text + "...";
104 size, Qt::Horizontal, boundingRect));
127 while (boundingRect.width() > size && label.length() > 3) {
128 label.remove(label.length() - 4, 1);
129 boundingRect = labelBoundingRect(fn, label);
130 }
131 labelItem->setText(label);
132 } else {
133 labelItem->setText(text);
134 }
135
105
136 //label transformation origin point
106 //label transformation origin point
137 const QRectF &rect = labelItem->boundingRect();
107 const QRectF &rect = labelItem->boundingRect();
138
139 QPointF center = rect.center();
108 QPointF center = rect.center();
140 labelItem->setTransformOriginPoint(center.x(), center.y());
109 labelItem->setTransformOriginPoint(center.x(), center.y());
141 int widthDiff = rect.width() - boundingRect.width();
110 int widthDiff = rect.width() - boundingRect.width();
142
111
143 //ticks and label position
112 //ticks and label position
144 if (axis()->alignment() == Qt::AlignLeft) {
113 if (axis()->alignment() == Qt::AlignLeft) {
145 labelItem->setPos(axisRect.right() - rect.width() + (widthDiff / 2) - labelPadding(), layout[i] - center.y());
114 labelItem->setPos(axisRect.right() - rect.width() + (widthDiff / 2) - labelPadding(), layout[i] - center.y());
146 tickItem->setLine(axisRect.right() - labelPadding(), layout[i], axisRect.right(), layout[i]);
115 tickItem->setLine(axisRect.right() - labelPadding(), layout[i], axisRect.right(), layout[i]);
147 } else if (axis()->alignment() == Qt::AlignRight) {
116 } else if (axis()->alignment() == Qt::AlignRight) {
148 labelItem->setPos(axisRect.left() + labelPadding() - (widthDiff / 2), layout[i] - center.y());
117 labelItem->setPos(axisRect.left() + labelPadding() - (widthDiff / 2), layout[i] - center.y());
149 tickItem->setLine(axisRect.left(), layout[i], axisRect.left() + labelPadding(), layout[i]);
118 tickItem->setLine(axisRect.left(), layout[i], axisRect.left() + labelPadding(), layout[i]);
150 }
119 }
151
120
152 //label in between
121 //label in between
153 bool forceHide = false;
122 bool forceHide = false;
154 if (intervalAxis() && (i + 1) != layout.size()) {
123 if (intervalAxis() && (i + 1) != layout.size()) {
155 qreal lowerBound = qMin(layout[i], gridRect.bottom());
124 qreal lowerBound = qMin(layout[i], gridRect.bottom());
156 qreal upperBound = qMax(layout[i + 1], gridRect.top());
125 qreal upperBound = qMax(layout[i + 1], gridRect.top());
157 const qreal delta = lowerBound - upperBound;
126 const qreal delta = lowerBound - upperBound;
158 // Hide label in case visible part of the category at the grid edge is too narrow
127 // Hide label in case visible part of the category at the grid edge is too narrow
159 if (delta < boundingRect.height()
128 if (delta < boundingRect.height()
160 && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())) {
129 && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())) {
161 forceHide = true;
130 forceHide = true;
162 } else {
131 } else {
163 labelItem->setPos(labelItem->pos().x() , lowerBound - (delta / 2.0) - center.y());
132 labelItem->setPos(labelItem->pos().x() , lowerBound - (delta / 2.0) - center.y());
164 }
133 }
165 }
134 }
166
135
167 //label overlap detection - compensate one pixel for rounding errors
136 //label overlap detection - compensate one pixel for rounding errors
168 if (labelItem->pos().y() + boundingRect.height() > height || forceHide ||
137 if (labelItem->pos().y() + boundingRect.height() > height || forceHide ||
169 (labelItem->pos().y() + (boundingRect.height() / 2.0) - 1.0) > axisRect.bottom() ||
138 (labelItem->pos().y() + (boundingRect.height() / 2.0) - 1.0) > axisRect.bottom() ||
170 labelItem->pos().y() + (boundingRect.height() / 2.0) < (axisRect.top() - 1.0)) {
139 labelItem->pos().y() + (boundingRect.height() / 2.0) < (axisRect.top() - 1.0)) {
171 labelItem->setVisible(false);
140 labelItem->setVisible(false);
172 }
141 }
173 else {
142 else {
174 labelItem->setVisible(true);
143 labelItem->setVisible(true);
175 height=labelItem->pos().y();
144 height=labelItem->pos().y();
176 }
145 }
177
146
178 //shades
147 //shades
179 if ((i + 1) % 2 && i > 1) {
148 if ((i + 1) % 2 && i > 1) {
180 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem *>(shades.at(i / 2 - 1));
149 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem *>(shades.at(i / 2 - 1));
181 qreal lowerBound = qMin(layout[i - 1], gridRect.bottom());
150 qreal lowerBound = qMin(layout[i - 1], gridRect.bottom());
182 qreal upperBound = qMax(layout[i], gridRect.top());
151 qreal upperBound = qMax(layout[i], gridRect.top());
183 rectItem->setRect(gridRect.left(), upperBound, gridRect.width(), lowerBound - upperBound);
152 rectItem->setRect(gridRect.left(), upperBound, gridRect.width(), lowerBound - upperBound);
184 if (rectItem->rect().height() <= 0.0)
153 if (rectItem->rect().height() <= 0.0)
185 rectItem->setVisible(false);
154 rectItem->setVisible(false);
186 else
155 else
187 rectItem->setVisible(true);
156 rectItem->setVisible(true);
188 }
157 }
189
158
190 // check if the grid line and the axis tick should be shown
159 // check if the grid line and the axis tick should be shown
191 qreal y = gridItem->line().p1().y();
160 qreal y = gridItem->line().p1().y();
192 if ((y < gridRect.top() || y > gridRect.bottom()))
161 if ((y < gridRect.top() || y > gridRect.bottom()))
193 {
162 {
194 gridItem->setVisible(false);
163 gridItem->setVisible(false);
195 tickItem->setVisible(false);
164 tickItem->setVisible(false);
196 }else{
165 }else{
197 gridItem->setVisible(true);
166 gridItem->setVisible(true);
198 tickItem->setVisible(true);
167 tickItem->setVisible(true);
199 }
168 }
200
169
201 }
170 }
202 //begin/end grid line in case labels between
171 //begin/end grid line in case labels between
203 if (intervalAxis()) {
172 if (intervalAxis()) {
204 QGraphicsLineItem *gridLine;
173 QGraphicsLineItem *gridLine;
205 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
174 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
206 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.right(), gridRect.top());
175 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.right(), gridRect.top());
207 gridLine->setVisible(true);
176 gridLine->setVisible(true);
208 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size() + 1));
177 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size() + 1));
209 gridLine->setLine(gridRect.left(), gridRect.bottom(), gridRect.right(), gridRect.bottom());
178 gridLine->setLine(gridRect.left(), gridRect.bottom(), gridRect.right(), gridRect.bottom());
210 gridLine->setVisible(true);
179 gridLine->setVisible(true);
211 }
180 }
212 }
181 }
213
182
214 QSizeF VerticalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
183 QSizeF VerticalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
215 {
184 {
216 Q_UNUSED(constraint);
185 Q_UNUSED(constraint);
217 QSizeF sh(0, 0);
186 QSizeF sh(0, 0);
218
187
219 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
188 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
220 return sh;
189 return sh;
221
190
222 switch (which) {
191 switch (which) {
223 case Qt::MinimumSize: {
192 case Qt::MinimumSize: {
224 QFontMetrics fn(axis()->titleFont());
193 QRectF titleRect = textBoundingRect(axis()->titleFont(), "...");
225 sh = QSizeF(fn.height() + (titlePadding() * 2), fn.boundingRect("...").width());
194 sh = QSizeF(titleRect.height() + (titlePadding() * 2), titleRect.width());
226 break;
195 break;
227 }
196 }
228 case Qt::MaximumSize:
197 case Qt::MaximumSize:
229 case Qt::PreferredSize: {
198 case Qt::PreferredSize: {
230 QGraphicsSimpleTextItem dummyTitle;
199 QRectF titleRect = textBoundingRect(axis()->titleFont(), axis()->titleText());
231 dummyTitle.setFont(axis()->titleFont());
232 dummyTitle.setText(axis()->titleText());
233 QRectF titleRect = dummyTitle.boundingRect();
234 sh = QSizeF(titleRect.height() + (titlePadding() * 2), titleRect.width());
200 sh = QSizeF(titleRect.height() + (titlePadding() * 2), titleRect.width());
235 break;
201 break;
236 }
202 }
237 default:
203 default:
238 break;
204 break;
239 }
205 }
240
206
241 return sh;
207 return sh;
242 }
208 }
243
209
244 QTCOMMERCIALCHART_END_NAMESPACE
210 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,86 +1,82
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "polarchartlayout_p.h"
21 #include "polarchartlayout_p.h"
22 #include "chartpresenter_p.h"
22 #include "chartpresenter_p.h"
23 #include "polarchartaxis_p.h"
23 #include "polarchartaxis_p.h"
24 #include <QDebug>
24 #include <QDebug>
25 #include <QFontMetrics>
26
25
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28
27
29 static const qreal golden_ratio = 0.4;
28 static const qreal golden_ratio = 0.4;
30
29
31 PolarChartLayout::PolarChartLayout(ChartPresenter *presenter)
30 PolarChartLayout::PolarChartLayout(ChartPresenter *presenter)
32 : AbstractChartLayout(presenter)
31 : AbstractChartLayout(presenter)
33 {
32 {
34 }
33 }
35
34
36 PolarChartLayout::~PolarChartLayout()
35 PolarChartLayout::~PolarChartLayout()
37 {
36 {
38 }
37 }
39
38
40 QRectF PolarChartLayout::calculateAxisGeometry(const QRectF &geometry, const QList<ChartAxisElement *> &axes) const
39 QRectF PolarChartLayout::calculateAxisGeometry(const QRectF &geometry, const QList<ChartAxisElement *> &axes) const
41 {
40 {
42 // How to handle multiple angular/radial axes?
41 // How to handle multiple angular/radial axes?
43 qreal axisRadius = geometry.height() / 2.0;
42 qreal axisRadius = geometry.height() / 2.0;
44 if (geometry.width() < geometry.height())
43 if (geometry.width() < geometry.height())
45 axisRadius = geometry.width() / 2.0;
44 axisRadius = geometry.width() / 2.0;
46
45
47 int titleHeight = 0;
46 int titleHeight = 0;
48 foreach (ChartAxisElement *chartAxis, axes) {
47 foreach (ChartAxisElement *chartAxis, axes) {
49 if (!chartAxis->isVisible())
48 if (!chartAxis->isVisible())
50 continue;
49 continue;
51
50
52 PolarChartAxis *polarChartAxis = static_cast<PolarChartAxis *>(chartAxis);
51 PolarChartAxis *polarChartAxis = static_cast<PolarChartAxis *>(chartAxis);
53 qreal radius = polarChartAxis->preferredAxisRadius(geometry.size());
52 qreal radius = polarChartAxis->preferredAxisRadius(geometry.size());
54 if (radius < axisRadius)
53 if (radius < axisRadius)
55 axisRadius = radius;
54 axisRadius = radius;
56
55
57 if (chartAxis->axis()->orientation() == Qt::Horizontal
56 if (chartAxis->axis()->orientation() == Qt::Horizontal
58 && chartAxis->axis()->isTitleVisible()
57 && chartAxis->axis()->isTitleVisible()
59 && !chartAxis->axis()->titleText().isEmpty()) {
58 && !chartAxis->axis()->titleText().isEmpty()) {
60 // If axis has angular title, adjust geometry down by the space title takes
59 // If axis has angular title, adjust geometry down by the space title takes
61 QGraphicsSimpleTextItem dummyTitle;
60 QRectF dummyRect = chartAxis->textBoundingRect(chartAxis->axis()->titleFont(), chartAxis->axis()->titleText());
62 dummyTitle.setFont(chartAxis->axis()->titleFont());
63 dummyTitle.setText(chartAxis->axis()->titleText());
64 QRectF dummyRect = dummyTitle.boundingRect();
65 titleHeight = (dummyRect.height() / 2.0) + chartAxis->titlePadding();
61 titleHeight = (dummyRect.height() / 2.0) + chartAxis->titlePadding();
66 }
62 }
67 }
63 }
68
64
69 QRectF axisRect;
65 QRectF axisRect;
70 axisRect.setSize(QSizeF(axisRadius * 2.0, axisRadius * 2.0));
66 axisRect.setSize(QSizeF(axisRadius * 2.0, axisRadius * 2.0));
71 axisRect.moveCenter(geometry.center());
67 axisRect.moveCenter(geometry.center());
72 axisRect.adjust(0, titleHeight, 0, titleHeight);
68 axisRect.adjust(0, titleHeight, 0, titleHeight);
73
69
74 foreach (ChartAxisElement *chartAxis, axes)
70 foreach (ChartAxisElement *chartAxis, axes)
75 chartAxis->setGeometry(axisRect, QRectF());
71 chartAxis->setGeometry(axisRect, QRectF());
76
72
77 return axisRect;
73 return axisRect;
78 }
74 }
79
75
80 QRectF PolarChartLayout::calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxisElement *> &axes) const
76 QRectF PolarChartLayout::calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxisElement *> &axes) const
81 {
77 {
82 Q_UNUSED(axes);
78 Q_UNUSED(axes);
83 return minimum;
79 return minimum;
84 }
80 }
85
81
86 QTCOMMERCIALCHART_END_NAMESPACE
82 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now