##// END OF EJS Templates
Fix multiline alignment...
Titta Heikkala -
r2607:dfd05e587e31
parent child
Show More
@@ -1,219 +1,224
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Enterprise Charts Add-on.
7 ** This file is part of the Qt Enterprise Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
11 ** accordance with the Qt Enterprise License Agreement provided with the
11 ** accordance with the Qt Enterprise License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "horizontalaxis_p.h"
21 #include "horizontalaxis_p.h"
22 #include "qabstractaxis_p.h"
22 #include "qabstractaxis_p.h"
23 #include "chartpresenter_p.h"
23 #include "chartpresenter_p.h"
24 #include <qmath.h>
24 #include <qmath.h>
25 #include <QDebug>
25 #include <QDebug>
26
26
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28
28
29 HorizontalAxis::HorizontalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
29 HorizontalAxis::HorizontalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
30 : CartesianChartAxis(axis, item, intervalAxis)
30 : CartesianChartAxis(axis, item, intervalAxis)
31 {
31 {
32 }
32 }
33
33
34 HorizontalAxis::~HorizontalAxis()
34 HorizontalAxis::~HorizontalAxis()
35 {
35 {
36 }
36 }
37
37
38 void HorizontalAxis::updateGeometry()
38 void HorizontalAxis::updateGeometry()
39 {
39 {
40 const QVector<qreal> &layout = ChartAxisElement::layout();
40 const QVector<qreal> &layout = ChartAxisElement::layout();
41
41
42 if (layout.isEmpty())
42 if (layout.isEmpty())
43 return;
43 return;
44
44
45 QStringList labelList = labels();
45 QStringList labelList = labels();
46
46
47 QList<QGraphicsItem *> lines = gridItems();
47 QList<QGraphicsItem *> lines = gridItems();
48 QList<QGraphicsItem *> labels = labelItems();
48 QList<QGraphicsItem *> labels = labelItems();
49 QList<QGraphicsItem *> shades = shadeItems();
49 QList<QGraphicsItem *> shades = shadeItems();
50 QList<QGraphicsItem *> arrow = arrowItems();
50 QList<QGraphicsItem *> arrow = arrowItems();
51 QGraphicsTextItem *title = titleItem();
51 QGraphicsTextItem *title = titleItem();
52
52
53 Q_ASSERT(labels.size() == labelList.size());
53 Q_ASSERT(labels.size() == labelList.size());
54 Q_ASSERT(layout.size() == labelList.size());
54 Q_ASSERT(layout.size() == labelList.size());
55
55
56 const QRectF &axisRect = axisGeometry();
56 const QRectF &axisRect = axisGeometry();
57 const QRectF &gridRect = gridGeometry();
57 const QRectF &gridRect = gridGeometry();
58
58
59 //arrow
59 //arrow
60 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem *>(arrow.at(0));
60 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem *>(arrow.at(0));
61
61
62 if (axis()->alignment() == Qt::AlignTop)
62 if (axis()->alignment() == Qt::AlignTop)
63 arrowItem->setLine(gridRect.left(), axisRect.bottom(), gridRect.right(), axisRect.bottom());
63 arrowItem->setLine(gridRect.left(), axisRect.bottom(), gridRect.right(), axisRect.bottom());
64 else if (axis()->alignment() == Qt::AlignBottom)
64 else if (axis()->alignment() == Qt::AlignBottom)
65 arrowItem->setLine(gridRect.left(), axisRect.top(), gridRect.right(), axisRect.top());
65 arrowItem->setLine(gridRect.left(), axisRect.top(), gridRect.right(), axisRect.top());
66
66
67 qreal width = 0;
67 qreal width = 0;
68
68
69 //title
69 //title
70 QRectF titleBoundingRect;
70 QRectF titleBoundingRect;
71 QString titleText = axis()->titleText();
71 QString titleText = axis()->titleText();
72 qreal availableSpace = axisRect.height() - labelPadding();
72 qreal availableSpace = axisRect.height() - labelPadding();
73 if (!titleText.isEmpty() && titleItem()->isVisible()) {
73 if (!titleText.isEmpty() && titleItem()->isVisible()) {
74 availableSpace -= titlePadding() * 2.0;
74 availableSpace -= titlePadding() * 2.0;
75 qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").height();
75 qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").height();
76 qreal titleSpace = availableSpace - minimumLabelHeight;
76 qreal titleSpace = availableSpace - minimumLabelHeight;
77 title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0),
77 title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0),
78 gridRect.width(), titleSpace,
78 gridRect.width(), titleSpace,
79 titleBoundingRect));
79 titleBoundingRect));
80 title->setTextWidth(titleBoundingRect.width());
80
81
81 titleBoundingRect = title->boundingRect();
82 titleBoundingRect = title->boundingRect();
82
83
83 QPointF center = gridRect.center() - titleBoundingRect.center();
84 QPointF center = gridRect.center() - titleBoundingRect.center();
84 if (axis()->alignment() == Qt::AlignTop)
85 if (axis()->alignment() == Qt::AlignTop)
85 title->setPos(center.x(), axisRect.top() + titlePadding());
86 title->setPos(center.x(), axisRect.top() + titlePadding());
86 else if (axis()->alignment() == Qt::AlignBottom)
87 else if (axis()->alignment() == Qt::AlignBottom)
87 title->setPos(center.x(), axisRect.bottom() - titleBoundingRect.height() - titlePadding());
88 title->setPos(center.x(), axisRect.bottom() - titleBoundingRect.height() - titlePadding());
88
89
89 availableSpace -= titleBoundingRect.height();
90 availableSpace -= titleBoundingRect.height();
90 }
91 }
91
92
92 for (int i = 0; i < layout.size(); ++i) {
93 for (int i = 0; i < layout.size(); ++i) {
93 //items
94 //items
94 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem*>(lines.at(i));
95 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem*>(lines.at(i));
95 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem*>(arrow.at(i + 1));
96 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem*>(arrow.at(i + 1));
96 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labels.at(i));
97 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labels.at(i));
97
98
98 //grid line
99 //grid line
99 gridItem->setLine(layout[i], gridRect.top(), layout[i], gridRect.bottom());
100 gridItem->setLine(layout[i], gridRect.top(), layout[i], gridRect.bottom());
100
101
101 //label text wrapping
102 //label text wrapping
102 QString text = labelList.at(i);
103 QString text = labelList.at(i);
103 QRectF boundingRect;
104 QRectF boundingRect;
104 // don't truncate empty labels
105 // don't truncate empty labels
105 if (text.isEmpty()) {
106 if (text.isEmpty()) {
106 labelItem->setHtml(text);
107 labelItem->setHtml(text);
107 } else {
108 } else {
108 qreal labelWidth = axisRect.width() / layout.count() - (2 * labelPadding());
109 qreal labelWidth = axisRect.width() / layout.count() - (2 * labelPadding());
109 labelItem->setHtml(ChartPresenter::truncatedText(axis()->labelsFont(), text,
110 QString truncatedText = ChartPresenter::truncatedText(axis()->labelsFont(), text,
110 axis()->labelsAngle(), labelWidth,
111 axis()->labelsAngle(),
111 availableSpace, boundingRect));
112 labelWidth,
113 availableSpace, boundingRect);
114 labelItem->setTextWidth(ChartPresenter::textBoundingRect(axis()->labelsFont(),
115 truncatedText).width());
116 labelItem->setHtml(truncatedText);
112 }
117 }
113
118
114 //label transformation origin point
119 //label transformation origin point
115 const QRectF& rect = labelItem->boundingRect();
120 const QRectF& rect = labelItem->boundingRect();
116 QPointF center = rect.center();
121 QPointF center = rect.center();
117 labelItem->setTransformOriginPoint(center.x(), center.y());
122 labelItem->setTransformOriginPoint(center.x(), center.y());
118 qreal heightDiff = rect.height() - boundingRect.height();
123 qreal heightDiff = rect.height() - boundingRect.height();
119 qreal widthDiff = rect.width() - boundingRect.width();
124 qreal widthDiff = rect.width() - boundingRect.width();
120
125
121 //ticks and label position
126 //ticks and label position
122 if (axis()->alignment() == Qt::AlignTop) {
127 if (axis()->alignment() == Qt::AlignTop) {
123 labelItem->setPos(layout[i] - center.x(), axisRect.bottom() - rect.height() + (heightDiff / 2.0) - labelPadding());
128 labelItem->setPos(layout[i] - center.x(), axisRect.bottom() - rect.height() + (heightDiff / 2.0) - labelPadding());
124 tickItem->setLine(layout[i], axisRect.bottom(), layout[i], axisRect.bottom() - labelPadding());
129 tickItem->setLine(layout[i], axisRect.bottom(), layout[i], axisRect.bottom() - labelPadding());
125 } else if (axis()->alignment() == Qt::AlignBottom) {
130 } else if (axis()->alignment() == Qt::AlignBottom) {
126 labelItem->setPos(layout[i] - center.x(), axisRect.top() - (heightDiff / 2.0) + labelPadding());
131 labelItem->setPos(layout[i] - center.x(), axisRect.top() - (heightDiff / 2.0) + labelPadding());
127 tickItem->setLine(layout[i], axisRect.top(), layout[i], axisRect.top() + labelPadding());
132 tickItem->setLine(layout[i], axisRect.top(), layout[i], axisRect.top() + labelPadding());
128 }
133 }
129
134
130 //label in between
135 //label in between
131 bool forceHide = false;
136 bool forceHide = false;
132 if (intervalAxis() && (i + 1) != layout.size()) {
137 if (intervalAxis() && (i + 1) != layout.size()) {
133 qreal leftBound = qMax(layout[i], gridRect.left());
138 qreal leftBound = qMax(layout[i], gridRect.left());
134 qreal rightBound = qMin(layout[i + 1], gridRect.right());
139 qreal rightBound = qMin(layout[i + 1], gridRect.right());
135 const qreal delta = rightBound - leftBound;
140 const qreal delta = rightBound - leftBound;
136 // Hide label in case visible part of the category at the grid edge is too narrow
141 // Hide label in case visible part of the category at the grid edge is too narrow
137 if (delta < boundingRect.width()
142 if (delta < boundingRect.width()
138 && (leftBound == gridRect.left() || rightBound == gridRect.right())
143 && (leftBound == gridRect.left() || rightBound == gridRect.right())
139 && !intervalAxis()) {
144 && !intervalAxis()) {
140 forceHide = true;
145 forceHide = true;
141 } else {
146 } else {
142 labelItem->setPos(leftBound + (delta / 2.0) - center.x(), labelItem->pos().y());
147 labelItem->setPos(leftBound + (delta / 2.0) - center.x(), labelItem->pos().y());
143 }
148 }
144 }
149 }
145 //label overlap detection - compensate one pixel for rounding errors
150 //label overlap detection - compensate one pixel for rounding errors
146 if ((labelItem->pos().x() < width || forceHide ||
151 if ((labelItem->pos().x() < width || forceHide ||
147 (labelItem->pos().x() + (widthDiff / 2.0)) < (axisRect.left() - 1.0) ||
152 (labelItem->pos().x() + (widthDiff / 2.0)) < (axisRect.left() - 1.0) ||
148 (labelItem->pos().x() + (widthDiff / 2.0) - 1.0) > axisRect.right())
153 (labelItem->pos().x() + (widthDiff / 2.0) - 1.0) > axisRect.right())
149 && !intervalAxis()) {
154 && !intervalAxis()) {
150 labelItem->setVisible(false);
155 labelItem->setVisible(false);
151 } else {
156 } else {
152 labelItem->setVisible(true);
157 labelItem->setVisible(true);
153 width = boundingRect.width() + labelItem->pos().x();
158 width = boundingRect.width() + labelItem->pos().x();
154 }
159 }
155
160
156 //shades
161 //shades
157 if ((i + 1) % 2 && i > 1) {
162 if ((i + 1) % 2 && i > 1) {
158 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem *>(shades.at(i / 2 - 1));
163 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem *>(shades.at(i / 2 - 1));
159 qreal leftBound = qMax(layout[i - 1], gridRect.left());
164 qreal leftBound = qMax(layout[i - 1], gridRect.left());
160 qreal rightBound = qMin(layout[i], gridRect.right());
165 qreal rightBound = qMin(layout[i], gridRect.right());
161 rectItem->setRect(leftBound, gridRect.top(), rightBound - leftBound, gridRect.height());
166 rectItem->setRect(leftBound, gridRect.top(), rightBound - leftBound, gridRect.height());
162 if (rectItem->rect().width() <= 0.0)
167 if (rectItem->rect().width() <= 0.0)
163 rectItem->setVisible(false);
168 rectItem->setVisible(false);
164 else
169 else
165 rectItem->setVisible(true);
170 rectItem->setVisible(true);
166 }
171 }
167
172
168 // check if the grid line and the axis tick should be shown
173 // check if the grid line and the axis tick should be shown
169 qreal x = gridItem->line().p1().x();
174 qreal x = gridItem->line().p1().x();
170 if (x < gridRect.left() || x > gridRect.right()) {
175 if (x < gridRect.left() || x > gridRect.right()) {
171 gridItem->setVisible(false);
176 gridItem->setVisible(false);
172 tickItem->setVisible(false);
177 tickItem->setVisible(false);
173 } else {
178 } else {
174 gridItem->setVisible(true);
179 gridItem->setVisible(true);
175 tickItem->setVisible(true);
180 tickItem->setVisible(true);
176 }
181 }
177
182
178 }
183 }
179
184
180 //begin/end grid line in case labels between
185 //begin/end grid line in case labels between
181 if (intervalAxis()) {
186 if (intervalAxis()) {
182 QGraphicsLineItem *gridLine;
187 QGraphicsLineItem *gridLine;
183 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
188 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
184 gridLine->setLine(gridRect.right(), gridRect.top(), gridRect.right(), gridRect.bottom());
189 gridLine->setLine(gridRect.right(), gridRect.top(), gridRect.right(), gridRect.bottom());
185 gridLine->setVisible(true);
190 gridLine->setVisible(true);
186 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size()+1));
191 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size()+1));
187 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.left(), gridRect.bottom());
192 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.left(), gridRect.bottom());
188 gridLine->setVisible(true);
193 gridLine->setVisible(true);
189 }
194 }
190 }
195 }
191
196
192 QSizeF HorizontalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
197 QSizeF HorizontalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
193 {
198 {
194 Q_UNUSED(constraint);
199 Q_UNUSED(constraint);
195 QSizeF sh(0,0);
200 QSizeF sh(0,0);
196
201
197 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
202 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
198 return sh;
203 return sh;
199
204
200 switch (which) {
205 switch (which) {
201 case Qt::MinimumSize: {
206 case Qt::MinimumSize: {
202 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), "...");
207 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), "...");
203 sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2.0));
208 sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2.0));
204 break;
209 break;
205 }
210 }
206 case Qt::MaximumSize:
211 case Qt::MaximumSize:
207 case Qt::PreferredSize: {
212 case Qt::PreferredSize: {
208 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
213 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
209 sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2.0));
214 sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2.0));
210 break;
215 break;
211 }
216 }
212 default:
217 default:
213 break;
218 break;
214 }
219 }
215
220
216 return sh;
221 return sh;
217 }
222 }
218
223
219 QTCOMMERCIALCHART_END_NAMESPACE
224 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,427 +1,431
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Enterprise Charts Add-on.
7 ** This file is part of the Qt Enterprise Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
11 ** accordance with the Qt Enterprise License Agreement provided with the
11 ** accordance with the Qt Enterprise License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "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 <QDebug>
26 #include <QDebug>
27 #include <qmath.h>
27 #include <qmath.h>
28 #include <QTextDocument>
28 #include <QTextDocument>
29
29
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
31
32 PolarChartAxisAngular::PolarChartAxisAngular(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
32 PolarChartAxisAngular::PolarChartAxisAngular(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
33 : PolarChartAxis(axis, item, intervalAxis)
33 : PolarChartAxis(axis, item, intervalAxis)
34 {
34 {
35 }
35 }
36
36
37 PolarChartAxisAngular::~PolarChartAxisAngular()
37 PolarChartAxisAngular::~PolarChartAxisAngular()
38 {
38 {
39 }
39 }
40
40
41 void PolarChartAxisAngular::updateGeometry()
41 void PolarChartAxisAngular::updateGeometry()
42 {
42 {
43 QGraphicsLayoutItem::updateGeometry();
43 QGraphicsLayoutItem::updateGeometry();
44
44
45 const QVector<qreal> &layout = this->layout();
45 const QVector<qreal> &layout = this->layout();
46 if (layout.isEmpty())
46 if (layout.isEmpty())
47 return;
47 return;
48
48
49 createAxisLabels(layout);
49 createAxisLabels(layout);
50 QStringList labelList = labels();
50 QStringList labelList = labels();
51 QPointF center = axisGeometry().center();
51 QPointF center = axisGeometry().center();
52 QList<QGraphicsItem *> arrowItemList = arrowItems();
52 QList<QGraphicsItem *> arrowItemList = arrowItems();
53 QList<QGraphicsItem *> gridItemList = gridItems();
53 QList<QGraphicsItem *> gridItemList = gridItems();
54 QList<QGraphicsItem *> labelItemList = labelItems();
54 QList<QGraphicsItem *> labelItemList = labelItems();
55 QList<QGraphicsItem *> shadeItemList = shadeItems();
55 QList<QGraphicsItem *> shadeItemList = shadeItems();
56 QGraphicsTextItem *title = titleItem();
56 QGraphicsTextItem *title = titleItem();
57
57
58 QGraphicsEllipseItem *axisLine = static_cast<QGraphicsEllipseItem *>(arrowItemList.at(0));
58 QGraphicsEllipseItem *axisLine = static_cast<QGraphicsEllipseItem *>(arrowItemList.at(0));
59 axisLine->setRect(axisGeometry());
59 axisLine->setRect(axisGeometry());
60
60
61 qreal radius = axisGeometry().height() / 2.0;
61 qreal radius = axisGeometry().height() / 2.0;
62
62
63 QRectF previousLabelRect;
63 QRectF previousLabelRect;
64 QRectF firstLabelRect;
64 QRectF firstLabelRect;
65
65
66 qreal labelHeight = 0;
66 qreal labelHeight = 0;
67
67
68 bool firstShade = true;
68 bool firstShade = true;
69 bool nextTickVisible = false;
69 bool nextTickVisible = false;
70 if (layout.size())
70 if (layout.size())
71 nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > 360.0);
71 nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > 360.0);
72
72
73 for (int i = 0; i < layout.size(); ++i) {
73 for (int i = 0; i < layout.size(); ++i) {
74 qreal angularCoordinate = layout.at(i);
74 qreal angularCoordinate = layout.at(i);
75
75
76 QGraphicsLineItem *gridLineItem = static_cast<QGraphicsLineItem *>(gridItemList.at(i));
76 QGraphicsLineItem *gridLineItem = static_cast<QGraphicsLineItem *>(gridItemList.at(i));
77 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1));
77 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1));
78 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labelItemList.at(i));
78 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labelItemList.at(i));
79 QGraphicsPathItem *shadeItem = 0;
79 QGraphicsPathItem *shadeItem = 0;
80 if (i == 0)
80 if (i == 0)
81 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
81 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
82 else if (i % 2)
82 else if (i % 2)
83 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1));
83 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1));
84
84
85 // Ignore ticks outside valid range
85 // Ignore ticks outside valid range
86 bool currentTickVisible = nextTickVisible;
86 bool currentTickVisible = nextTickVisible;
87 if ((i == layout.size() - 1)
87 if ((i == layout.size() - 1)
88 || layout.at(i + 1) < 0.0
88 || layout.at(i + 1) < 0.0
89 || layout.at(i + 1) > 360.0) {
89 || layout.at(i + 1) > 360.0) {
90 nextTickVisible = false;
90 nextTickVisible = false;
91 } else {
91 } else {
92 nextTickVisible = true;
92 nextTickVisible = true;
93 }
93 }
94
94
95 qreal labelCoordinate = angularCoordinate;
95 qreal labelCoordinate = angularCoordinate;
96 qreal labelVisible = currentTickVisible;
96 qreal labelVisible = currentTickVisible;
97 if (intervalAxis()) {
97 if (intervalAxis()) {
98 qreal farEdge;
98 qreal farEdge;
99 if (i == (layout.size() - 1))
99 if (i == (layout.size() - 1))
100 farEdge = 360.0;
100 farEdge = 360.0;
101 else
101 else
102 farEdge = qMin(qreal(360.0), layout.at(i + 1));
102 farEdge = qMin(qreal(360.0), layout.at(i + 1));
103
103
104 // Adjust the labelCoordinate to show it if next tick is visible
104 // Adjust the labelCoordinate to show it if next tick is visible
105 if (nextTickVisible)
105 if (nextTickVisible)
106 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
106 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
107
107
108 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
108 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
109 // Don't display label once the category gets too small near the axis
109 // Don't display label once the category gets too small near the axis
110 if (labelCoordinate < 5.0 || labelCoordinate > 355.0)
110 if (labelCoordinate < 5.0 || labelCoordinate > 355.0)
111 labelVisible = false;
111 labelVisible = false;
112 else
112 else
113 labelVisible = true;
113 labelVisible = true;
114 }
114 }
115
115
116 // Need this also in label calculations, so determine it first
116 // Need this also in label calculations, so determine it first
117 QLineF tickLine(QLineF::fromPolar(radius - tickWidth(), 90.0 - angularCoordinate).p2(),
117 QLineF tickLine(QLineF::fromPolar(radius - tickWidth(), 90.0 - angularCoordinate).p2(),
118 QLineF::fromPolar(radius + tickWidth(), 90.0 - angularCoordinate).p2());
118 QLineF::fromPolar(radius + tickWidth(), 90.0 - angularCoordinate).p2());
119 tickLine.translate(center);
119 tickLine.translate(center);
120
120
121 // Angular axis label
121 // Angular axis label
122 if (axis()->labelsVisible() && labelVisible) {
122 if (axis()->labelsVisible() && labelVisible) {
123 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
124 labelList.at(i),
125 axis()->labelsAngle());
126 labelItem->setTextWidth(boundingRect.width());
123 labelItem->setHtml(labelList.at(i));
127 labelItem->setHtml(labelList.at(i));
124 const QRectF &rect = labelItem->boundingRect();
128 const QRectF &rect = labelItem->boundingRect();
125 QPointF labelCenter = rect.center();
129 QPointF labelCenter = rect.center();
126 labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
130 labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
127 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(), labelList.at(i), axis()->labelsAngle());
128 boundingRect.moveCenter(labelCenter);
131 boundingRect.moveCenter(labelCenter);
129 QPointF positionDiff(rect.topLeft() - boundingRect.topLeft());
132 QPointF positionDiff(rect.topLeft() - boundingRect.topLeft());
130
133
131 QPointF labelPoint;
134 QPointF labelPoint;
132 if (intervalAxis()) {
135 if (intervalAxis()) {
133 QLineF labelLine = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate);
136 QLineF labelLine = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate);
134 labelLine.translate(center);
137 labelLine.translate(center);
135 labelPoint = labelLine.p2();
138 labelPoint = labelLine.p2();
136 } else {
139 } else {
137 labelPoint = tickLine.p2();
140 labelPoint = tickLine.p2();
138 }
141 }
139
142
140 QRectF labelRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
143 QRectF labelRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
141 labelItem->setPos(labelRect.topLeft() + positionDiff);
144 labelItem->setPos(labelRect.topLeft() + positionDiff);
142
145
143 // Store height for title calculations
146 // Store height for title calculations
144 qreal labelClearance = axisGeometry().top() - labelRect.top();
147 qreal labelClearance = axisGeometry().top() - labelRect.top();
145 labelHeight = qMax(labelHeight, labelClearance);
148 labelHeight = qMax(labelHeight, labelClearance);
146
149
147 // Label overlap detection
150 // Label overlap detection
148 if (i && (previousLabelRect.intersects(labelRect) || firstLabelRect.intersects(labelRect))) {
151 if (i && (previousLabelRect.intersects(labelRect) || firstLabelRect.intersects(labelRect))) {
149 labelVisible = false;
152 labelVisible = false;
150 } else {
153 } else {
151 // Store labelRect for future comparison. Some area is deducted to make things look
154 // 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.
155 // little nicer, as usually intersection happens at label corner with angular labels.
153 labelRect.adjust(-2.0, -4.0, -2.0, -4.0);
156 labelRect.adjust(-2.0, -4.0, -2.0, -4.0);
154 if (firstLabelRect.isEmpty())
157 if (firstLabelRect.isEmpty())
155 firstLabelRect = labelRect;
158 firstLabelRect = labelRect;
156
159
157 previousLabelRect = labelRect;
160 previousLabelRect = labelRect;
158 labelVisible = true;
161 labelVisible = true;
159 }
162 }
160 }
163 }
161
164
162 labelItem->setVisible(labelVisible);
165 labelItem->setVisible(labelVisible);
163 if (!currentTickVisible) {
166 if (!currentTickVisible) {
164 gridLineItem->setVisible(false);
167 gridLineItem->setVisible(false);
165 tickItem->setVisible(false);
168 tickItem->setVisible(false);
166 if (shadeItem)
169 if (shadeItem)
167 shadeItem->setVisible(false);
170 shadeItem->setVisible(false);
168 continue;
171 continue;
169 }
172 }
170
173
171 // Angular grid line
174 // Angular grid line
172 QLineF gridLine = QLineF::fromPolar(radius, 90.0 - angularCoordinate);
175 QLineF gridLine = QLineF::fromPolar(radius, 90.0 - angularCoordinate);
173 gridLine.translate(center);
176 gridLine.translate(center);
174 gridLineItem->setLine(gridLine);
177 gridLineItem->setLine(gridLine);
175 gridLineItem->setVisible(true);
178 gridLineItem->setVisible(true);
176
179
177 // Tick
180 // Tick
178 tickItem->setLine(tickLine);
181 tickItem->setLine(tickLine);
179 tickItem->setVisible(true);
182 tickItem->setVisible(true);
180
183
181 // Shades
184 // Shades
182 if (i % 2 || (i == 0 && !nextTickVisible)) {
185 if (i % 2 || (i == 0 && !nextTickVisible)) {
183 QPainterPath path;
186 QPainterPath path;
184 path.moveTo(center);
187 path.moveTo(center);
185 if (i == 0) {
188 if (i == 0) {
186 // If first tick is also the last, we need to custom fill the first partial arc
189 // If first tick is also the last, we need to custom fill the first partial arc
187 // or it won't get filled.
190 // or it won't get filled.
188 path.arcTo(axisGeometry(), 90.0 - layout.at(0), layout.at(0));
191 path.arcTo(axisGeometry(), 90.0 - layout.at(0), layout.at(0));
189 path.closeSubpath();
192 path.closeSubpath();
190 } else {
193 } else {
191 qreal nextCoordinate;
194 qreal nextCoordinate;
192 if (!nextTickVisible) // Last visible tick
195 if (!nextTickVisible) // Last visible tick
193 nextCoordinate = 360.0;
196 nextCoordinate = 360.0;
194 else
197 else
195 nextCoordinate = layout.at(i + 1);
198 nextCoordinate = layout.at(i + 1);
196 qreal arcSpan = angularCoordinate - nextCoordinate;
199 qreal arcSpan = angularCoordinate - nextCoordinate;
197 path.arcTo(axisGeometry(), 90.0 - angularCoordinate, arcSpan);
200 path.arcTo(axisGeometry(), 90.0 - angularCoordinate, arcSpan);
198 path.closeSubpath();
201 path.closeSubpath();
199
202
200 // Add additional arc for first shade item if there is a partial arc to be filled
203 // Add additional arc for first shade item if there is a partial arc to be filled
201 if (firstShade) {
204 if (firstShade) {
202 QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
205 QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
203 if (layout.at(i - 1) > 0.0) {
206 if (layout.at(i - 1) > 0.0) {
204 QPainterPath specialPath;
207 QPainterPath specialPath;
205 specialPath.moveTo(center);
208 specialPath.moveTo(center);
206 specialPath.arcTo(axisGeometry(), 90.0 - layout.at(i - 1), layout.at(i - 1));
209 specialPath.arcTo(axisGeometry(), 90.0 - layout.at(i - 1), layout.at(i - 1));
207 specialPath.closeSubpath();
210 specialPath.closeSubpath();
208 specialShadeItem->setPath(specialPath);
211 specialShadeItem->setPath(specialPath);
209 specialShadeItem->setVisible(true);
212 specialShadeItem->setVisible(true);
210 } else {
213 } else {
211 specialShadeItem->setVisible(false);
214 specialShadeItem->setVisible(false);
212 }
215 }
213 }
216 }
214 }
217 }
215 shadeItem->setPath(path);
218 shadeItem->setPath(path);
216 shadeItem->setVisible(true);
219 shadeItem->setVisible(true);
217 firstShade = false;
220 firstShade = false;
218 }
221 }
219 }
222 }
220
223
221 // Title, centered above the chart
224 // Title, centered above the chart
222 QString titleText = axis()->titleText();
225 QString titleText = axis()->titleText();
223 if (!titleText.isEmpty() && axis()->isTitleVisible()) {
226 if (!titleText.isEmpty() && axis()->isTitleVisible()) {
224 QRectF dummyRect;
227 QRectF truncatedRect;
225 qreal availableTitleHeight = axisGeometry().height() - labelPadding() - titlePadding() * 2.0;
228 qreal availableTitleHeight = axisGeometry().height() - labelPadding() - titlePadding() * 2.0;
226 qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").height();
229 qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").height();
227 availableTitleHeight -= minimumLabelHeight;
230 availableTitleHeight -= minimumLabelHeight;
228 title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0),
231 title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0),
229 axisGeometry().width(), availableTitleHeight,
232 axisGeometry().width(), availableTitleHeight,
230 dummyRect));
233 truncatedRect));
234 title->setTextWidth(truncatedRect.width());
231
235
232 QRectF titleBoundingRect = title->boundingRect();
236 QRectF titleBoundingRect = title->boundingRect();
233 QPointF titleCenter = center - titleBoundingRect.center();
237 QPointF titleCenter = center - titleBoundingRect.center();
234 title->setPos(titleCenter.x(), axisGeometry().top() - titlePadding() * 2.0 - titleBoundingRect.height() - labelHeight);
238 title->setPos(titleCenter.x(), axisGeometry().top() - titlePadding() * 2.0 - titleBoundingRect.height() - labelHeight);
235 }
239 }
236 }
240 }
237
241
238 Qt::Orientation PolarChartAxisAngular::orientation() const
242 Qt::Orientation PolarChartAxisAngular::orientation() const
239 {
243 {
240 return Qt::Horizontal;
244 return Qt::Horizontal;
241 }
245 }
242
246
243 void PolarChartAxisAngular::createItems(int count)
247 void PolarChartAxisAngular::createItems(int count)
244 {
248 {
245 if (arrowItems().count() == 0) {
249 if (arrowItems().count() == 0) {
246 // angular axis line
250 // angular axis line
247 QGraphicsEllipseItem *arrow = new QGraphicsEllipseItem(presenter()->rootItem());
251 QGraphicsEllipseItem *arrow = new QGraphicsEllipseItem(presenter()->rootItem());
248 arrow->setPen(axis()->linePen());
252 arrow->setPen(axis()->linePen());
249 arrowGroup()->addToGroup(arrow);
253 arrowGroup()->addToGroup(arrow);
250 }
254 }
251
255
252 for (int i = 0; i < count; ++i) {
256 for (int i = 0; i < count; ++i) {
253 QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
257 QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
254 QGraphicsLineItem *grid = new QGraphicsLineItem(presenter()->rootItem());
258 QGraphicsLineItem *grid = new QGraphicsLineItem(presenter()->rootItem());
255 QGraphicsTextItem *label = new QGraphicsTextItem(presenter()->rootItem());
259 QGraphicsTextItem *label = new QGraphicsTextItem(presenter()->rootItem());
256 label->document()->setDocumentMargin(ChartPresenter::textMargin());
260 label->document()->setDocumentMargin(ChartPresenter::textMargin());
257 QGraphicsTextItem *title = titleItem();
261 QGraphicsTextItem *title = titleItem();
258 arrow->setPen(axis()->linePen());
262 arrow->setPen(axis()->linePen());
259 grid->setPen(axis()->gridLinePen());
263 grid->setPen(axis()->gridLinePen());
260 label->setFont(axis()->labelsFont());
264 label->setFont(axis()->labelsFont());
261 label->setDefaultTextColor(axis()->labelsBrush().color());
265 label->setDefaultTextColor(axis()->labelsBrush().color());
262 label->setRotation(axis()->labelsAngle());
266 label->setRotation(axis()->labelsAngle());
263 title->setFont(axis()->titleFont());
267 title->setFont(axis()->titleFont());
264 title->setDefaultTextColor(axis()->titleBrush().color());
268 title->setDefaultTextColor(axis()->titleBrush().color());
265 title->setHtml(axis()->titleText());
269 title->setHtml(axis()->titleText());
266 arrowGroup()->addToGroup(arrow);
270 arrowGroup()->addToGroup(arrow);
267 gridGroup()->addToGroup(grid);
271 gridGroup()->addToGroup(grid);
268 labelGroup()->addToGroup(label);
272 labelGroup()->addToGroup(label);
269 if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) {
273 if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) {
270 QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem());
274 QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem());
271 shade->setPen(axis()->shadesPen());
275 shade->setPen(axis()->shadesPen());
272 shade->setBrush(axis()->shadesBrush());
276 shade->setBrush(axis()->shadesBrush());
273 shadeGroup()->addToGroup(shade);
277 shadeGroup()->addToGroup(shade);
274 }
278 }
275 }
279 }
276 }
280 }
277
281
278 void PolarChartAxisAngular::handleArrowPenChanged(const QPen &pen)
282 void PolarChartAxisAngular::handleArrowPenChanged(const QPen &pen)
279 {
283 {
280 bool first = true;
284 bool first = true;
281 foreach (QGraphicsItem *item, arrowItems()) {
285 foreach (QGraphicsItem *item, arrowItems()) {
282 if (first) {
286 if (first) {
283 first = false;
287 first = false;
284 // First arrow item is the outer circle of axis
288 // First arrow item is the outer circle of axis
285 static_cast<QGraphicsEllipseItem *>(item)->setPen(pen);
289 static_cast<QGraphicsEllipseItem *>(item)->setPen(pen);
286 } else {
290 } else {
287 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
291 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
288 }
292 }
289 }
293 }
290 }
294 }
291
295
292 void PolarChartAxisAngular::handleGridPenChanged(const QPen &pen)
296 void PolarChartAxisAngular::handleGridPenChanged(const QPen &pen)
293 {
297 {
294 foreach (QGraphicsItem *item, gridItems())
298 foreach (QGraphicsItem *item, gridItems())
295 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
299 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
296 }
300 }
297
301
298 QSizeF PolarChartAxisAngular::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
302 QSizeF PolarChartAxisAngular::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
299 {
303 {
300 Q_UNUSED(which);
304 Q_UNUSED(which);
301 Q_UNUSED(constraint);
305 Q_UNUSED(constraint);
302 return QSizeF(-1, -1);
306 return QSizeF(-1, -1);
303 }
307 }
304
308
305 qreal PolarChartAxisAngular::preferredAxisRadius(const QSizeF &maxSize)
309 qreal PolarChartAxisAngular::preferredAxisRadius(const QSizeF &maxSize)
306 {
310 {
307 qreal radius = maxSize.height() / 2.0;
311 qreal radius = maxSize.height() / 2.0;
308 if (maxSize.width() < maxSize.height())
312 if (maxSize.width() < maxSize.height())
309 radius = maxSize.width() / 2.0;
313 radius = maxSize.width() / 2.0;
310
314
311 if (axis()->labelsVisible()) {
315 if (axis()->labelsVisible()) {
312 QVector<qreal> layout = calculateLayout();
316 QVector<qreal> layout = calculateLayout();
313 if (layout.isEmpty())
317 if (layout.isEmpty())
314 return radius;
318 return radius;
315
319
316 createAxisLabels(layout);
320 createAxisLabels(layout);
317 QStringList labelList = labels();
321 QStringList labelList = labels();
318 QFont font = axis()->labelsFont();
322 QFont font = axis()->labelsFont();
319
323
320 QRectF maxRect;
324 QRectF maxRect;
321 maxRect.setSize(maxSize);
325 maxRect.setSize(maxSize);
322 maxRect.moveCenter(QPointF(0.0, 0.0));
326 maxRect.moveCenter(QPointF(0.0, 0.0));
323
327
324 // This is a horrible way to find out the maximum radius for angular axis and its labels.
328 // This is a horrible way to find out the maximum radius for angular axis and its labels.
325 // It just increments the radius down until everyhing fits the constraint size.
329 // It just increments the radius down until everyhing fits the constraint size.
326 // Proper way would be to actually calculate it but this seems to work reasonably fast as it is.
330 // Proper way would be to actually calculate it but this seems to work reasonably fast as it is.
327 bool nextTickVisible = false;
331 bool nextTickVisible = false;
328 for (int i = 0; i < layout.size(); ) {
332 for (int i = 0; i < layout.size(); ) {
329 if ((i == layout.size() - 1)
333 if ((i == layout.size() - 1)
330 || layout.at(i + 1) < 0.0
334 || layout.at(i + 1) < 0.0
331 || layout.at(i + 1) > 360.0) {
335 || layout.at(i + 1) > 360.0) {
332 nextTickVisible = false;
336 nextTickVisible = false;
333 } else {
337 } else {
334 nextTickVisible = true;
338 nextTickVisible = true;
335 }
339 }
336
340
337 qreal labelCoordinate = layout.at(i);
341 qreal labelCoordinate = layout.at(i);
338 qreal labelVisible;
342 qreal labelVisible;
339
343
340 if (intervalAxis()) {
344 if (intervalAxis()) {
341 qreal farEdge;
345 qreal farEdge;
342 if (i == (layout.size() - 1))
346 if (i == (layout.size() - 1))
343 farEdge = 360.0;
347 farEdge = 360.0;
344 else
348 else
345 farEdge = qMin(qreal(360.0), layout.at(i + 1));
349 farEdge = qMin(qreal(360.0), layout.at(i + 1));
346
350
347 // Adjust the labelCoordinate to show it if next tick is visible
351 // Adjust the labelCoordinate to show it if next tick is visible
348 if (nextTickVisible)
352 if (nextTickVisible)
349 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
353 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
350
354
351 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
355 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
352 }
356 }
353
357
354 if (labelCoordinate < 0.0 || labelCoordinate > 360.0)
358 if (labelCoordinate < 0.0 || labelCoordinate > 360.0)
355 labelVisible = false;
359 labelVisible = false;
356 else
360 else
357 labelVisible = true;
361 labelVisible = true;
358
362
359 if (!labelVisible) {
363 if (!labelVisible) {
360 i++;
364 i++;
361 continue;
365 continue;
362 }
366 }
363
367
364 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(), labelList.at(i), axis()->labelsAngle());
368 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(), labelList.at(i), axis()->labelsAngle());
365 QPointF labelPoint = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate).p2();
369 QPointF labelPoint = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate).p2();
366
370
367 boundingRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
371 boundingRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
368 QRectF intersectRect = maxRect.intersected(boundingRect);
372 QRectF intersectRect = maxRect.intersected(boundingRect);
369 if (boundingRect.isEmpty() || intersectRect == boundingRect) {
373 if (boundingRect.isEmpty() || intersectRect == boundingRect) {
370 i++;
374 i++;
371 } else {
375 } else {
372 qreal reduction(0.0);
376 qreal reduction(0.0);
373 // If there is no intersection, reduce by smallest dimension of label rect to be on the safe side
377 // If there is no intersection, reduce by smallest dimension of label rect to be on the safe side
374 if (intersectRect.isEmpty()) {
378 if (intersectRect.isEmpty()) {
375 reduction = qMin(boundingRect.height(), boundingRect.width());
379 reduction = qMin(boundingRect.height(), boundingRect.width());
376 } else {
380 } else {
377 // Approximate needed radius reduction is the amount label rect exceeds max rect in either dimension.
381 // Approximate needed radius reduction is the amount label rect exceeds max rect in either dimension.
378 // Could be further optimized by figuring out the proper math how to calculate exact needed reduction.
382 // Could be further optimized by figuring out the proper math how to calculate exact needed reduction.
379 reduction = qMax(boundingRect.height() - intersectRect.height(),
383 reduction = qMax(boundingRect.height() - intersectRect.height(),
380 boundingRect.width() - intersectRect.width());
384 boundingRect.width() - intersectRect.width());
381 }
385 }
382 // Typically the approximated reduction is little low, so add one
386 // Typically the approximated reduction is little low, so add one
383 radius -= (reduction + 1.0);
387 radius -= (reduction + 1.0);
384
388
385 if (radius < 1.0) // safeguard
389 if (radius < 1.0) // safeguard
386 return 1.0;
390 return 1.0;
387 }
391 }
388 }
392 }
389 }
393 }
390
394
391 if (!axis()->titleText().isEmpty() && axis()->isTitleVisible()) {
395 if (!axis()->titleText().isEmpty() && axis()->isTitleVisible()) {
392 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
396 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
393
397
394 radius -= titlePadding() + (titleRect.height() / 2.0);
398 radius -= titlePadding() + (titleRect.height() / 2.0);
395 if (radius < 1.0) // safeguard
399 if (radius < 1.0) // safeguard
396 return 1.0;
400 return 1.0;
397 }
401 }
398
402
399 return radius;
403 return radius;
400 }
404 }
401
405
402 QRectF PolarChartAxisAngular::moveLabelToPosition(qreal angularCoordinate, QPointF labelPoint, QRectF labelRect) const
406 QRectF PolarChartAxisAngular::moveLabelToPosition(qreal angularCoordinate, QPointF labelPoint, QRectF labelRect) const
403 {
407 {
404 if (angularCoordinate == 0.0)
408 if (angularCoordinate == 0.0)
405 labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0));
409 labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0));
406 else if (angularCoordinate < 90.0)
410 else if (angularCoordinate < 90.0)
407 labelRect.moveBottomLeft(labelPoint);
411 labelRect.moveBottomLeft(labelPoint);
408 else if (angularCoordinate == 90.0)
412 else if (angularCoordinate == 90.0)
409 labelRect.moveCenter(labelPoint + QPointF(labelRect.width() / 2.0 + 2.0, 0)); // +2 so that it does not hit the radial axis
413 labelRect.moveCenter(labelPoint + QPointF(labelRect.width() / 2.0 + 2.0, 0)); // +2 so that it does not hit the radial axis
410 else if (angularCoordinate < 180.0)
414 else if (angularCoordinate < 180.0)
411 labelRect.moveTopLeft(labelPoint);
415 labelRect.moveTopLeft(labelPoint);
412 else if (angularCoordinate == 180.0)
416 else if (angularCoordinate == 180.0)
413 labelRect.moveCenter(labelPoint + QPointF(0, labelRect.height() / 2.0));
417 labelRect.moveCenter(labelPoint + QPointF(0, labelRect.height() / 2.0));
414 else if (angularCoordinate < 270.0)
418 else if (angularCoordinate < 270.0)
415 labelRect.moveTopRight(labelPoint);
419 labelRect.moveTopRight(labelPoint);
416 else if (angularCoordinate == 270.0)
420 else if (angularCoordinate == 270.0)
417 labelRect.moveCenter(labelPoint + QPointF(-labelRect.width() / 2.0 - 2.0, 0)); // -2 so that it does not hit the radial axis
421 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 < 360.0)
422 else if (angularCoordinate < 360.0)
419 labelRect.moveBottomRight(labelPoint);
423 labelRect.moveBottomRight(labelPoint);
420 else
424 else
421 labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0));
425 labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0));
422 return labelRect;
426 return labelRect;
423 }
427 }
424
428
425 #include "moc_polarchartaxisangular_p.cpp"
429 #include "moc_polarchartaxisangular_p.cpp"
426
430
427 QTCOMMERCIALCHART_END_NAMESPACE
431 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,292 +1,296
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Enterprise Charts Add-on.
7 ** This file is part of the Qt Enterprise Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
11 ** accordance with the Qt Enterprise License Agreement provided with the
11 ** accordance with the Qt Enterprise License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "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 <QTextDocument>
26 #include <QTextDocument>
27
27
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29
29
30 PolarChartAxisRadial::PolarChartAxisRadial(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
30 PolarChartAxisRadial::PolarChartAxisRadial(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
31 : PolarChartAxis(axis, item, intervalAxis)
31 : PolarChartAxis(axis, item, intervalAxis)
32 {
32 {
33 }
33 }
34
34
35 PolarChartAxisRadial::~PolarChartAxisRadial()
35 PolarChartAxisRadial::~PolarChartAxisRadial()
36 {
36 {
37 }
37 }
38
38
39 void PolarChartAxisRadial::updateGeometry()
39 void PolarChartAxisRadial::updateGeometry()
40 {
40 {
41 const QVector<qreal> &layout = this->layout();
41 const QVector<qreal> &layout = this->layout();
42 if (layout.isEmpty())
42 if (layout.isEmpty())
43 return;
43 return;
44
44
45 createAxisLabels(layout);
45 createAxisLabels(layout);
46 QStringList labelList = labels();
46 QStringList labelList = labels();
47 QPointF center = axisGeometry().center();
47 QPointF center = axisGeometry().center();
48 QList<QGraphicsItem *> arrowItemList = arrowItems();
48 QList<QGraphicsItem *> arrowItemList = arrowItems();
49 QList<QGraphicsItem *> gridItemList = gridItems();
49 QList<QGraphicsItem *> gridItemList = gridItems();
50 QList<QGraphicsItem *> labelItemList = labelItems();
50 QList<QGraphicsItem *> labelItemList = labelItems();
51 QList<QGraphicsItem *> shadeItemList = shadeItems();
51 QList<QGraphicsItem *> shadeItemList = shadeItems();
52 QGraphicsTextItem* title = titleItem();
52 QGraphicsTextItem* title = titleItem();
53 qreal radius = axisGeometry().height() / 2.0;
53 qreal radius = axisGeometry().height() / 2.0;
54
54
55 QLineF line(center, center + QPointF(0, -radius));
55 QLineF line(center, center + QPointF(0, -radius));
56 QGraphicsLineItem *axisLine = static_cast<QGraphicsLineItem *>(arrowItemList.at(0));
56 QGraphicsLineItem *axisLine = static_cast<QGraphicsLineItem *>(arrowItemList.at(0));
57 axisLine->setLine(line);
57 axisLine->setLine(line);
58
58
59 QRectF previousLabelRect;
59 QRectF previousLabelRect;
60 bool firstShade = true;
60 bool firstShade = true;
61 bool nextTickVisible = false;
61 bool nextTickVisible = false;
62 if (layout.size())
62 if (layout.size())
63 nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > radius);
63 nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > radius);
64
64
65 for (int i = 0; i < layout.size(); ++i) {
65 for (int i = 0; i < layout.size(); ++i) {
66 qreal radialCoordinate = layout.at(i);
66 qreal radialCoordinate = layout.at(i);
67
67
68 QGraphicsEllipseItem *gridItem = static_cast<QGraphicsEllipseItem *>(gridItemList.at(i));
68 QGraphicsEllipseItem *gridItem = static_cast<QGraphicsEllipseItem *>(gridItemList.at(i));
69 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1));
69 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1));
70 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labelItemList.at(i));
70 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labelItemList.at(i));
71 QGraphicsPathItem *shadeItem = 0;
71 QGraphicsPathItem *shadeItem = 0;
72 if (i == 0)
72 if (i == 0)
73 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
73 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
74 else if (i % 2)
74 else if (i % 2)
75 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1));
75 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1));
76
76
77 // Ignore ticks outside valid range
77 // Ignore ticks outside valid range
78 bool currentTickVisible = nextTickVisible;
78 bool currentTickVisible = nextTickVisible;
79 if ((i == layout.size() - 1)
79 if ((i == layout.size() - 1)
80 || layout.at(i + 1) < 0.0
80 || layout.at(i + 1) < 0.0
81 || layout.at(i + 1) > radius) {
81 || layout.at(i + 1) > radius) {
82 nextTickVisible = false;
82 nextTickVisible = false;
83 } else {
83 } else {
84 nextTickVisible = true;
84 nextTickVisible = true;
85 }
85 }
86
86
87 qreal labelCoordinate = radialCoordinate;
87 qreal labelCoordinate = radialCoordinate;
88 qreal labelVisible = currentTickVisible;
88 qreal labelVisible = currentTickVisible;
89 qreal labelPad = labelPadding() / 2.0;
89 qreal labelPad = labelPadding() / 2.0;
90 if (intervalAxis()) {
90 if (intervalAxis()) {
91 qreal farEdge;
91 qreal farEdge;
92 if (i == (layout.size() - 1))
92 if (i == (layout.size() - 1))
93 farEdge = radius;
93 farEdge = radius;
94 else
94 else
95 farEdge = qMin(radius, layout.at(i + 1));
95 farEdge = qMin(radius, layout.at(i + 1));
96
96
97 // Adjust the labelCoordinate to show it if next tick is visible
97 // Adjust the labelCoordinate to show it if next tick is visible
98 if (nextTickVisible)
98 if (nextTickVisible)
99 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
99 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
100
100
101 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
101 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
102 if (labelCoordinate > 0.0 && labelCoordinate < radius)
102 if (labelCoordinate > 0.0 && labelCoordinate < radius)
103 labelVisible = true;
103 labelVisible = true;
104 else
104 else
105 labelVisible = false;
105 labelVisible = false;
106 }
106 }
107
107
108 // Radial axis label
108 // Radial axis label
109 if (axis()->labelsVisible() && labelVisible) {
109 if (axis()->labelsVisible() && labelVisible) {
110 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
111 labelList.at(i),
112 axis()->labelsAngle());
113 labelItem->setTextWidth(boundingRect.width());
110 labelItem->setHtml(labelList.at(i));
114 labelItem->setHtml(labelList.at(i));
111 QRectF labelRect = labelItem->boundingRect();
115 QRectF labelRect = labelItem->boundingRect();
112 QPointF labelCenter = labelRect.center();
116 QPointF labelCenter = labelRect.center();
113 labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
117 labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
114 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(), labelList.at(i), axis()->labelsAngle());
115 boundingRect.moveCenter(labelCenter);
118 boundingRect.moveCenter(labelCenter);
116 QPointF positionDiff(labelRect.topLeft() - boundingRect.topLeft());
119 QPointF positionDiff(labelRect.topLeft() - boundingRect.topLeft());
117 QPointF labelPoint = center;
120 QPointF labelPoint = center;
118 if (intervalAxis())
121 if (intervalAxis())
119 labelPoint += QPointF(labelPad, -labelCoordinate - (boundingRect.height() / 2.0));
122 labelPoint += QPointF(labelPad, -labelCoordinate - (boundingRect.height() / 2.0));
120 else
123 else
121 labelPoint += QPointF(labelPad, labelPad - labelCoordinate);
124 labelPoint += QPointF(labelPad, labelPad - labelCoordinate);
122 labelRect.moveTopLeft(labelPoint);
125 labelRect.moveTopLeft(labelPoint);
123 labelItem->setPos(labelRect.topLeft() + positionDiff);
126 labelItem->setPos(labelRect.topLeft() + positionDiff);
124
127
125 // Label overlap detection
128 // Label overlap detection
126 labelRect.setSize(boundingRect.size());
129 labelRect.setSize(boundingRect.size());
127 if ((i && previousLabelRect.intersects(labelRect))
130 if ((i && previousLabelRect.intersects(labelRect))
128 || !axisGeometry().contains(labelRect)) {
131 || !axisGeometry().contains(labelRect)) {
129 labelVisible = false;
132 labelVisible = false;
130 } else {
133 } else {
131 previousLabelRect = labelRect;
134 previousLabelRect = labelRect;
132 labelVisible = true;
135 labelVisible = true;
133 }
136 }
134 }
137 }
135
138
136 labelItem->setVisible(labelVisible);
139 labelItem->setVisible(labelVisible);
137 if (!currentTickVisible) {
140 if (!currentTickVisible) {
138 gridItem->setVisible(false);
141 gridItem->setVisible(false);
139 tickItem->setVisible(false);
142 tickItem->setVisible(false);
140 if (shadeItem)
143 if (shadeItem)
141 shadeItem->setVisible(false);
144 shadeItem->setVisible(false);
142 continue;
145 continue;
143 }
146 }
144
147
145 // Radial grid line
148 // Radial grid line
146 QRectF gridRect;
149 QRectF gridRect;
147 gridRect.setWidth(radialCoordinate * 2.0);
150 gridRect.setWidth(radialCoordinate * 2.0);
148 gridRect.setHeight(radialCoordinate * 2.0);
151 gridRect.setHeight(radialCoordinate * 2.0);
149 gridRect.moveCenter(center);
152 gridRect.moveCenter(center);
150
153
151 gridItem->setRect(gridRect);
154 gridItem->setRect(gridRect);
152 gridItem->setVisible(true);
155 gridItem->setVisible(true);
153
156
154 // Tick
157 // Tick
155 QLineF tickLine(-tickWidth(), 0.0, tickWidth(), 0.0);
158 QLineF tickLine(-tickWidth(), 0.0, tickWidth(), 0.0);
156 tickLine.translate(center.rx(), gridRect.top());
159 tickLine.translate(center.rx(), gridRect.top());
157 tickItem->setLine(tickLine);
160 tickItem->setLine(tickLine);
158 tickItem->setVisible(true);
161 tickItem->setVisible(true);
159
162
160 // Shades
163 // Shades
161 if (i % 2 || (i == 0 && !nextTickVisible)) {
164 if (i % 2 || (i == 0 && !nextTickVisible)) {
162 QPainterPath path;
165 QPainterPath path;
163 if (i == 0) {
166 if (i == 0) {
164 // If first tick is also the last, we need to custom fill the inner circle
167 // If first tick is also the last, we need to custom fill the inner circle
165 // or it won't get filled.
168 // or it won't get filled.
166 QRectF innerCircle(0.0, 0.0, layout.at(0) * 2.0, layout.at(0) * 2.0);
169 QRectF innerCircle(0.0, 0.0, layout.at(0) * 2.0, layout.at(0) * 2.0);
167 innerCircle.moveCenter(center);
170 innerCircle.moveCenter(center);
168 path.addEllipse(innerCircle);
171 path.addEllipse(innerCircle);
169 } else {
172 } else {
170 QRectF otherGridRect;
173 QRectF otherGridRect;
171 if (!nextTickVisible) { // Last visible tick
174 if (!nextTickVisible) { // Last visible tick
172 otherGridRect = axisGeometry();
175 otherGridRect = axisGeometry();
173 } else {
176 } else {
174 qreal otherGridRectDimension = layout.at(i + 1) * 2.0;
177 qreal otherGridRectDimension = layout.at(i + 1) * 2.0;
175 otherGridRect.setWidth(otherGridRectDimension);
178 otherGridRect.setWidth(otherGridRectDimension);
176 otherGridRect.setHeight(otherGridRectDimension);
179 otherGridRect.setHeight(otherGridRectDimension);
177 otherGridRect.moveCenter(center);
180 otherGridRect.moveCenter(center);
178 }
181 }
179 path.addEllipse(gridRect);
182 path.addEllipse(gridRect);
180 path.addEllipse(otherGridRect);
183 path.addEllipse(otherGridRect);
181
184
182 // Add additional shading in first visible shade item if there is a partial tick
185 // Add additional shading in first visible shade item if there is a partial tick
183 // to be filled at the center (log & category axes)
186 // to be filled at the center (log & category axes)
184 if (firstShade) {
187 if (firstShade) {
185 QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
188 QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
186 if (layout.at(i - 1) > 0.0) {
189 if (layout.at(i - 1) > 0.0) {
187 QRectF innerCircle(0.0, 0.0, layout.at(i - 1) * 2.0, layout.at(i - 1) * 2.0);
190 QRectF innerCircle(0.0, 0.0, layout.at(i - 1) * 2.0, layout.at(i - 1) * 2.0);
188 innerCircle.moveCenter(center);
191 innerCircle.moveCenter(center);
189 QPainterPath specialPath;
192 QPainterPath specialPath;
190 specialPath.addEllipse(innerCircle);
193 specialPath.addEllipse(innerCircle);
191 specialShadeItem->setPath(specialPath);
194 specialShadeItem->setPath(specialPath);
192 specialShadeItem->setVisible(true);
195 specialShadeItem->setVisible(true);
193 } else {
196 } else {
194 specialShadeItem->setVisible(false);
197 specialShadeItem->setVisible(false);
195 }
198 }
196 }
199 }
197 }
200 }
198 shadeItem->setPath(path);
201 shadeItem->setPath(path);
199 shadeItem->setVisible(true);
202 shadeItem->setVisible(true);
200 firstShade = false;
203 firstShade = false;
201 }
204 }
202 }
205 }
203
206
204 // Title, along the 0 axis
207 // Title, along the 0 axis
205 QString titleText = axis()->titleText();
208 QString titleText = axis()->titleText();
206 if (!titleText.isEmpty() && axis()->isTitleVisible()) {
209 if (!titleText.isEmpty() && axis()->isTitleVisible()) {
207 QRectF dummyRect;
210 QRectF truncatedRect;
208 title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0),
211 title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0),
209 radius, radius, dummyRect));
212 radius, radius, truncatedRect));
213 title->setTextWidth(truncatedRect.width());
210
214
211 QRectF titleBoundingRect = title->boundingRect();
215 QRectF titleBoundingRect = title->boundingRect();
212 QPointF titleCenter = titleBoundingRect.center();
216 QPointF titleCenter = titleBoundingRect.center();
213 QPointF arrowCenter = axisLine->boundingRect().center();
217 QPointF arrowCenter = axisLine->boundingRect().center();
214 QPointF titleCenterDiff = arrowCenter - titleCenter;
218 QPointF titleCenterDiff = arrowCenter - titleCenter;
215 title->setPos(titleCenterDiff.x() - titlePadding() - (titleBoundingRect.height() / 2.0), titleCenterDiff.y());
219 title->setPos(titleCenterDiff.x() - titlePadding() - (titleBoundingRect.height() / 2.0), titleCenterDiff.y());
216 title->setTransformOriginPoint(titleCenter);
220 title->setTransformOriginPoint(titleCenter);
217 title->setRotation(270.0);
221 title->setRotation(270.0);
218 }
222 }
219
223
220 QGraphicsLayoutItem::updateGeometry();
224 QGraphicsLayoutItem::updateGeometry();
221 }
225 }
222
226
223 Qt::Orientation PolarChartAxisRadial::orientation() const
227 Qt::Orientation PolarChartAxisRadial::orientation() const
224 {
228 {
225 return Qt::Vertical;
229 return Qt::Vertical;
226 }
230 }
227
231
228 void PolarChartAxisRadial::createItems(int count)
232 void PolarChartAxisRadial::createItems(int count)
229 {
233 {
230 if (arrowItems().count() == 0) {
234 if (arrowItems().count() == 0) {
231 // radial axis center line
235 // radial axis center line
232 QGraphicsLineItem *arrow = new LineArrowItem(this, presenter()->rootItem());
236 QGraphicsLineItem *arrow = new LineArrowItem(this, presenter()->rootItem());
233 arrow->setPen(axis()->linePen());
237 arrow->setPen(axis()->linePen());
234 arrowGroup()->addToGroup(arrow);
238 arrowGroup()->addToGroup(arrow);
235 }
239 }
236
240
237 for (int i = 0; i < count; ++i) {
241 for (int i = 0; i < count; ++i) {
238 QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
242 QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
239 QGraphicsEllipseItem *grid = new QGraphicsEllipseItem(presenter()->rootItem());
243 QGraphicsEllipseItem *grid = new QGraphicsEllipseItem(presenter()->rootItem());
240 QGraphicsTextItem *label = new QGraphicsTextItem(presenter()->rootItem());
244 QGraphicsTextItem *label = new QGraphicsTextItem(presenter()->rootItem());
241 label->document()->setDocumentMargin(ChartPresenter::textMargin());
245 label->document()->setDocumentMargin(ChartPresenter::textMargin());
242 QGraphicsTextItem *title = titleItem();
246 QGraphicsTextItem *title = titleItem();
243 arrow->setPen(axis()->linePen());
247 arrow->setPen(axis()->linePen());
244 grid->setPen(axis()->gridLinePen());
248 grid->setPen(axis()->gridLinePen());
245 label->setFont(axis()->labelsFont());
249 label->setFont(axis()->labelsFont());
246 label->setDefaultTextColor(axis()->labelsBrush().color());
250 label->setDefaultTextColor(axis()->labelsBrush().color());
247 label->setRotation(axis()->labelsAngle());
251 label->setRotation(axis()->labelsAngle());
248 title->setFont(axis()->titleFont());
252 title->setFont(axis()->titleFont());
249 title->setDefaultTextColor(axis()->titleBrush().color());
253 title->setDefaultTextColor(axis()->titleBrush().color());
250 title->setHtml(axis()->titleText());
254 title->setHtml(axis()->titleText());
251 arrowGroup()->addToGroup(arrow);
255 arrowGroup()->addToGroup(arrow);
252 gridGroup()->addToGroup(grid);
256 gridGroup()->addToGroup(grid);
253 labelGroup()->addToGroup(label);
257 labelGroup()->addToGroup(label);
254 if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) {
258 if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) {
255 QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem());
259 QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem());
256 shade->setPen(axis()->shadesPen());
260 shade->setPen(axis()->shadesPen());
257 shade->setBrush(axis()->shadesBrush());
261 shade->setBrush(axis()->shadesBrush());
258 shadeGroup()->addToGroup(shade);
262 shadeGroup()->addToGroup(shade);
259 }
263 }
260 }
264 }
261 }
265 }
262
266
263 void PolarChartAxisRadial::handleArrowPenChanged(const QPen &pen)
267 void PolarChartAxisRadial::handleArrowPenChanged(const QPen &pen)
264 {
268 {
265 foreach (QGraphicsItem *item, arrowItems())
269 foreach (QGraphicsItem *item, arrowItems())
266 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
270 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
267 }
271 }
268
272
269 void PolarChartAxisRadial::handleGridPenChanged(const QPen &pen)
273 void PolarChartAxisRadial::handleGridPenChanged(const QPen &pen)
270 {
274 {
271 foreach (QGraphicsItem *item, gridItems())
275 foreach (QGraphicsItem *item, gridItems())
272 static_cast<QGraphicsEllipseItem *>(item)->setPen(pen);
276 static_cast<QGraphicsEllipseItem *>(item)->setPen(pen);
273 }
277 }
274
278
275 QSizeF PolarChartAxisRadial::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
279 QSizeF PolarChartAxisRadial::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
276 {
280 {
277 Q_UNUSED(which);
281 Q_UNUSED(which);
278 Q_UNUSED(constraint);
282 Q_UNUSED(constraint);
279 return QSizeF(-1.0, -1.0);
283 return QSizeF(-1.0, -1.0);
280 }
284 }
281
285
282 qreal PolarChartAxisRadial::preferredAxisRadius(const QSizeF &maxSize)
286 qreal PolarChartAxisRadial::preferredAxisRadius(const QSizeF &maxSize)
283 {
287 {
284 qreal radius = maxSize.height() / 2.0;
288 qreal radius = maxSize.height() / 2.0;
285 if (maxSize.width() < maxSize.height())
289 if (maxSize.width() < maxSize.height())
286 radius = maxSize.width() / 2.0;
290 radius = maxSize.width() / 2.0;
287 return radius;
291 return radius;
288 }
292 }
289
293
290 #include "moc_polarchartaxisradial_p.cpp"
294 #include "moc_polarchartaxisradial_p.cpp"
291
295
292 QTCOMMERCIALCHART_END_NAMESPACE
296 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,225 +1,230
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Enterprise Charts Add-on.
7 ** This file is part of the Qt Enterprise Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
11 ** accordance with the Qt Enterprise License Agreement provided with the
11 ** accordance with the Qt Enterprise License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "verticalaxis_p.h"
21 #include "verticalaxis_p.h"
22 #include "qabstractaxis.h"
22 #include "qabstractaxis.h"
23 #include "chartpresenter_p.h"
23 #include "chartpresenter_p.h"
24 #include <QDebug>
24 #include <QDebug>
25
25
26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27
27
28 VerticalAxis::VerticalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
28 VerticalAxis::VerticalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
29 : CartesianChartAxis(axis, item, intervalAxis)
29 : CartesianChartAxis(axis, item, intervalAxis)
30 {
30 {
31 }
31 }
32
32
33 VerticalAxis::~VerticalAxis()
33 VerticalAxis::~VerticalAxis()
34 {
34 {
35 }
35 }
36
36
37 void VerticalAxis::updateGeometry()
37 void VerticalAxis::updateGeometry()
38 {
38 {
39 const QVector<qreal> &layout = ChartAxisElement::layout();
39 const QVector<qreal> &layout = ChartAxisElement::layout();
40
40
41 if (layout.isEmpty())
41 if (layout.isEmpty())
42 return;
42 return;
43
43
44 QStringList labelList = labels();
44 QStringList labelList = labels();
45
45
46 QList<QGraphicsItem *> lines = gridItems();
46 QList<QGraphicsItem *> lines = gridItems();
47 QList<QGraphicsItem *> labels = labelItems();
47 QList<QGraphicsItem *> labels = labelItems();
48 QList<QGraphicsItem *> shades = shadeItems();
48 QList<QGraphicsItem *> shades = shadeItems();
49 QList<QGraphicsItem *> arrow = arrowItems();
49 QList<QGraphicsItem *> arrow = arrowItems();
50 QGraphicsTextItem *title = titleItem();
50 QGraphicsTextItem *title = titleItem();
51
51
52 Q_ASSERT(labels.size() == labelList.size());
52 Q_ASSERT(labels.size() == labelList.size());
53 Q_ASSERT(layout.size() == labelList.size());
53 Q_ASSERT(layout.size() == labelList.size());
54
54
55 const QRectF &axisRect = axisGeometry();
55 const QRectF &axisRect = axisGeometry();
56 const QRectF &gridRect = gridGeometry();
56 const QRectF &gridRect = gridGeometry();
57
57
58 qreal height = axisRect.bottom();
58 qreal height = axisRect.bottom();
59
59
60
60
61 //arrow
61 //arrow
62 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem*>(arrow.at(0));
62 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem*>(arrow.at(0));
63
63
64 //arrow position
64 //arrow position
65 if (axis()->alignment() == Qt::AlignLeft)
65 if (axis()->alignment() == Qt::AlignLeft)
66 arrowItem->setLine(axisRect.right(), gridRect.top(), axisRect.right(), gridRect.bottom());
66 arrowItem->setLine(axisRect.right(), gridRect.top(), axisRect.right(), gridRect.bottom());
67 else if (axis()->alignment() == Qt::AlignRight)
67 else if (axis()->alignment() == Qt::AlignRight)
68 arrowItem->setLine(axisRect.left(), gridRect.top(), axisRect.left(), gridRect.bottom());
68 arrowItem->setLine(axisRect.left(), gridRect.top(), axisRect.left(), gridRect.bottom());
69
69
70 //title
70 //title
71 QRectF titleBoundingRect;
71 QRectF titleBoundingRect;
72 QString titleText = axis()->titleText();
72 QString titleText = axis()->titleText();
73 qreal availableSpace = axisRect.width() - labelPadding();
73 qreal availableSpace = axisRect.width() - labelPadding();
74 if (!titleText.isEmpty() && titleItem()->isVisible()) {
74 if (!titleText.isEmpty() && titleItem()->isVisible()) {
75 availableSpace -= titlePadding() * 2.0;
75 availableSpace -= titlePadding() * 2.0;
76 qreal minimumLabelWidth = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").width();
76 qreal minimumLabelWidth = ChartPresenter::textBoundingRect(axis()->labelsFont(), "...").width();
77 qreal titleSpace = availableSpace - minimumLabelWidth;
77 qreal titleSpace = availableSpace - minimumLabelWidth;
78 title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(90.0),
78 title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(90.0),
79 titleSpace, gridRect.height(),
79 titleSpace, gridRect.height(),
80 titleBoundingRect));
80 titleBoundingRect));
81 title->setTextWidth(titleBoundingRect.height());
81
82
82 titleBoundingRect = title->boundingRect();
83 titleBoundingRect = title->boundingRect();
83
84
84 QPointF center = gridRect.center() - titleBoundingRect.center();
85 QPointF center = gridRect.center() - titleBoundingRect.center();
85 if (axis()->alignment() == Qt::AlignLeft)
86 if (axis()->alignment() == Qt::AlignLeft)
86 title->setPos(axisRect.left() - titleBoundingRect.width() / 2.0 + titleBoundingRect.height() / 2.0 + titlePadding(), center.y());
87 title->setPos(axisRect.left() - titleBoundingRect.width() / 2.0 + titleBoundingRect.height() / 2.0 + titlePadding(), center.y());
87 else if (axis()->alignment() == Qt::AlignRight)
88 else if (axis()->alignment() == Qt::AlignRight)
88 title->setPos(axisRect.right() - titleBoundingRect.width() / 2.0 - titleBoundingRect.height() / 2.0 - titlePadding(), center.y());
89 title->setPos(axisRect.right() - titleBoundingRect.width() / 2.0 - titleBoundingRect.height() / 2.0 - titlePadding(), center.y());
89
90
90 title->setTransformOriginPoint(titleBoundingRect.center());
91 title->setTransformOriginPoint(titleBoundingRect.center());
91 title->setRotation(270);
92 title->setRotation(270);
92
93
93 availableSpace -= titleBoundingRect.height();
94 availableSpace -= titleBoundingRect.height();
94 }
95 }
95
96
96 for (int i = 0; i < layout.size(); ++i) {
97 for (int i = 0; i < layout.size(); ++i) {
97 //items
98 //items
98 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem *>(lines.at(i));
99 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem *>(lines.at(i));
99 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrow.at(i + 1));
100 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrow.at(i + 1));
100 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labels.at(i));
101 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labels.at(i));
101
102
102 //grid line
103 //grid line
103 gridItem->setLine(gridRect.left(), layout[i], gridRect.right(), layout[i]);
104 gridItem->setLine(gridRect.left(), layout[i], gridRect.right(), layout[i]);
104
105
105 //label text wrapping
106 //label text wrapping
106 QString text = labelList.at(i);
107 QString text = labelList.at(i);
107 QRectF boundingRect;
108 QRectF boundingRect;
108 // don't truncate empty labels
109 // don't truncate empty labels
109 if (text.isEmpty()) {
110 if (text.isEmpty()) {
110 labelItem->setHtml(text);
111 labelItem->setHtml(text);
111 } else {
112 } else {
112 qreal labelHeight = (axisRect.height() / layout.count()) - (2 * labelPadding());
113 qreal labelHeight = (axisRect.height() / layout.count()) - (2 * labelPadding());
113 labelItem->setHtml(ChartPresenter::truncatedText(axis()->labelsFont(), text,
114 QString truncatedText = ChartPresenter::truncatedText(axis()->labelsFont(), text,
114 axis()->labelsAngle(), availableSpace,
115 axis()->labelsAngle(),
115 labelHeight, boundingRect));
116 availableSpace,
117 labelHeight, boundingRect);
118 labelItem->setTextWidth(ChartPresenter::textBoundingRect(axis()->labelsFont(),
119 truncatedText).width());
120 labelItem->setHtml(truncatedText);
116 }
121 }
117
122
118 //label transformation origin point
123 //label transformation origin point
119 const QRectF &rect = labelItem->boundingRect();
124 const QRectF &rect = labelItem->boundingRect();
120 QPointF center = rect.center();
125 QPointF center = rect.center();
121 labelItem->setTransformOriginPoint(center.x(), center.y());
126 labelItem->setTransformOriginPoint(center.x(), center.y());
122 qreal widthDiff = rect.width() - boundingRect.width();
127 qreal widthDiff = rect.width() - boundingRect.width();
123 qreal heightDiff = rect.height() - boundingRect.height();
128 qreal heightDiff = rect.height() - boundingRect.height();
124
129
125 //ticks and label position
130 //ticks and label position
126 if (axis()->alignment() == Qt::AlignLeft) {
131 if (axis()->alignment() == Qt::AlignLeft) {
127 labelItem->setPos(axisRect.right() - rect.width() + (widthDiff / 2.0) - labelPadding(), layout[i] - center.y());
132 labelItem->setPos(axisRect.right() - rect.width() + (widthDiff / 2.0) - labelPadding(), layout[i] - center.y());
128 tickItem->setLine(axisRect.right() - labelPadding(), layout[i], axisRect.right(), layout[i]);
133 tickItem->setLine(axisRect.right() - labelPadding(), layout[i], axisRect.right(), layout[i]);
129 } else if (axis()->alignment() == Qt::AlignRight) {
134 } else if (axis()->alignment() == Qt::AlignRight) {
130 labelItem->setPos(axisRect.left() + labelPadding() - (widthDiff / 2.0), layout[i] - center.y());
135 labelItem->setPos(axisRect.left() + labelPadding() - (widthDiff / 2.0), layout[i] - center.y());
131 tickItem->setLine(axisRect.left(), layout[i], axisRect.left() + labelPadding(), layout[i]);
136 tickItem->setLine(axisRect.left(), layout[i], axisRect.left() + labelPadding(), layout[i]);
132 }
137 }
133
138
134 //label in between
139 //label in between
135 bool forceHide = false;
140 bool forceHide = false;
136 if (intervalAxis() && (i + 1) != layout.size()) {
141 if (intervalAxis() && (i + 1) != layout.size()) {
137 qreal lowerBound = qMin(layout[i], gridRect.bottom());
142 qreal lowerBound = qMin(layout[i], gridRect.bottom());
138 qreal upperBound = qMax(layout[i + 1], gridRect.top());
143 qreal upperBound = qMax(layout[i + 1], gridRect.top());
139 const qreal delta = lowerBound - upperBound;
144 const qreal delta = lowerBound - upperBound;
140 // Hide label in case visible part of the category at the grid edge is too narrow
145 // Hide label in case visible part of the category at the grid edge is too narrow
141 if (delta < boundingRect.height()
146 if (delta < boundingRect.height()
142 && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())
147 && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())
143 && !intervalAxis()) {
148 && !intervalAxis()) {
144 forceHide = true;
149 forceHide = true;
145 } else {
150 } else {
146 labelItem->setPos(labelItem->pos().x() , lowerBound - (delta / 2.0) - center.y());
151 labelItem->setPos(labelItem->pos().x() , lowerBound - (delta / 2.0) - center.y());
147 }
152 }
148 }
153 }
149
154
150 //label overlap detection - compensate one pixel for rounding errors
155 //label overlap detection - compensate one pixel for rounding errors
151 if ((labelItem->pos().y() + boundingRect.height() > height || forceHide ||
156 if ((labelItem->pos().y() + boundingRect.height() > height || forceHide ||
152 (labelItem->pos().y() + (heightDiff / 2.0) - 1.0) > axisRect.bottom() ||
157 (labelItem->pos().y() + (heightDiff / 2.0) - 1.0) > axisRect.bottom() ||
153 labelItem->pos().y() + (heightDiff / 2.0) < (axisRect.top() - 1.0))
158 labelItem->pos().y() + (heightDiff / 2.0) < (axisRect.top() - 1.0))
154 && !intervalAxis()) {
159 && !intervalAxis()) {
155 labelItem->setVisible(false);
160 labelItem->setVisible(false);
156 }
161 }
157 else {
162 else {
158 labelItem->setVisible(true);
163 labelItem->setVisible(true);
159 height=labelItem->pos().y();
164 height=labelItem->pos().y();
160 }
165 }
161
166
162 //shades
167 //shades
163 if ((i + 1) % 2 && i > 1) {
168 if ((i + 1) % 2 && i > 1) {
164 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem *>(shades.at(i / 2 - 1));
169 QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem *>(shades.at(i / 2 - 1));
165 qreal lowerBound = qMin(layout[i - 1], gridRect.bottom());
170 qreal lowerBound = qMin(layout[i - 1], gridRect.bottom());
166 qreal upperBound = qMax(layout[i], gridRect.top());
171 qreal upperBound = qMax(layout[i], gridRect.top());
167 rectItem->setRect(gridRect.left(), upperBound, gridRect.width(), lowerBound - upperBound);
172 rectItem->setRect(gridRect.left(), upperBound, gridRect.width(), lowerBound - upperBound);
168 if (rectItem->rect().height() <= 0.0)
173 if (rectItem->rect().height() <= 0.0)
169 rectItem->setVisible(false);
174 rectItem->setVisible(false);
170 else
175 else
171 rectItem->setVisible(true);
176 rectItem->setVisible(true);
172 }
177 }
173
178
174 // check if the grid line and the axis tick should be shown
179 // check if the grid line and the axis tick should be shown
175 qreal y = gridItem->line().p1().y();
180 qreal y = gridItem->line().p1().y();
176 if ((y < gridRect.top() || y > gridRect.bottom()))
181 if ((y < gridRect.top() || y > gridRect.bottom()))
177 {
182 {
178 gridItem->setVisible(false);
183 gridItem->setVisible(false);
179 tickItem->setVisible(false);
184 tickItem->setVisible(false);
180 }else{
185 }else{
181 gridItem->setVisible(true);
186 gridItem->setVisible(true);
182 tickItem->setVisible(true);
187 tickItem->setVisible(true);
183 }
188 }
184
189
185 }
190 }
186 //begin/end grid line in case labels between
191 //begin/end grid line in case labels between
187 if (intervalAxis()) {
192 if (intervalAxis()) {
188 QGraphicsLineItem *gridLine;
193 QGraphicsLineItem *gridLine;
189 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
194 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
190 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.right(), gridRect.top());
195 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.right(), gridRect.top());
191 gridLine->setVisible(true);
196 gridLine->setVisible(true);
192 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size() + 1));
197 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size() + 1));
193 gridLine->setLine(gridRect.left(), gridRect.bottom(), gridRect.right(), gridRect.bottom());
198 gridLine->setLine(gridRect.left(), gridRect.bottom(), gridRect.right(), gridRect.bottom());
194 gridLine->setVisible(true);
199 gridLine->setVisible(true);
195 }
200 }
196 }
201 }
197
202
198 QSizeF VerticalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
203 QSizeF VerticalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
199 {
204 {
200 Q_UNUSED(constraint);
205 Q_UNUSED(constraint);
201 QSizeF sh(0, 0);
206 QSizeF sh(0, 0);
202
207
203 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
208 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
204 return sh;
209 return sh;
205
210
206 switch (which) {
211 switch (which) {
207 case Qt::MinimumSize: {
212 case Qt::MinimumSize: {
208 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), "...");
213 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), "...");
209 sh = QSizeF(titleRect.height() + (titlePadding() * 2.0), titleRect.width());
214 sh = QSizeF(titleRect.height() + (titlePadding() * 2.0), titleRect.width());
210 break;
215 break;
211 }
216 }
212 case Qt::MaximumSize:
217 case Qt::MaximumSize:
213 case Qt::PreferredSize: {
218 case Qt::PreferredSize: {
214 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
219 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
215 sh = QSizeF(titleRect.height() + (titlePadding() * 2.0), titleRect.width());
220 sh = QSizeF(titleRect.height() + (titlePadding() * 2.0), titleRect.width());
216 break;
221 break;
217 }
222 }
218 default:
223 default:
219 break;
224 break;
220 }
225 }
221
226
222 return sh;
227 return sh;
223 }
228 }
224
229
225 QTCOMMERCIALCHART_END_NAMESPACE
230 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,90 +1,91
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Enterprise Charts Add-on.
7 ** This file is part of the Qt Enterprise Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
11 ** accordance with the Qt Enterprise License Agreement provided with the
11 ** accordance with the Qt Enterprise License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "charttitle_p.h"
21 #include "charttitle_p.h"
22 #include "chartpresenter_p.h"
22 #include "chartpresenter_p.h"
23 #include <QFont>
23 #include <QFont>
24 #include <QFontMetrics>
24 #include <QFontMetrics>
25 #include <QDebug>
25 #include <QDebug>
26 #include <QTextDocument>
26 #include <QTextDocument>
27
27
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29
29
30 ChartTitle::ChartTitle(QGraphicsItem *parent)
30 ChartTitle::ChartTitle(QGraphicsItem *parent)
31 : QGraphicsTextItem(parent)
31 : QGraphicsTextItem(parent)
32 {
32 {
33 document()->setDocumentMargin(ChartPresenter::textMargin());
33 document()->setDocumentMargin(ChartPresenter::textMargin());
34 }
34 }
35
35
36 ChartTitle::~ChartTitle()
36 ChartTitle::~ChartTitle()
37 {
37 {
38
38
39 }
39 }
40
40
41 void ChartTitle::setText(const QString &text)
41 void ChartTitle::setText(const QString &text)
42 {
42 {
43 m_text = text;
43 m_text = text;
44 }
44 }
45
45
46 QString ChartTitle::text() const
46 QString ChartTitle::text() const
47 {
47 {
48 return m_text;
48 return m_text;
49 }
49 }
50
50
51 void ChartTitle::setGeometry(const QRectF &rect)
51 void ChartTitle::setGeometry(const QRectF &rect)
52 {
52 {
53 QRectF dummyRect;
53 QRectF truncatedRect;
54 QGraphicsTextItem::setHtml(ChartPresenter::truncatedText(font(), m_text, qreal(0.0),
54 QGraphicsTextItem::setHtml(ChartPresenter::truncatedText(font(), m_text, qreal(0.0),
55 rect.width(), rect.height(),
55 rect.width(), rect.height(),
56 dummyRect));
56 truncatedRect));
57 QGraphicsTextItem::setTextWidth(truncatedRect.width());
57 setPos(rect.topLeft());
58 setPos(rect.topLeft());
58 }
59 }
59
60
60
61
61 QSizeF ChartTitle::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
62 QSizeF ChartTitle::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
62 {
63 {
63 Q_UNUSED(constraint);
64 Q_UNUSED(constraint);
64 QSizeF sh;
65 QSizeF sh;
65
66
66 switch (which) {
67 switch (which) {
67 case Qt::MinimumSize: {
68 case Qt::MinimumSize: {
68 QRectF titleRect = ChartPresenter::textBoundingRect(font(), "...");
69 QRectF titleRect = ChartPresenter::textBoundingRect(font(), "...");
69 sh = QSizeF(titleRect.width(), titleRect.height());
70 sh = QSizeF(titleRect.width(), titleRect.height());
70 break;
71 break;
71 }
72 }
72 case Qt::PreferredSize:
73 case Qt::PreferredSize:
73 case Qt::MaximumSize: {
74 case Qt::MaximumSize: {
74 QRectF titleRect = ChartPresenter::textBoundingRect(font(), m_text);
75 QRectF titleRect = ChartPresenter::textBoundingRect(font(), m_text);
75 sh = QSizeF(titleRect.width(), titleRect.height());
76 sh = QSizeF(titleRect.width(), titleRect.height());
76 break;
77 break;
77 }
78 }
78 case Qt::MinimumDescent: {
79 case Qt::MinimumDescent: {
79 QFontMetrics fn(font());
80 QFontMetrics fn(font());
80 sh = QSizeF(0, fn.descent());
81 sh = QSizeF(0, fn.descent());
81 break;
82 break;
82 }
83 }
83 default:
84 default:
84 break;
85 break;
85 }
86 }
86
87
87 return sh;
88 return sh;
88 }
89 }
89
90
90 QTCOMMERCIALCHART_END_NAMESPACE
91 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,190 +1,191
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Enterprise Charts Add-on.
7 ** This file is part of the Qt Enterprise Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
11 ** accordance with the Qt Enterprise License Agreement provided with the
11 ** accordance with the Qt Enterprise License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include <QPainter>
21 #include <QPainter>
22 #include <QGraphicsSceneEvent>
22 #include <QGraphicsSceneEvent>
23 #include <QGraphicsTextItem>
23 #include <QGraphicsTextItem>
24 #include <QTextDocument>
24 #include <QTextDocument>
25
25
26 #include "qlegend.h"
26 #include "qlegend.h"
27 #include "qlegend_p.h"
27 #include "qlegend_p.h"
28 #include "qlegendmarker.h"
28 #include "qlegendmarker.h"
29 #include "qlegendmarker_p.h"
29 #include "qlegendmarker_p.h"
30 #include "legendmarkeritem_p.h"
30 #include "legendmarkeritem_p.h"
31 #include "chartpresenter_p.h"
31 #include "chartpresenter_p.h"
32
32
33 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 QTCOMMERCIALCHART_BEGIN_NAMESPACE
34
34
35 LegendMarkerItem::LegendMarkerItem(QLegendMarkerPrivate *marker, QGraphicsObject *parent) :
35 LegendMarkerItem::LegendMarkerItem(QLegendMarkerPrivate *marker, QGraphicsObject *parent) :
36 QGraphicsObject(parent),
36 QGraphicsObject(parent),
37 m_marker(marker),
37 m_marker(marker),
38 m_markerRect(0,0,10.0,10.0),
38 m_markerRect(0,0,10.0,10.0),
39 m_boundingRect(0,0,0,0),
39 m_boundingRect(0,0,0,0),
40 m_textItem(new QGraphicsTextItem(this)),
40 m_textItem(new QGraphicsTextItem(this)),
41 m_rectItem(new QGraphicsRectItem(this)),
41 m_rectItem(new QGraphicsRectItem(this)),
42 m_margin(3),
42 m_margin(3),
43 m_space(4),
43 m_space(4),
44 m_hovering(false),
44 m_hovering(false),
45 m_pressPos(0, 0)
45 m_pressPos(0, 0)
46 {
46 {
47 m_rectItem->setRect(m_markerRect);
47 m_rectItem->setRect(m_markerRect);
48 m_textItem->document()->setDocumentMargin(ChartPresenter::textMargin());
48 m_textItem->document()->setDocumentMargin(ChartPresenter::textMargin());
49 setAcceptHoverEvents(true);
49 setAcceptHoverEvents(true);
50 }
50 }
51
51
52 LegendMarkerItem::~LegendMarkerItem()
52 LegendMarkerItem::~LegendMarkerItem()
53 {
53 {
54 if (m_hovering) {
54 if (m_hovering) {
55 emit m_marker->q_ptr->hovered(false);
55 emit m_marker->q_ptr->hovered(false);
56 }
56 }
57 }
57 }
58
58
59 void LegendMarkerItem::setPen(const QPen &pen)
59 void LegendMarkerItem::setPen(const QPen &pen)
60 {
60 {
61 m_rectItem->setPen(pen);
61 m_rectItem->setPen(pen);
62 }
62 }
63
63
64 QPen LegendMarkerItem::pen() const
64 QPen LegendMarkerItem::pen() const
65 {
65 {
66 return m_rectItem->pen();
66 return m_rectItem->pen();
67 }
67 }
68
68
69 void LegendMarkerItem::setBrush(const QBrush &brush)
69 void LegendMarkerItem::setBrush(const QBrush &brush)
70 {
70 {
71 m_rectItem->setBrush(brush);
71 m_rectItem->setBrush(brush);
72 }
72 }
73
73
74 QBrush LegendMarkerItem::brush() const
74 QBrush LegendMarkerItem::brush() const
75 {
75 {
76 return m_rectItem->brush();
76 return m_rectItem->brush();
77 }
77 }
78
78
79 void LegendMarkerItem::setFont(const QFont &font)
79 void LegendMarkerItem::setFont(const QFont &font)
80 {
80 {
81 m_textItem->setFont(font);
81 m_textItem->setFont(font);
82 QFontMetrics fn(font);
82 QFontMetrics fn(font);
83 m_markerRect = QRectF(0,0,fn.height()/2,fn.height()/2);
83 m_markerRect = QRectF(0,0,fn.height()/2,fn.height()/2);
84 updateGeometry();
84 updateGeometry();
85 }
85 }
86
86
87 QFont LegendMarkerItem::font() const
87 QFont LegendMarkerItem::font() const
88 {
88 {
89 return m_textItem->font();
89 return m_textItem->font();
90 }
90 }
91
91
92 void LegendMarkerItem::setLabel(const QString label)
92 void LegendMarkerItem::setLabel(const QString label)
93 {
93 {
94 m_label = label;
94 m_label = label;
95 updateGeometry();
95 updateGeometry();
96 }
96 }
97
97
98 QString LegendMarkerItem::label() const
98 QString LegendMarkerItem::label() const
99 {
99 {
100 return m_label;
100 return m_label;
101 }
101 }
102
102
103 void LegendMarkerItem::setLabelBrush(const QBrush &brush)
103 void LegendMarkerItem::setLabelBrush(const QBrush &brush)
104 {
104 {
105 m_textItem->setDefaultTextColor(brush.color());
105 m_textItem->setDefaultTextColor(brush.color());
106 }
106 }
107
107
108 QBrush LegendMarkerItem::labelBrush() const
108 QBrush LegendMarkerItem::labelBrush() const
109 {
109 {
110 return QBrush(m_textItem->defaultTextColor());
110 return QBrush(m_textItem->defaultTextColor());
111 }
111 }
112
112
113 void LegendMarkerItem::setGeometry(const QRectF &rect)
113 void LegendMarkerItem::setGeometry(const QRectF &rect)
114 {
114 {
115 qreal width = rect.width();
115 qreal width = rect.width();
116 qreal x = m_margin + m_markerRect.width() + m_space + m_margin;
116 qreal x = m_margin + m_markerRect.width() + m_space + m_margin;
117 QRectF truncatedRect;
117 QRectF truncatedRect;
118
118
119 m_textItem->setHtml(ChartPresenter::truncatedText(m_textItem->font(), m_label, qreal(0.0),
119 m_textItem->setHtml(ChartPresenter::truncatedText(m_textItem->font(), m_label, qreal(0.0),
120 width - x, rect.height(), truncatedRect));
120 width - x, rect.height(), truncatedRect));
121 m_textItem->setTextWidth(truncatedRect.width());
121
122
122 qreal y = qMax(m_markerRect.height() + 2 * m_margin, truncatedRect.height() + 2 * m_margin);
123 qreal y = qMax(m_markerRect.height() + 2 * m_margin, truncatedRect.height() + 2 * m_margin);
123
124
124 const QRectF &textRect = m_textItem->boundingRect();
125 const QRectF &textRect = m_textItem->boundingRect();
125
126
126 m_textItem->setPos(x - m_margin, y / 2 - textRect.height() / 2);
127 m_textItem->setPos(x - m_margin, y / 2 - textRect.height() / 2);
127 m_rectItem->setRect(m_markerRect);
128 m_rectItem->setRect(m_markerRect);
128 // The textMargin adjustments to position are done to make default case rects less blurry with anti-aliasing
129 // The textMargin adjustments to position are done to make default case rects less blurry with anti-aliasing
129 m_rectItem->setPos(m_margin - ChartPresenter::textMargin(), y / 2.0 - m_markerRect.height() / 2.0 + ChartPresenter::textMargin());
130 m_rectItem->setPos(m_margin - ChartPresenter::textMargin(), y / 2.0 - m_markerRect.height() / 2.0 + ChartPresenter::textMargin());
130
131
131 prepareGeometryChange();
132 prepareGeometryChange();
132 m_boundingRect = QRectF(0, 0, x + textRect.width() + m_margin, y);
133 m_boundingRect = QRectF(0, 0, x + textRect.width() + m_margin, y);
133 }
134 }
134
135
135 QRectF LegendMarkerItem::boundingRect() const
136 QRectF LegendMarkerItem::boundingRect() const
136 {
137 {
137 return m_boundingRect;
138 return m_boundingRect;
138 }
139 }
139
140
140 void LegendMarkerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
141 void LegendMarkerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
141 {
142 {
142 Q_UNUSED(option)
143 Q_UNUSED(option)
143 Q_UNUSED(widget)
144 Q_UNUSED(widget)
144 Q_UNUSED(painter)
145 Q_UNUSED(painter)
145 }
146 }
146
147
147 QSizeF LegendMarkerItem::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const
148 QSizeF LegendMarkerItem::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const
148 {
149 {
149 Q_UNUSED(constraint)
150 Q_UNUSED(constraint)
150
151
151 QSizeF sh;
152 QSizeF sh;
152
153
153 switch (which) {
154 switch (which) {
154 case Qt::MinimumSize: {
155 case Qt::MinimumSize: {
155 QRectF labelRect = ChartPresenter::textBoundingRect(m_textItem->font(), "...");
156 QRectF labelRect = ChartPresenter::textBoundingRect(m_textItem->font(), "...");
156 sh = QSizeF(labelRect.width() + (2.0 * m_margin) + m_space + m_markerRect.width(),
157 sh = QSizeF(labelRect.width() + (2.0 * m_margin) + m_space + m_markerRect.width(),
157 qMax(m_markerRect.height(), labelRect.height()) + (2.0 * m_margin));
158 qMax(m_markerRect.height(), labelRect.height()) + (2.0 * m_margin));
158 break;
159 break;
159 }
160 }
160 case Qt::PreferredSize: {
161 case Qt::PreferredSize: {
161 QRectF labelRect = ChartPresenter::textBoundingRect(m_textItem->font(), m_label);
162 QRectF labelRect = ChartPresenter::textBoundingRect(m_textItem->font(), m_label);
162 sh = QSizeF(labelRect.width() + (2.0 * m_margin) + m_space + m_markerRect.width(),
163 sh = QSizeF(labelRect.width() + (2.0 * m_margin) + m_space + m_markerRect.width(),
163 qMax(m_markerRect.height(), labelRect.height()) + (2.0 * m_margin));
164 qMax(m_markerRect.height(), labelRect.height()) + (2.0 * m_margin));
164 break;
165 break;
165 }
166 }
166 default:
167 default:
167 break;
168 break;
168 }
169 }
169
170
170 return sh;
171 return sh;
171 }
172 }
172
173
173 void LegendMarkerItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
174 void LegendMarkerItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
174 {
175 {
175 Q_UNUSED(event)
176 Q_UNUSED(event)
176 m_hovering = true;
177 m_hovering = true;
177 emit m_marker->q_ptr->hovered(true);
178 emit m_marker->q_ptr->hovered(true);
178 }
179 }
179
180
180 void LegendMarkerItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
181 void LegendMarkerItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
181 {
182 {
182 Q_UNUSED(event)
183 Q_UNUSED(event)
183 m_hovering = false;
184 m_hovering = false;
184 emit m_marker->q_ptr->hovered(false);
185 emit m_marker->q_ptr->hovered(false);
185 }
186 }
186
187
187
188
188 #include "moc_legendmarkeritem_p.cpp"
189 #include "moc_legendmarkeritem_p.cpp"
189
190
190 QTCOMMERCIALCHART_END_NAMESPACE
191 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now