##// END OF EJS Templates
Fix some warnings for android build....
Miikka Heikkinen -
r2504:54fd83ddb7ed
parent child
Show More
@@ -1,120 +1,126
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "polarchartaxis_p.h"
22 22 #include "qabstractaxis_p.h"
23 23 #include "chartpresenter_p.h"
24 24
25 25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 26
27 27 PolarChartAxis::PolarChartAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
28 28 : ChartAxisElement(axis, item, intervalAxis)
29 29 {
30 30 }
31 31
32 32 PolarChartAxis::~PolarChartAxis()
33 33 {
34 34
35 35 }
36 36
37 37 void PolarChartAxis::setGeometry(const QRectF &axis, const QRectF &grid)
38 38 {
39 39 Q_UNUSED(grid);
40 40 setAxisGeometry(axis);
41 41
42 42 if (isEmpty())
43 43 return;
44 44
45 45 QVector<qreal> layout = calculateLayout();
46 46 updateLayout(layout);
47 47 }
48 48
49 49 QRectF PolarChartAxis::gridGeometry() const
50 50 {
51 51 return QRectF();
52 52 }
53 53
54 54 void PolarChartAxis::updateLayout(QVector<qreal> &layout)
55 55 {
56 56 int diff = ChartAxisElement::layout().size() - layout.size();
57 57
58 58 if (animation()) {
59 59 switch (presenter()->state()) {
60 case ChartPresenter::ZoomInState:
61 case ChartPresenter::ZoomOutState:
62 case ChartPresenter::ScrollUpState:
63 case ChartPresenter::ScrollLeftState:
64 case ChartPresenter::ScrollDownState:
65 case ChartPresenter::ScrollRightState:
60 66 case ChartPresenter::ShowState:
61 67 animation()->setAnimationType(AxisAnimation::DefaultAnimation);
62 68 break;
63 69 }
64 70 // Update to "old" geometry before starting animation to avoid incorrectly sized
65 71 // axes lingering in wrong position compared to series plot before animation can kick in.
66 72 // Note that the position mismatch still exists even with this update, but it will be
67 73 // far less ugly.
68 74 updateGeometry();
69 75 }
70 76
71 77 if (diff > 0)
72 78 deleteItems(diff);
73 79 else if (diff < 0)
74 80 createItems(-diff);
75 81
76 82 if (animation()) {
77 83 animation()->setValues(ChartAxisElement::layout(), layout);
78 84 presenter()->startAnimation(animation());
79 85 } else {
80 86 setLayout(layout);
81 87 updateGeometry();
82 88 }
83 89 }
84 90
85 91 bool PolarChartAxis::isEmpty()
86 92 {
87 93 return !axisGeometry().isValid() || qFuzzyIsNull(min() - max());
88 94 }
89 95
90 96 void PolarChartAxis::deleteItems(int count)
91 97 {
92 98 QList<QGraphicsItem *> gridLines = gridItems();
93 99 QList<QGraphicsItem *> labels = labelItems();
94 100 QList<QGraphicsItem *> shades = shadeItems();
95 101 QList<QGraphicsItem *> axis = arrowItems();
96 102
97 103 for (int i = 0; i < count; ++i) {
98 104 if (gridItems().size() == 1 || (((gridLines.size() + 1) % 2) && gridLines.size() > 0))
99 105 delete(shades.takeLast());
100 106 delete(gridLines.takeLast());
101 107 delete(labels.takeLast());
102 108 delete(axis.takeLast());
103 109 }
104 110 }
105 111
106 112 void PolarChartAxis::handleShadesBrushChanged(const QBrush &brush)
107 113 {
108 114 foreach (QGraphicsItem *item, shadeItems())
109 115 static_cast<QGraphicsPathItem *>(item)->setBrush(brush);
110 116 }
111 117
112 118 void PolarChartAxis::handleShadesPenChanged(const QPen &pen)
113 119 {
114 120 foreach (QGraphicsItem *item, shadeItems())
115 121 static_cast<QGraphicsPathItem *>(item)->setPen(pen);
116 122 }
117 123
118 124 #include "moc_polarchartaxis_p.cpp"
119 125
120 126 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,428 +1,425
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "polarchartaxisangular_p.h"
22 22 #include "chartpresenter_p.h"
23 23 #include "abstractchartlayout_p.h"
24 24 #include "qabstractaxis.h"
25 25 #include "qabstractaxis_p.h"
26 26 #include <QFontMetrics>
27 27 #include <QDebug>
28 28
29 29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 30
31 31 PolarChartAxisAngular::PolarChartAxisAngular(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
32 32 : PolarChartAxis(axis, item, intervalAxis)
33 33 {
34 34 }
35 35
36 36 PolarChartAxisAngular::~PolarChartAxisAngular()
37 37 {
38 38 }
39 39
40 40 void PolarChartAxisAngular::updateGeometry()
41 41 {
42 42 QGraphicsLayoutItem::updateGeometry();
43 43
44 44 const QVector<qreal> &layout = this->layout();
45 45 if (layout.isEmpty())
46 46 return;
47 47
48 48 createAxisLabels(layout);
49 49 QStringList labelList = labels();
50 50 QPointF center = axisGeometry().center();
51 51 QList<QGraphicsItem *> arrowItemList = arrowItems();
52 52 QList<QGraphicsItem *> gridItemList = gridItems();
53 53 QList<QGraphicsItem *> labelItemList = labelItems();
54 54 QList<QGraphicsItem *> shadeItemList = shadeItems();
55 55 QGraphicsSimpleTextItem *title = titleItem();
56 56
57 57 QGraphicsEllipseItem *axisLine = static_cast<QGraphicsEllipseItem *>(arrowItemList.at(0));
58 58 axisLine->setRect(axisGeometry());
59 59
60 60 qreal radius = axisGeometry().height() / 2.0;
61 61
62 62 QFontMetrics fn(axis()->labelsFont());
63 63 QRectF previousLabelRect;
64 64 QRectF firstLabelRect;
65 65
66 66 qreal labelHeight = 0;
67 67
68 68 bool firstShade = true;
69 69 bool nextTickVisible = false;
70 70 if (layout.size())
71 71 nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > 360.0);
72 72
73 73 for (int i = 0; i < layout.size(); ++i) {
74 74 qreal angularCoordinate = layout.at(i);
75 75
76 76 QGraphicsLineItem *gridLineItem = static_cast<QGraphicsLineItem *>(gridItemList.at(i));
77 77 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1));
78 78 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labelItemList.at(i));
79 79 QGraphicsPathItem *shadeItem = 0;
80 80 if (i == 0)
81 81 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
82 82 else if (i % 2)
83 83 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1));
84 84
85 85 // Ignore ticks outside valid range
86 86 bool currentTickVisible = nextTickVisible;
87 87 if ((i == layout.size() - 1)
88 88 || layout.at(i + 1) < 0.0
89 89 || layout.at(i + 1) > 360.0) {
90 90 nextTickVisible = false;
91 91 } else {
92 92 nextTickVisible = true;
93 93 }
94 94
95 95 qreal labelCoordinate = angularCoordinate;
96 96 qreal labelVisible = currentTickVisible;
97 97 if (intervalAxis()) {
98 98 qreal farEdge;
99 99 if (i == (layout.size() - 1))
100 100 farEdge = 360.0;
101 101 else
102 farEdge = qMin(360.0, layout.at(i + 1));
102 farEdge = qMin(qreal(360.0), layout.at(i + 1));
103 103
104 104 // Adjust the labelCoordinate to show it if next tick is visible
105 105 if (nextTickVisible)
106 labelCoordinate = qMax(0.0, labelCoordinate);
106 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
107 107
108 108 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
109 109 // Don't display label once the category gets too small near the axis
110 110 if (labelCoordinate < 5.0 || labelCoordinate > 355.0)
111 111 labelVisible = false;
112 112 else
113 113 labelVisible = true;
114 114 }
115 115
116 116 // Need this also in label calculations, so determine it first
117 117 QLineF tickLine(QLineF::fromPolar(radius - tickWidth(), 90.0 - angularCoordinate).p2(),
118 118 QLineF::fromPolar(radius + tickWidth(), 90.0 - angularCoordinate).p2());
119 119 tickLine.translate(center);
120 120
121 121 // Angular axis label
122 122 if (axis()->labelsVisible() && labelVisible) {
123 123 labelItem->setText(labelList.at(i));
124 124 const QRectF &rect = labelItem->boundingRect();
125 125 QPointF labelCenter = rect.center();
126 126 labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
127 127 QRectF boundingRect = labelBoundingRect(fn, labelList.at(i));
128 128 boundingRect.moveCenter(labelCenter);
129 129 QPointF positionDiff(rect.topLeft() - boundingRect.topLeft());
130 130
131 131 QPointF labelPoint;
132 132 if (intervalAxis()) {
133 133 QLineF labelLine = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate);
134 134 labelLine.translate(center);
135 135 labelPoint = labelLine.p2();
136 136 } else {
137 137 labelPoint = tickLine.p2();
138 138 }
139 139
140 140 QRectF labelRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
141 141 labelItem->setPos(labelRect.topLeft() + positionDiff);
142 142
143 143 // Store height for title calculations
144 144 qreal labelClearance = axisGeometry().top() - labelRect.top();
145 145 labelHeight = qMax(labelHeight, labelClearance);
146 146
147 147 // Label overlap detection
148 148 if (i && (previousLabelRect.intersects(labelRect) || firstLabelRect.intersects(labelRect))) {
149 149 labelVisible = false;
150 150 } else {
151 151 // Store labelRect for future comparison. Some area is deducted to make things look
152 152 // little nicer, as usually intersection happens at label corner with angular labels.
153 153 labelRect.adjust(-2.0, -4.0, -2.0, -4.0);
154 154 if (firstLabelRect.isEmpty())
155 155 firstLabelRect = labelRect;
156 156
157 157 previousLabelRect = labelRect;
158 158 labelVisible = true;
159 159 }
160 160 }
161 161
162 162 labelItem->setVisible(labelVisible);
163 163 if (!currentTickVisible) {
164 164 gridLineItem->setVisible(false);
165 165 tickItem->setVisible(false);
166 166 if (shadeItem)
167 167 shadeItem->setVisible(false);
168 168 continue;
169 169 }
170 170
171 171 // Angular grid line
172 172 QLineF gridLine = QLineF::fromPolar(radius, 90.0 - angularCoordinate);
173 173 gridLine.translate(center);
174 174 gridLineItem->setLine(gridLine);
175 175 gridLineItem->setVisible(true);
176 176
177 177 // Tick
178 178 tickItem->setLine(tickLine);
179 179 tickItem->setVisible(true);
180 180
181 181 // Shades
182 182 if (i % 2 || (i == 0 && !nextTickVisible)) {
183 183 QPainterPath path;
184 184 path.moveTo(center);
185 185 if (i == 0) {
186 186 // If first tick is also the last, we need to custom fill the first partial arc
187 187 // or it won't get filled.
188 188 path.arcTo(axisGeometry(), 90.0 - layout.at(0), layout.at(0));
189 189 path.closeSubpath();
190 190 } else {
191 191 qreal nextCoordinate;
192 192 if (!nextTickVisible) // Last visible tick
193 193 nextCoordinate = 360.0;
194 194 else
195 195 nextCoordinate = layout.at(i + 1);
196 196 qreal arcSpan = angularCoordinate - nextCoordinate;
197 197 path.arcTo(axisGeometry(), 90.0 - angularCoordinate, arcSpan);
198 198 path.closeSubpath();
199 199
200 200 // Add additional arc for first shade item if there is a partial arc to be filled
201 201 if (firstShade) {
202 202 QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
203 203 if (layout.at(i - 1) > 0.0) {
204 204 QPainterPath specialPath;
205 205 specialPath.moveTo(center);
206 206 specialPath.arcTo(axisGeometry(), 90.0 - layout.at(i - 1), layout.at(i - 1));
207 207 specialPath.closeSubpath();
208 208 specialShadeItem->setPath(specialPath);
209 209 specialShadeItem->setVisible(true);
210 210 } else {
211 211 specialShadeItem->setVisible(false);
212 212 }
213 213 }
214 214 }
215 215 shadeItem->setPath(path);
216 216 shadeItem->setVisible(true);
217 217 firstShade = false;
218 218 }
219 219 }
220 220
221 221 // Title, centered above the chart
222 222 QString titleText = axis()->titleText();
223 223 if (!titleText.isEmpty() && axis()->isTitleVisible()) {
224 224 int size(0);
225 225 size = axisGeometry().width();
226 226
227 227 QFontMetrics titleMetrics(axis()->titleFont());
228 228 if (titleMetrics.boundingRect(titleText).width() > size) {
229 229 QString string = titleText + "...";
230 230 while (titleMetrics.boundingRect(string).width() > size && string.length() > 3)
231 231 string.remove(string.length() - 4, 1);
232 232 title->setText(string);
233 233 } else {
234 234 title->setText(titleText);
235 235 }
236 236
237 237 QRectF titleBoundingRect;
238 238 titleBoundingRect = title->boundingRect();
239 239 QPointF titleCenter = center - titleBoundingRect.center();
240 240 title->setPos(titleCenter.x(), axisGeometry().top() - qreal(titlePadding()) * 2.0 - titleBoundingRect.height() - labelHeight);
241 241 }
242 242 }
243 243
244 244 Qt::Orientation PolarChartAxisAngular::orientation() const
245 245 {
246 246 return Qt::Horizontal;
247 247 }
248 248
249 249 void PolarChartAxisAngular::createItems(int count)
250 250 {
251 251 if (arrowItems().count() == 0) {
252 252 // angular axis line
253 253 // TODO: need class similar to LineArrowItem for click handling?
254 254 QGraphicsEllipseItem *arrow = new QGraphicsEllipseItem(presenter()->rootItem());
255 255 arrow->setPen(axis()->linePen());
256 256 arrowGroup()->addToGroup(arrow);
257 257 }
258 258
259 259 for (int i = 0; i < count; ++i) {
260 260 QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
261 261 QGraphicsLineItem *grid = new QGraphicsLineItem(presenter()->rootItem());
262 262 QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem(presenter()->rootItem());
263 263 QGraphicsSimpleTextItem *title = titleItem();
264 264 arrow->setPen(axis()->linePen());
265 265 grid->setPen(axis()->gridLinePen());
266 266 label->setFont(axis()->labelsFont());
267 267 label->setPen(axis()->labelsPen());
268 268 label->setBrush(axis()->labelsBrush());
269 269 label->setRotation(axis()->labelsAngle());
270 270 title->setFont(axis()->titleFont());
271 271 title->setPen(axis()->titlePen());
272 272 title->setBrush(axis()->titleBrush());
273 273 title->setText(axis()->titleText());
274 274 arrowGroup()->addToGroup(arrow);
275 275 gridGroup()->addToGroup(grid);
276 276 labelGroup()->addToGroup(label);
277 277 if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) {
278 278 QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem());
279 279 shade->setPen(axis()->shadesPen());
280 280 shade->setBrush(axis()->shadesBrush());
281 281 shadeGroup()->addToGroup(shade);
282 282 }
283 283 }
284 284 }
285 285
286 286 void PolarChartAxisAngular::handleArrowPenChanged(const QPen &pen)
287 287 {
288 288 bool first = true;
289 289 foreach (QGraphicsItem *item, arrowItems()) {
290 290 if (first) {
291 291 first = false;
292 292 // First arrow item is the outer circle of axis
293 293 static_cast<QGraphicsEllipseItem *>(item)->setPen(pen);
294 294 } else {
295 295 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
296 296 }
297 297 }
298 298 }
299 299
300 300 void PolarChartAxisAngular::handleGridPenChanged(const QPen &pen)
301 301 {
302 302 foreach (QGraphicsItem *item, gridItems())
303 303 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
304 304 }
305 305
306 306 QSizeF PolarChartAxisAngular::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
307 307 {
308 308 Q_UNUSED(which);
309 309 Q_UNUSED(constraint);
310 310 return QSizeF(-1, -1);
311 311 }
312 312
313 313 qreal PolarChartAxisAngular::preferredAxisRadius(const QSizeF &maxSize)
314 314 {
315 315 qreal radius = maxSize.height() / 2.0;
316 316 if (maxSize.width() < maxSize.height())
317 317 radius = maxSize.width() / 2.0;
318 318
319 int labelHeight = 0;
320
321 319 if (axis()->labelsVisible()) {
322 320 QVector<qreal> layout = calculateLayout();
323 321 if (layout.isEmpty())
324 322 return radius;
325 323
326 324 createAxisLabels(layout);
327 325 QStringList labelList = labels();
328 326 QFont font = axis()->labelsFont();
329 327
330 328 QRectF maxRect;
331 329 maxRect.setSize(maxSize);
332 330 maxRect.moveCenter(QPointF(0.0, 0.0));
333 331
334 332 // This is a horrible way to find out the maximum radius for angular axis and its labels.
335 333 // It just increments the radius down until everyhing fits the constraint size.
336 334 // Proper way would be to actually calculate it but this seems to work reasonably fast as it is.
337 335 QFontMetrics fm(font);
338 336 bool nextTickVisible = false;
339 337 for (int i = 0; i < layout.size(); ) {
340 338 if ((i == layout.size() - 1)
341 339 || layout.at(i + 1) < 0.0
342 340 || layout.at(i + 1) > 360.0) {
343 341 nextTickVisible = false;
344 342 } else {
345 343 nextTickVisible = true;
346 344 }
347 345
348 346 qreal labelCoordinate = layout.at(i);
349 347 qreal labelVisible;
350 348
351 349 if (intervalAxis()) {
352 350 qreal farEdge;
353 351 if (i == (layout.size() - 1))
354 352 farEdge = 360.0;
355 353 else
356 farEdge = qMin(360.0, layout.at(i + 1));
354 farEdge = qMin(qreal(360.0), layout.at(i + 1));
357 355
358 356 // Adjust the labelCoordinate to show it if next tick is visible
359 357 if (nextTickVisible)
360 labelCoordinate = qMax(0.0, labelCoordinate);
358 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
361 359
362 360 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
363 361 }
364 362
365 363 if (labelCoordinate < 0.0 || labelCoordinate > 360.0)
366 364 labelVisible = false;
367 365 else
368 366 labelVisible = true;
369 367
370 368 if (!labelVisible) {
371 369 i++;
372 370 continue;
373 371 }
374 372
375 373 QRectF boundingRect = labelBoundingRect(fm, labelList.at(i));
376 labelHeight = boundingRect.height();
377 374 QPointF labelPoint = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate).p2();
378 375
379 376 boundingRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect);
380 377 if (boundingRect.isEmpty() || maxRect.intersected(boundingRect) == boundingRect) {
381 378 i++;
382 379 } else {
383 380 radius -= 1.0;
384 381 if (radius < 1.0) // safeguard
385 382 return 1.0;
386 383 }
387 384 }
388 385 }
389 386
390 387 if (!axis()->titleText().isEmpty() && axis()->isTitleVisible()) {
391 388 QFontMetrics titleMetrics(axis()->titleFont());
392 389 int titleHeight = titleMetrics.boundingRect(axis()->titleText()).height();
393 390 radius -= titlePadding() + (titleHeight / 2);
394 391 if (radius < 1.0) // safeguard
395 392 return 1.0;
396 393 }
397 394
398 395 return radius;
399 396 }
400 397
401 398 QRectF PolarChartAxisAngular::moveLabelToPosition(qreal angularCoordinate, QPointF labelPoint, QRectF labelRect) const
402 399 {
403 400 // TODO use fuzzy compare for "==" cases?
404 401 // TODO Adjust the rect position near 0, 90, 180, and 270 angles for smoother animation?
405 402 if (angularCoordinate == 0.0)
406 403 labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0));
407 404 else if (angularCoordinate < 90.0)
408 405 labelRect.moveBottomLeft(labelPoint);
409 406 else if (angularCoordinate == 90.0)
410 407 labelRect.moveCenter(labelPoint + QPointF(labelRect.width() / 2.0 + 2.0, 0)); // +2 so that it does not hit the radial axis
411 408 else if (angularCoordinate < 180.0)
412 409 labelRect.moveTopLeft(labelPoint);
413 410 else if (angularCoordinate == 180.0)
414 411 labelRect.moveCenter(labelPoint + QPointF(0, labelRect.height() / 2.0));
415 412 else if (angularCoordinate < 270.0)
416 413 labelRect.moveTopRight(labelPoint);
417 414 else if (angularCoordinate == 270.0)
418 415 labelRect.moveCenter(labelPoint + QPointF(-labelRect.width() / 2.0 - 2.0, 0)); // -2 so that it does not hit the radial axis
419 416 else if (angularCoordinate < 360.0)
420 417 labelRect.moveBottomRight(labelPoint);
421 418 else
422 419 labelRect.moveCenter(labelPoint + QPointF(0, -labelRect.height() / 2.0));
423 420 return labelRect;
424 421 }
425 422
426 423 #include "moc_polarchartaxisangular_p.cpp"
427 424
428 425 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,301 +1,301
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "polarchartaxisradial_p.h"
22 22 #include "chartpresenter_p.h"
23 23 #include "abstractchartlayout_p.h"
24 24 #include "qabstractaxis_p.h"
25 25 #include "linearrowitem_p.h"
26 26 #include <QFontMetrics>
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 PolarChartAxisRadial::PolarChartAxisRadial(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
31 31 : PolarChartAxis(axis, item, intervalAxis)
32 32 {
33 33 }
34 34
35 35 PolarChartAxisRadial::~PolarChartAxisRadial()
36 36 {
37 37 }
38 38
39 39 void PolarChartAxisRadial::updateGeometry()
40 40 {
41 41 const QVector<qreal> &layout = this->layout();
42 42 if (layout.isEmpty())
43 43 return;
44 44
45 45 createAxisLabels(layout);
46 46 QStringList labelList = labels();
47 47 QPointF center = axisGeometry().center();
48 48 QList<QGraphicsItem *> arrowItemList = arrowItems();
49 49 QList<QGraphicsItem *> gridItemList = gridItems();
50 50 QList<QGraphicsItem *> labelItemList = labelItems();
51 51 QList<QGraphicsItem *> shadeItemList = shadeItems();
52 52 QGraphicsSimpleTextItem* title = titleItem();
53 53 qreal radius = axisGeometry().height() / 2.0;
54 54
55 55 QLineF line(center, center + QPointF(0, -radius));
56 56 QGraphicsLineItem *axisLine = static_cast<QGraphicsLineItem *>(arrowItemList.at(0));
57 57 axisLine->setLine(line);
58 58
59 59 QFontMetrics fn(axis()->labelsFont());
60 60 QRectF previousLabelRect;
61 61 bool firstShade = true;
62 62 bool nextTickVisible = false;
63 63 if (layout.size())
64 64 nextTickVisible = !(layout.at(0) < 0.0 || layout.at(0) > radius);
65 65
66 66 for (int i = 0; i < layout.size(); ++i) {
67 67 qreal radialCoordinate = layout.at(i);
68 68
69 69 QGraphicsEllipseItem *gridItem = static_cast<QGraphicsEllipseItem *>(gridItemList.at(i));
70 70 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrowItemList.at(i + 1));
71 71 QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem *>(labelItemList.at(i));
72 72 QGraphicsPathItem *shadeItem = 0;
73 73 if (i == 0)
74 74 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
75 75 else if (i % 2)
76 76 shadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at((i / 2) + 1));
77 77
78 78 // Ignore ticks outside valid range
79 79 bool currentTickVisible = nextTickVisible;
80 80 if ((i == layout.size() - 1)
81 81 || layout.at(i + 1) < 0.0
82 82 || layout.at(i + 1) > radius) {
83 83 nextTickVisible = false;
84 84 } else {
85 85 nextTickVisible = true;
86 86 }
87 87
88 88 qreal labelCoordinate = radialCoordinate;
89 89 qreal labelVisible = currentTickVisible;
90 90 qreal labelPad = labelPadding() / 2.0;
91 91 if (intervalAxis()) {
92 92 qreal farEdge;
93 93 if (i == (layout.size() - 1))
94 94 farEdge = radius;
95 95 else
96 96 farEdge = qMin(radius, layout.at(i + 1));
97 97
98 98 // Adjust the labelCoordinate to show it if next tick is visible
99 99 if (nextTickVisible)
100 labelCoordinate = qMax(0.0, labelCoordinate);
100 labelCoordinate = qMax(qreal(0.0), labelCoordinate);
101 101
102 102 labelCoordinate = (labelCoordinate + farEdge) / 2.0;
103 103 if (labelCoordinate > 0.0 && labelCoordinate < radius)
104 104 labelVisible = true;
105 105 else
106 106 labelVisible = false;
107 107 }
108 108
109 109 // Radial axis label
110 110 if (axis()->labelsVisible() && labelVisible) {
111 111 labelItem->setText(labelList.at(i));
112 112 QRectF labelRect = labelItem->boundingRect();
113 113 QPointF labelCenter = labelRect.center();
114 114 labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y());
115 115 QRectF boundingRect = labelBoundingRect(fn, labelList.at(i));
116 116 boundingRect.moveCenter(labelCenter);
117 117 QPointF positionDiff(labelRect.topLeft() - boundingRect.topLeft());
118 118 QPointF labelPoint = center;
119 119 if (intervalAxis())
120 120 labelPoint += QPointF(labelPad, -labelCoordinate - (boundingRect.height() / 2.0));
121 121 else
122 122 labelPoint += QPointF(labelPad, labelPad - labelCoordinate);
123 123 labelRect.moveTopLeft(labelPoint);
124 124 labelItem->setPos(labelRect.topLeft() + positionDiff);
125 125
126 126 // Label overlap detection
127 127 labelRect.setSize(boundingRect.size());
128 128 if ((i && previousLabelRect.intersects(labelRect))
129 129 || !axisGeometry().contains(labelRect)) {
130 130 labelVisible = false;
131 131 } else {
132 132 previousLabelRect = labelRect;
133 133 labelVisible = true;
134 134 }
135 135 }
136 136
137 137 labelItem->setVisible(labelVisible);
138 138 if (!currentTickVisible) {
139 139 gridItem->setVisible(false);
140 140 tickItem->setVisible(false);
141 141 if (shadeItem)
142 142 shadeItem->setVisible(false);
143 143 continue;
144 144 }
145 145
146 146 // Radial grid line
147 147 QRectF gridRect;
148 148 gridRect.setWidth(radialCoordinate * 2.0);
149 149 gridRect.setHeight(radialCoordinate * 2.0);
150 150 gridRect.moveCenter(center);
151 151
152 152 gridItem->setRect(gridRect);
153 153 gridItem->setVisible(true);
154 154
155 155 // Tick
156 156 QLineF tickLine(-tickWidth(), 0.0, tickWidth(), 0.0);
157 157 tickLine.translate(center.rx(), gridRect.top());
158 158 tickItem->setLine(tickLine);
159 159 tickItem->setVisible(true);
160 160
161 161 // Shades
162 162 if (i % 2 || (i == 0 && !nextTickVisible)) {
163 163 QPainterPath path;
164 164 if (i == 0) {
165 165 // If first tick is also the last, we need to custom fill the inner circle
166 166 // or it won't get filled.
167 167 QRectF innerCircle(0.0, 0.0, layout.at(0) * 2.0, layout.at(0) * 2.0);
168 168 innerCircle.moveCenter(center);
169 169 path.addEllipse(innerCircle);
170 170 } else {
171 171 QRectF otherGridRect;
172 172 if (!nextTickVisible) { // Last visible tick
173 173 otherGridRect = axisGeometry();
174 174 } else {
175 175 qreal otherGridRectDimension = layout.at(i + 1) * 2.0;
176 176 otherGridRect.setWidth(otherGridRectDimension);
177 177 otherGridRect.setHeight(otherGridRectDimension);
178 178 otherGridRect.moveCenter(center);
179 179 }
180 180 path.addEllipse(gridRect);
181 181 path.addEllipse(otherGridRect);
182 182
183 183 // Add additional shading in first visible shade item if there is a partial tick
184 184 // to be filled at the center (log & category axes)
185 185 if (firstShade) {
186 186 QGraphicsPathItem *specialShadeItem = static_cast<QGraphicsPathItem *>(shadeItemList.at(0));
187 187 if (layout.at(i - 1) > 0.0) {
188 188 QRectF innerCircle(0.0, 0.0, layout.at(i - 1) * 2.0, layout.at(i - 1) * 2.0);
189 189 innerCircle.moveCenter(center);
190 190 QPainterPath specialPath;
191 191 specialPath.addEllipse(innerCircle);
192 192 specialShadeItem->setPath(specialPath);
193 193 specialShadeItem->setVisible(true);
194 194 } else {
195 195 specialShadeItem->setVisible(false);
196 196 }
197 197 }
198 198 }
199 199 shadeItem->setPath(path);
200 200 shadeItem->setVisible(true);
201 201 firstShade = false;
202 202 }
203 203 }
204 204
205 205 // Title, along the 0 axis
206 206 QString titleText = axis()->titleText();
207 207 if (!titleText.isEmpty() && axis()->isTitleVisible()) {
208 208 QFontMetrics titleMetrics(axis()->titleFont());
209 209 if (titleMetrics.boundingRect(titleText).width() > radius) {
210 210 QString string = titleText + "...";
211 211 while (titleMetrics.boundingRect(string).width() > radius && string.length() > 3)
212 212 string.remove(string.length() - 4, 1);
213 213 title->setText(string);
214 214 } else {
215 215 title->setText(titleText);
216 216 }
217 217
218 218 QRectF titleBoundingRect;
219 219 titleBoundingRect = title->boundingRect();
220 220 QPointF titleCenter = titleBoundingRect.center();
221 221 QPointF arrowCenter = axisLine->boundingRect().center();
222 222 QPointF titleCenterDiff = arrowCenter - titleCenter;
223 223 title->setPos(titleCenterDiff.x() - qreal(titlePadding()) - (titleBoundingRect.height() / 2.0), titleCenterDiff.y());
224 224 title->setTransformOriginPoint(titleCenter);
225 225 title->setRotation(270.0);
226 226 }
227 227
228 228 QGraphicsLayoutItem::updateGeometry();
229 229 }
230 230
231 231 Qt::Orientation PolarChartAxisRadial::orientation() const
232 232 {
233 233 return Qt::Vertical;
234 234 }
235 235
236 236 void PolarChartAxisRadial::createItems(int count)
237 237 {
238 238 if (arrowItems().count() == 0) {
239 239 // radial axis center line
240 240 QGraphicsLineItem *arrow = new LineArrowItem(this, presenter()->rootItem());
241 241 arrow->setPen(axis()->linePen());
242 242 arrowGroup()->addToGroup(arrow);
243 243 }
244 244
245 245 for (int i = 0; i < count; ++i) {
246 246 QGraphicsLineItem *arrow = new QGraphicsLineItem(presenter()->rootItem());
247 247 QGraphicsEllipseItem *grid = new QGraphicsEllipseItem(presenter()->rootItem());
248 248 QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem(presenter()->rootItem());
249 249 QGraphicsSimpleTextItem *title = titleItem();
250 250 arrow->setPen(axis()->linePen());
251 251 grid->setPen(axis()->gridLinePen());
252 252 label->setFont(axis()->labelsFont());
253 253 label->setPen(axis()->labelsPen());
254 254 label->setBrush(axis()->labelsBrush());
255 255 label->setRotation(axis()->labelsAngle());
256 256 title->setFont(axis()->titleFont());
257 257 title->setPen(axis()->titlePen());
258 258 title->setBrush(axis()->titleBrush());
259 259 title->setText(axis()->titleText());
260 260 arrowGroup()->addToGroup(arrow);
261 261 gridGroup()->addToGroup(grid);
262 262 labelGroup()->addToGroup(label);
263 263 if (gridItems().size() == 1 || (((gridItems().size() + 1) % 2) && gridItems().size() > 0)) {
264 264 QGraphicsPathItem *shade = new QGraphicsPathItem(presenter()->rootItem());
265 265 shade->setPen(axis()->shadesPen());
266 266 shade->setBrush(axis()->shadesBrush());
267 267 shadeGroup()->addToGroup(shade);
268 268 }
269 269 }
270 270 }
271 271
272 272 void PolarChartAxisRadial::handleArrowPenChanged(const QPen &pen)
273 273 {
274 274 foreach (QGraphicsItem *item, arrowItems())
275 275 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
276 276 }
277 277
278 278 void PolarChartAxisRadial::handleGridPenChanged(const QPen &pen)
279 279 {
280 280 foreach (QGraphicsItem *item, gridItems())
281 281 static_cast<QGraphicsEllipseItem *>(item)->setPen(pen);
282 282 }
283 283
284 284 QSizeF PolarChartAxisRadial::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
285 285 {
286 286 Q_UNUSED(which);
287 287 Q_UNUSED(constraint);
288 288 return QSizeF(-1.0, -1.0);
289 289 }
290 290
291 291 qreal PolarChartAxisRadial::preferredAxisRadius(const QSizeF &maxSize)
292 292 {
293 293 qreal radius = maxSize.height() / 2.0;
294 294 if (maxSize.width() < maxSize.height())
295 295 radius = maxSize.width() / 2.0;
296 296 return radius;
297 297 }
298 298
299 299 #include "moc_polarchartaxisradial_p.cpp"
300 300
301 301 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,86 +1,86
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef CHARTCONFIG_H
31 31 #define CHARTCONFIG_H
32 32
33 33 #include "qchartglobal.h"
34 34
35 35 #ifdef Q_CC_MSVC
36 36 // There is a problem with jom.exe currently. It does not seem to understand QMAKE_EXTRA_TARGETS properly.
37 37 // This is the case at least with shadow builds.
38 38 // http://qt-project.org/wiki/jom
39 39 #undef DEVELOPMENT_BUILD
40 40 #endif
41 41
42 42 #ifndef DEVELOPMENT_BUILD
43 43 const char *buildTime = __TIME__" "__DATE__;
44 44 const char *gitHead = "unknown";
45 45 #else
46 46 #include "qchartversion_p.h"
47 47 #endif
48 48
49 49 QTCOMMERCIALCHART_BEGIN_NAMESPACE
50 50
51 51 class ChartConfig
52 52 {
53 53 private:
54 54 ChartConfig() {
55 55 #if defined(DEVELOPMENT_BUILD) && !defined(QT_NO_DEBUG)
56 56 qDebug() << "buildTime" << buildTime;
57 57 qDebug() << "gitHead" << gitHead;
58 58 #endif
59 59 m_instance = this;
60 60 }
61 61 public:
62 62 static ChartConfig *instance() {
63 63 if (!m_instance) {
64 64 m_instance = new ChartConfig();
65 65 }
66 66 return m_instance;
67 67 }
68 68
69 69 QString compilationTime() {
70 return buildTime;
70 return QString(buildTime);
71 71 }
72 72
73 73 QString compilationHead() {
74 return gitHead;
74 return QString(gitHead);
75 75 }
76 76
77 77 private:
78 78 static ChartConfig *m_instance;
79 79 };
80 80
81 81
82 82 ChartConfig *ChartConfig::m_instance = 0;
83 83
84 84 QTCOMMERCIALCHART_END_NAMESPACE
85 85
86 86 #endif
@@ -1,754 +1,754
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qchart.h"
22 22 #include "qchart_p.h"
23 23 #include "legendscroller_p.h"
24 24 #include "qlegend_p.h"
25 25 #include "chartbackground_p.h"
26 26 #include "qabstractaxis.h"
27 27 #include "abstractchartlayout_p.h"
28 28 #include "charttheme_p.h"
29 29 #include "chartpresenter_p.h"
30 30 #include "chartdataset_p.h"
31 31 #include <QGraphicsScene>
32 32 #include <QGraphicsSceneResizeEvent>
33 33
34 34 QTCOMMERCIALCHART_BEGIN_NAMESPACE
35 35
36 36 /*!
37 37 \enum QChart::ChartTheme
38 38
39 39 This enum describes the theme used by the chart.
40 40
41 41 \value ChartThemeLight The default theme
42 42 \value ChartThemeBlueCerulean
43 43 \value ChartThemeDark
44 44 \value ChartThemeBrownSand
45 45 \value ChartThemeBlueNcs
46 46 \value ChartThemeHighContrast
47 47 \value ChartThemeBlueIcy
48 48 */
49 49
50 50 /*!
51 51 \enum QChart::AnimationOption
52 52
53 53 For enabling/disabling animations. Defaults to NoAnimation.
54 54
55 55 \value NoAnimation
56 56 \value GridAxisAnimations
57 57 \value SeriesAnimations
58 58 \value AllAnimations
59 59 */
60 60
61 61 /*!
62 62 \enum QChart::ChartType
63 63
64 64 This enum describes the chart type.
65 65
66 66 \value ChartTypeUndefined
67 67 \value ChartTypeCartesian
68 68 \value ChartTypePolar
69 69 */
70 70
71 71 /*!
72 72 \class QChart
73 73 \brief QtCommercial chart API.
74 74
75 75 QChart is a QGraphicsWidget that you can show in a QGraphicsScene. It manages the graphical
76 76 representation of different types of series and other chart related objects like legend and
77 77 axes. If you simply want to show a chart in a layout, you can use the
78 78 convenience class QChartView instead of QChart.
79 79 \sa QChartView, QPolarChart
80 80 */
81 81
82 82 /*!
83 83 \property QChart::animationOptions
84 84 The animation \a options for the chart. Animations are enabled/disabled based on this setting.
85 85 */
86 86
87 87 /*!
88 88 \property QChart::backgroundVisible
89 89 Specifies whether the chart background is visible or not.
90 90 \sa setBackgroundBrush(), setBackgroundPen(), plotAreaBackgroundVisible
91 91 */
92 92
93 93 /*!
94 94 \property QChart::dropShadowEnabled
95 95 If set to true, the background drop shadow effect is enabled. If set to false, it is disabled. Note that the drop
96 96 shadow effect depends on theme, which means the setting may be changed if you switch to another theme.
97 97 */
98 98
99 99 /*!
100 100 \property QChart::minimumMargins
101 101 Minimum margins between the plot area (axes) and the edge of the chart widget.
102 102 This property is deprecated; use margins property instead.
103 103
104 104 \sa margins
105 105 */
106 106
107 107 /*!
108 108 \property QChart::margins
109 109 Margins between the plot area (axes) and the edge of the chart widget.
110 110 */
111 111
112 112 /*!
113 113 \property QChart::theme
114 114 Theme is a built-in collection of UI style related settings applied for all visual elements of a chart, like colors,
115 115 pens, brushes, and fonts of series, axes, title, and legend. \l {Chart themes demo} shows an example with a few
116 116 different themes.
117 117 \note Changing the theme will overwrite all customizations previously applied to the series.
118 118 */
119 119
120 120 /*!
121 121 \property QChart::title
122 122 Title is the name (label) of a chart. It is shown as a headline on top of the chart.
123 123 */
124 124
125 125 /*!
126 126 \property QChart::chartType
127 127 Chart type indicates if the chart is a cartesian chart or a polar chart.
128 128 This property is set internally and it is read only.
129 129 \sa QPolarChart
130 130 */
131 131
132 132 /*!
133 133 \property QChart::plotAreaBackgroundVisible
134 134 Specifies whether the chart plot area background is visible or not.
135 135 \note By default the plot area background is not visible and the plot area uses
136 136 the general chart background.
137 137 \sa setPlotAreaBackgroundBrush(), setPlotAreaBackgroundPen(), backgroundVisible
138 138 */
139 139
140 140 /*!
141 141 \internal
142 142 Constructs a chart object of \a type which is a child of a \a parent.
143 143 Parameter \a wFlags is passed to the QGraphicsWidget constructor.
144 144 This constructor is called only by subclasses.
145 145 */
146 146 QChart::QChart(QChart::ChartType type, QGraphicsItem *parent, Qt::WindowFlags wFlags)
147 147 : QGraphicsWidget(parent, wFlags),
148 148 d_ptr(new QChartPrivate(this, type))
149 149 {
150 150 d_ptr->init();
151 151 }
152 152
153 153 /*!
154 154 Constructs a chart object which is a child of a \a parent.
155 155 Parameter \a wFlags is passed to the QGraphicsWidget constructor.
156 156 */
157 157 QChart::QChart(QGraphicsItem *parent, Qt::WindowFlags wFlags)
158 158 : QGraphicsWidget(parent, wFlags),
159 159 d_ptr(new QChartPrivate(this, ChartTypeCartesian))
160 160 {
161 161 d_ptr->init();
162 162 }
163 163
164 164 /*!
165 165 Destroys the chart object and its children, like series and axis objects added to it.
166 166 */
167 167 QChart::~QChart()
168 168 {
169 169 //start by deleting dataset, it will remove all series and axes
170 170 delete d_ptr->m_dataset;
171 171 d_ptr->m_dataset = 0;
172 172 }
173 173
174 174 /*!
175 175 Adds the \a series onto the chart and takes the ownership of it.
176 176
177 177 \note A newly added series is attached to no axes by default, including any axes that were created for the chart
178 178 using createDefaultAxes() before the series was added to the chart. If no axes are attached to
179 179 the newly added series before the chart is shown, the series will get drawn as if it had axes with ranges
180 180 that exactly fit the series to the plot area of the chart. This can be confusing if the same chart also displays other
181 181 series that have properly attached axes, so always make sure you either call createDefaultAxes() after
182 182 a series has been added or explicitly attach axes for the series.
183 183
184 184 \sa removeSeries(), removeAllSeries(), createDefaultAxes(), QAbstractSeries::attachAxis()
185 185 */
186 186 void QChart::addSeries(QAbstractSeries *series)
187 187 {
188 188 Q_ASSERT(series);
189 189 d_ptr->m_dataset->addSeries(series);
190 190 }
191 191
192 192 /*!
193 193 Removes the \a series from the chart.
194 194 The chart releases its ownership of the specified \a series object.
195 195
196 196 \sa addSeries(), removeAllSeries()
197 197 */
198 198 void QChart::removeSeries(QAbstractSeries *series)
199 199 {
200 200 Q_ASSERT(series);
201 201 d_ptr->m_dataset->removeSeries(series);
202 202 }
203 203
204 204 /*!
205 205 Removes and deletes all series objects that have been added to the chart.
206 206
207 207 \sa addSeries(), removeSeries()
208 208 */
209 209 void QChart::removeAllSeries()
210 210 {
211 211 foreach (QAbstractSeries *s , d_ptr->m_dataset->series()){
212 212 removeSeries(s);
213 213 delete s;
214 214 }
215 215 }
216 216
217 217 /*!
218 218 Sets the \a brush that is used for painting the background of the chart area.
219 219 */
220 220 void QChart::setBackgroundBrush(const QBrush &brush)
221 221 {
222 222 d_ptr->m_presenter->setBackgroundBrush(brush);
223 223 }
224 224
225 225 /*!
226 226 Gets the brush that is used for painting the background of the chart area.
227 227 */
228 228 QBrush QChart::backgroundBrush() const
229 229 {
230 230 return d_ptr->m_presenter->backgroundBrush();
231 231 }
232 232
233 233 /*!
234 234 Sets the \a pen that is used for painting the background of the chart area.
235 235 */
236 236 void QChart::setBackgroundPen(const QPen &pen)
237 237 {
238 238 d_ptr->m_presenter->setBackgroundPen(pen);
239 239 }
240 240
241 241 /*!
242 242 Gets the pen that is used for painting the background of the chart area.
243 243 */
244 244 QPen QChart::backgroundPen() const
245 245 {
246 246 return d_ptr->m_presenter->backgroundPen();
247 247 }
248 248
249 249 void QChart::setTitle(const QString &title)
250 250 {
251 251 d_ptr->m_presenter->setTitle(title);
252 252 }
253 253
254 254 QString QChart::title() const
255 255 {
256 256 return d_ptr->m_presenter->title();
257 257 }
258 258
259 259 /*!
260 260 Sets the \a font that is used for drawing the chart title.
261 261 */
262 262 void QChart::setTitleFont(const QFont &font)
263 263 {
264 264 d_ptr->m_presenter->setTitleFont(font);
265 265 }
266 266
267 267 /*!
268 268 Gets the font that is used for drawing the chart title.
269 269 */
270 270 QFont QChart::titleFont() const
271 271 {
272 272 return d_ptr->m_presenter->titleFont();
273 273 }
274 274
275 275 /*!
276 276 Sets the \a brush used for drawing the title text.
277 277 */
278 278 void QChart::setTitleBrush(const QBrush &brush)
279 279 {
280 280 d_ptr->m_presenter->setTitleBrush(brush);
281 281 }
282 282
283 283 /*!
284 284 Returns the brush used for drawing the title text.
285 285 */
286 286 QBrush QChart::titleBrush() const
287 287 {
288 288 return d_ptr->m_presenter->titleBrush();
289 289 }
290 290
291 291 void QChart::setTheme(QChart::ChartTheme theme)
292 292 {
293 293 d_ptr->m_themeManager->setTheme(theme);
294 294 }
295 295
296 296 QChart::ChartTheme QChart::theme() const
297 297 {
298 298 return d_ptr->m_themeManager->theme()->id();
299 299 }
300 300
301 301 /*!
302 302 Zooms in the view by a factor of two.
303 303 */
304 304 void QChart::zoomIn()
305 305 {
306 306 d_ptr->zoomIn(2.0);
307 307 }
308 308
309 309 /*!
310 310 Zooms in the view to a maximum level at which \a rect is still fully visible.
311 311 \note This is not supported for polar charts.
312 312 */
313 313 void QChart::zoomIn(const QRectF &rect)
314 314 {
315 315 if (d_ptr->m_type == QChart::ChartTypePolar)
316 316 return;
317 317 d_ptr->zoomIn(rect);
318 318 }
319 319
320 320 /*!
321 321 Zooms out the view by a factor of two.
322 322 */
323 323 void QChart::zoomOut()
324 324 {
325 325 d_ptr->zoomOut(2.0);
326 326 }
327 327
328 328 /*!
329 329 Zooms in the view by a custom \a factor.
330 330
331 331 A factor over 1.0 zooms the view in and factor between 0.0 and 1.0 zooms out.
332 332 */
333 333 void QChart::zoom(qreal factor)
334 334 {
335 335 if (qFuzzyCompare(factor, 0))
336 336 return;
337 337
338 338 if (qFuzzyCompare(factor, (qreal)1.0))
339 339 return;
340 340
341 341 if (factor < 0)
342 342 return;
343 343
344 344 if (factor > 1.0)
345 345 d_ptr->zoomIn(factor);
346 346 else
347 347 d_ptr->zoomOut(1.0 / factor);
348 348 }
349 349
350 350 /*!
351 351 Returns a pointer to the horizontal axis attached to the specified \a series.
352 352 If no \a series is specified, the first horizontal axis added to the chart is returned.
353 353
354 354 \sa addAxis(), QAbstractSeries::attachAxis()
355 355 */
356 356 QAbstractAxis *QChart::axisX(QAbstractSeries *series) const
357 357 {
358 358 QList<QAbstractAxis *> axisList = axes(Qt::Horizontal, series);
359 359 if (axisList.count())
360 360 return axisList[0];
361 361 return 0;
362 362 }
363 363
364 364 /*!
365 365 Returns a pointer to the vertical axis attached to the specified \a series.
366 366 If no \a series is specified, the first vertical axis added to the chart is returned.
367 367
368 368 \sa addAxis(), QAbstractSeries::attachAxis()
369 369 */
370 370 QAbstractAxis *QChart::axisY(QAbstractSeries *series) const
371 371 {
372 372 QList<QAbstractAxis *> axisList = axes(Qt::Vertical, series);
373 373 if (axisList.count())
374 374 return axisList[0];
375 375 return 0;
376 376 }
377 377
378 378 /*!
379 379 Returns the axes attached to the \a series with \a orientation. If no \a series is provided,
380 380 then all axes added to the chart with the specified orientation are returned.
381 381 \sa addAxis(), createDefaultAxes()
382 382 */
383 383 QList<QAbstractAxis *> QChart::axes(Qt::Orientations orientation, QAbstractSeries *series) const
384 384 {
385 385 QList<QAbstractAxis *> result ;
386 386
387 387 if (series) {
388 388 foreach (QAbstractAxis *axis, series->attachedAxes()){
389 389 if (orientation.testFlag(axis->orientation()))
390 390 result << axis;
391 391 }
392 392 } else {
393 393 foreach (QAbstractAxis *axis, d_ptr->m_dataset->axes()){
394 394 if (orientation.testFlag(axis->orientation()) && !result.contains(axis))
395 395 result << axis;
396 396 }
397 397 }
398 398
399 399 return result;
400 400 }
401 401
402 402 /*!
403 403 Creates axes for the chart based on the series that have already been added to the chart. Any axes previously added to
404 404 the chart will be deleted.
405 405
406 406 \note This function has to be called after all series have been added to the chart. The axes created by this function
407 407 will NOT get automatically attached to any series added to the chart after this function has been called.
408 408 A series with no axes attached will by default scale to utilize the entire plot area of the chart, which can be confusing
409 409 if there are other series with properly attached axes also present.
410 410
411 411 \table
412 412 \header
413 413 \o Series type
414 414 \o X-axis
415 415 \o Y-axis
416 416 \row
417 417 \o QXYSeries
418 418 \o QValueAxis
419 419 \o QValueAxis
420 420 \row
421 421 \o QBarSeries
422 422 \o QBarCategoryAxis
423 423 \o QValueAxis
424 424 \row
425 425 \o QPieSeries
426 426 \o None
427 427 \o None
428 428 \endtable
429 429
430 430 If there are several QXYSeries derived series added to the chart and no series of other types have been added, then only one pair of axes is created.
431 431 If there are several series of different types added to the chart, then each series gets its own axes pair.
432 432
433 433 The axes specific to the series can be later obtained from the chart by providing the series as the parameter for axes() function call.
434 434 QPieSeries does not create any axes.
435 435
436 436 \sa axisX(), axisY(), axes(), setAxisX(), setAxisY(), QAbstractSeries::attachAxis()
437 437 */
438 438 void QChart::createDefaultAxes()
439 439 {
440 440 d_ptr->m_dataset->createDefaultAxes();
441 441 }
442 442
443 443 /*!
444 444 Returns the legend object of the chart. Ownership stays with the chart.
445 445 */
446 446 QLegend *QChart::legend() const
447 447 {
448 448 return d_ptr->m_legend;
449 449 }
450 450
451 451 void QChart::setMinimumMargins(const QMargins &margins)
452 452 {
453 453 qWarning() << "QChart::setMinimumMargins is deprecated. Use QChart::setMargins instead.";
454 454 d_ptr->m_presenter->layout()->setMargins(margins);
455 455 }
456 456
457 457 QMargins QChart::minimumMargins() const
458 458 {
459 459 qWarning() << "QChart::minimumMargins is deprecated. Use QChart::margins instead.";
460 460 return d_ptr->m_presenter->layout()->margins();
461 461 }
462 462
463 463 void QChart::setMargins(const QMargins &margins)
464 464 {
465 465 d_ptr->m_presenter->layout()->setMargins(margins);
466 466 }
467 467
468 468 QMargins QChart::margins() const
469 469 {
470 470 return d_ptr->m_presenter->layout()->margins();
471 471 }
472 472
473 473 QChart::ChartType QChart::chartType() const
474 474 {
475 475 return d_ptr->m_type;
476 476 }
477 477
478 478 /*!
479 479 Returns the the rectangle within which the drawing of the chart is done.
480 480 It does not include the area defined by margins.
481 481 */
482 482 QRectF QChart::plotArea() const
483 483 {
484 484 return d_ptr->m_presenter->geometry();
485 485 }
486 486
487 487 /*!
488 488 Sets the \a brush for the background of the plot area of the chart.
489 489
490 490 \sa plotArea(), plotAreaBackgroundVisible, setPlotAreaBackgroundPen(), plotAreaBackgroundBrush()
491 491 */
492 492 void QChart::setPlotAreaBackgroundBrush(const QBrush &brush)
493 493 {
494 494 d_ptr->m_presenter->setPlotAreaBackgroundBrush(brush);
495 495 }
496 496
497 497 /*!
498 498 Returns the brush for the background of the plot area of the chart.
499 499
500 500 \sa plotArea(), plotAreaBackgroundVisible, plotAreaBackgroundPen(), setPlotAreaBackgroundBrush()
501 501 */
502 502 QBrush QChart::plotAreaBackgroundBrush() const
503 503 {
504 504 return d_ptr->m_presenter->plotAreaBackgroundBrush();
505 505 }
506 506
507 507 /*!
508 508 Sets the \a pen for the background of the plot area of the chart.
509 509
510 510 \sa plotArea(), plotAreaBackgroundVisible, setPlotAreaBackgroundBrush(), plotAreaBackgroundPen()
511 511 */
512 512 void QChart::setPlotAreaBackgroundPen(const QPen &pen)
513 513 {
514 514 d_ptr->m_presenter->setPlotAreaBackgroundPen(pen);
515 515 }
516 516
517 517 /*!
518 518 Returns the pen for the background of the plot area of the chart.
519 519
520 520 \sa plotArea(), plotAreaBackgroundVisible, plotAreaBackgroundBrush(), setPlotAreaBackgroundPen()
521 521 */
522 522 QPen QChart::plotAreaBackgroundPen() const
523 523 {
524 524 return d_ptr->m_presenter->plotAreaBackgroundPen();
525 525 }
526 526
527 527 void QChart::setPlotAreaBackgroundVisible(bool visible)
528 528 {
529 529 d_ptr->m_presenter->setPlotAreaBackgroundVisible(visible);
530 530 }
531 531
532 532 bool QChart::isPlotAreaBackgroundVisible() const
533 533 {
534 534 return d_ptr->m_presenter->isPlotAreaBackgroundVisible();
535 535 }
536 536
537 537 void QChart::setAnimationOptions(AnimationOptions options)
538 538 {
539 539 d_ptr->m_presenter->setAnimationOptions(options);
540 540 }
541 541
542 542 QChart::AnimationOptions QChart::animationOptions() const
543 543 {
544 544 return d_ptr->m_presenter->animationOptions();
545 545 }
546 546
547 547 /*!
548 548 Scrolls the visible area of the chart by the distance defined in the \a dx and \a dy.
549 549
550 550 For polar charts, \a dx indicates the angle along angular axis instead of distance.
551 551 */
552 552 void QChart::scroll(qreal dx, qreal dy)
553 553 {
554 554 d_ptr->scroll(dx,dy);
555 555 }
556 556
557 557 void QChart::setBackgroundVisible(bool visible)
558 558 {
559 559 d_ptr->m_presenter->setBackgroundVisible(visible);
560 560 }
561 561
562 562 bool QChart::isBackgroundVisible() const
563 563 {
564 564 return d_ptr->m_presenter->isBackgroundVisible();
565 565 }
566 566
567 567 void QChart::setDropShadowEnabled(bool enabled)
568 568 {
569 569 d_ptr->m_presenter->setBackgroundDropShadowEnabled(enabled);
570 570 }
571 571
572 572 bool QChart::isDropShadowEnabled() const
573 573 {
574 574 return d_ptr->m_presenter->isBackgroundDropShadowEnabled();
575 575 }
576 576
577 577 /*!
578 578 Returns all series that are added to the chart.
579 579
580 580 \sa addSeries(), removeSeries(), removeAllSeries()
581 581 */
582 582 QList<QAbstractSeries *> QChart::series() const
583 583 {
584 584 return d_ptr->m_dataset->series();
585 585 }
586 586
587 587 /*!
588 588 Adds the \a axis to the chart and attaches it to the \a series as a bottom-aligned horizontal axis.
589 589 The chart takes ownership of both the \a axis and the \a series.
590 590 Any horizontal axes previously attached to the \a series are deleted.
591 591
592 592 \sa axisX(), axisY(), setAxisY(), createDefaultAxes(), QAbstractSeries::attachAxis()
593 593 */
594 594 void QChart::setAxisX(QAbstractAxis *axis ,QAbstractSeries *series)
595 595 {
596 596 QList<QAbstractAxis*> list = axes(Qt::Horizontal, series);
597 597
598 598 foreach (QAbstractAxis* a, list) {
599 599 d_ptr->m_dataset->removeAxis(a);
600 600 delete a;
601 601 }
602 602
603 603 if (!d_ptr->m_dataset->axes().contains(axis))
604 604 d_ptr->m_dataset->addAxis(axis, Qt::AlignBottom);
605 605 d_ptr->m_dataset->attachAxis(series, axis);
606 606 }
607 607
608 608 /*!
609 609 Adds the \a axis to the chart and attaches it to the \a series as a left-aligned vertical axis.
610 610 The chart takes ownership of both the \a axis and the \a series.
611 611 Any vertical axes previously attached to the \a series are deleted.
612 612
613 613 \sa axisX(), axisY(), setAxisX(), createDefaultAxes(), QAbstractSeries::attachAxis()
614 614 */
615 615 void QChart::setAxisY(QAbstractAxis *axis ,QAbstractSeries *series)
616 616 {
617 617 QList<QAbstractAxis*> list = axes(Qt::Vertical, series);
618 618
619 619 foreach (QAbstractAxis* a, list) {
620 620 d_ptr->m_dataset->removeAxis(a);
621 621 delete a;
622 622 }
623 623
624 624 if (!d_ptr->m_dataset->axes().contains(axis))
625 625 d_ptr->m_dataset->addAxis(axis, Qt::AlignLeft);
626 626 d_ptr->m_dataset->attachAxis(series, axis);
627 627 }
628 628
629 629 /*!
630 630 Adds the \a axis to the chart with \a alignment. The chart takes the ownership of the axis.
631 631
632 632 \sa removeAxis(), createDefaultAxes(), QAbstractSeries::attachAxis()
633 633 */
634 634 void QChart::addAxis(QAbstractAxis *axis, Qt::Alignment alignment)
635 635 {
636 636 d_ptr->m_dataset->addAxis(axis, alignment);
637 637 }
638 638
639 639 /*!
640 640 Removes the \a axis from the chart.
641 641 The chart releases its ownership of the specified \a axis object.
642 642
643 643 \sa addAxis(), createDefaultAxes(), QAbstractSeries::detachAxis()
644 644 */
645 645 void QChart::removeAxis(QAbstractAxis *axis)
646 646 {
647 647 d_ptr->m_dataset->removeAxis(axis);
648 648 }
649 649
650 650 /*!
651 651 Returns the value in the \a series domain that corresponds to the \a position relative to chart widget.
652 652 */
653 653 QPointF QChart::mapToValue(const QPointF &position, QAbstractSeries *series)
654 654 {
655 655 return d_ptr->m_dataset->mapToValue(position, series);
656 656 }
657 657
658 658 /*!
659 659 Returns the position on the chart widget that corresponds to the \a value in the \a series domain.
660 660 */
661 661 QPointF QChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
662 662 {
663 663 return d_ptr->m_dataset->mapToPosition(value, series);
664 664 }
665 665
666 666 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
667 667
668 668 QChartPrivate::QChartPrivate(QChart *q, QChart::ChartType type):
669 669 q_ptr(q),
670 m_type(type),
671 670 m_legend(0),
672 671 m_dataset(new ChartDataSet(q)),
673 672 m_presenter(new ChartPresenter(q, type)),
674 m_themeManager(new ChartThemeManager(q))
673 m_themeManager(new ChartThemeManager(q)),
674 m_type(type)
675 675 {
676 676 QObject::connect(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), m_presenter, SLOT(handleSeriesAdded(QAbstractSeries*)));
677 677 QObject::connect(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), m_presenter, SLOT(handleSeriesRemoved(QAbstractSeries*)));
678 678 QObject::connect(m_dataset, SIGNAL(axisAdded(QAbstractAxis*)), m_presenter, SLOT(handleAxisAdded(QAbstractAxis*)));
679 679 QObject::connect(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*)), m_presenter, SLOT(handleAxisRemoved(QAbstractAxis*)));
680 680 QObject::connect(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), m_themeManager, SLOT(handleSeriesAdded(QAbstractSeries*)));
681 681 QObject::connect(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), m_themeManager, SLOT(handleSeriesRemoved(QAbstractSeries*)));
682 682 QObject::connect(m_dataset, SIGNAL(axisAdded(QAbstractAxis*)), m_themeManager, SLOT(handleAxisAdded(QAbstractAxis*)));
683 683 QObject::connect(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*)), m_themeManager, SLOT(handleAxisRemoved(QAbstractAxis*)));
684 684 }
685 685
686 686 QChartPrivate::~QChartPrivate()
687 687 {
688 688 }
689 689
690 690 void QChartPrivate::init()
691 691 {
692 692 m_legend = new LegendScroller(q_ptr);
693 693 q_ptr->setTheme(QChart::ChartThemeLight);
694 694 q_ptr->setLayout(m_presenter->layout());
695 695 }
696 696
697 697 void QChartPrivate::zoomIn(qreal factor)
698 698 {
699 699 QRectF rect = m_presenter->geometry();
700 700 rect.setWidth(rect.width() / factor);
701 701 rect.setHeight(rect.height() / factor);
702 702 rect.moveCenter(m_presenter->geometry().center());
703 703 zoomIn(rect);
704 704 }
705 705
706 706 void QChartPrivate::zoomIn(const QRectF &rect)
707 707 {
708 708 if (!rect.isValid())
709 709 return;
710 710
711 711 QRectF r = rect.normalized();
712 712 const QRectF geometry = m_presenter->geometry();
713 713 r.translate(-geometry.topLeft());
714 714
715 715 if (!r.isValid())
716 716 return;
717 717
718 718 QPointF zoomPoint(r.center().x() / geometry.width(), r.center().y() / geometry.height());
719 719 m_presenter->setState(ChartPresenter::ZoomInState,zoomPoint);
720 720 m_dataset->zoomInDomain(r);
721 721 m_presenter->setState(ChartPresenter::ShowState,QPointF());
722 722
723 723 }
724 724
725 725 void QChartPrivate::zoomOut(qreal factor)
726 726 {
727 727 const QRectF geometry = m_presenter->geometry();
728 728
729 729 QRectF r;
730 730 r.setSize(geometry.size() / factor);
731 731 r.moveCenter(QPointF(geometry.size().width()/2 ,geometry.size().height()/2));
732 732 if (!r.isValid())
733 733 return;
734 734
735 735 QPointF zoomPoint(r.center().x() / geometry.width(), r.center().y() / geometry.height());
736 736 m_presenter->setState(ChartPresenter::ZoomOutState,zoomPoint);
737 737 m_dataset->zoomOutDomain(r);
738 738 m_presenter->setState(ChartPresenter::ShowState,QPointF());
739 739 }
740 740
741 741 void QChartPrivate::scroll(qreal dx, qreal dy)
742 742 {
743 743 if (dx < 0) m_presenter->setState(ChartPresenter::ScrollLeftState,QPointF());
744 744 if (dx > 0) m_presenter->setState(ChartPresenter::ScrollRightState,QPointF());
745 745 if (dy < 0) m_presenter->setState(ChartPresenter::ScrollUpState,QPointF());
746 746 if (dy > 0) m_presenter->setState(ChartPresenter::ScrollDownState,QPointF());
747 747
748 748 m_dataset->scrollDomain(dx, dy);
749 749 m_presenter->setState(ChartPresenter::ShowState,QPointF());
750 750 }
751 751
752 752 #include "moc_qchart.cpp"
753 753
754 754 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,281 +1,282
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qchartview.h"
22 22 #include "qchartview_p.h"
23 23 #include "qchart_p.h"
24 24 #include <QGraphicsScene>
25 25 #include <QRubberBand>
26 #include <qmath.h>
26 27
27 28 /*!
28 29 \enum QChartView::RubberBand
29 30
30 31 This enum describes the different types of rubber bands that can be used for zoom rect selection
31 32
32 33 \value NoRubberBand
33 34 \value VerticalRubberBand
34 35 \value HorizonalRubberBand
35 36 \value RectangleRubberBand
36 37 */
37 38
38 39 /*!
39 40 \class QChartView
40 41 \brief Standalone charting widget.
41 42
42 43 QChartView is a standalone widget that can display charts. It does not require separate
43 44 QGraphicsScene to work. If you want to display a chart in your existing QGraphicsScene,
44 45 you need to use the QChart (or QPolarChart) class instead.
45 46
46 47 \sa QChart, QPolarChart
47 48 */
48 49
49 50 QTCOMMERCIALCHART_BEGIN_NAMESPACE
50 51
51 52 /*!
52 53 Constructs a chartView object with parent \a parent.
53 54 */
54 55
55 56 QChartView::QChartView(QWidget *parent)
56 57 : QGraphicsView(parent),
57 58 d_ptr(new QChartViewPrivate(this))
58 59 {
59 60
60 61 }
61 62
62 63 /*!
63 64 Constructs a chartview object with parent \a parent to display a \a chart.
64 65 Ownership of the \a chart is passed to chartview.
65 66 */
66 67
67 68 QChartView::QChartView(QChart *chart, QWidget *parent)
68 69 : QGraphicsView(parent),
69 70 d_ptr(new QChartViewPrivate(this, chart))
70 71 {
71 72
72 73 }
73 74
74 75
75 76 /*!
76 77 Destroys the chartview object and the associated chart.
77 78 */
78 79 QChartView::~QChartView()
79 80 {
80 81 }
81 82
82 83 /*!
83 84 Returns the pointer to the associated chart.
84 85 */
85 86 QChart *QChartView::chart() const
86 87 {
87 88 return d_ptr->m_chart;
88 89 }
89 90
90 91 /*!
91 92 Sets the current chart to \a chart. Ownership of the new chart is passed to chartview
92 93 and ownership of the previous chart is released.
93 94
94 95 To avoid memory leaks users need to make sure the previous chart is deleted.
95 96 */
96 97
97 98 void QChartView::setChart(QChart *chart)
98 99 {
99 100 d_ptr->setChart(chart);
100 101 }
101 102
102 103 /*!
103 104 Sets the rubber band flags to \a rubberBand.
104 105 Selected flags determine the way zooming is performed.
105 106
106 107 \note Rubber band zooming is not supported for polar charts.
107 108 */
108 109 void QChartView::setRubberBand(const RubberBands &rubberBand)
109 110 {
110 111 d_ptr->m_rubberBandFlags = rubberBand;
111 112
112 113 if (!d_ptr->m_rubberBandFlags) {
113 114 delete d_ptr->m_rubberBand;
114 115 d_ptr->m_rubberBand = 0;
115 116 return;
116 117 }
117 118
118 119 if (!d_ptr->m_rubberBand) {
119 120 d_ptr->m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
120 121 d_ptr->m_rubberBand->setEnabled(true);
121 122 }
122 123 }
123 124
124 125 /*!
125 126 Returns the rubber band flags that are currently being used by the widget.
126 127 */
127 128 QChartView::RubberBands QChartView::rubberBand() const
128 129 {
129 130 return d_ptr->m_rubberBandFlags;
130 131 }
131 132
132 133 /*!
133 134 If Left mouse button is pressed and the rubber band is enabled the \a event is accepted and the rubber band is displayed on the screen allowing the user to select the zoom area.
134 135 If different mouse button is pressed and/or the rubber band is disabled then the \a event is passed to QGraphicsView::mousePressEvent() implementation.
135 136 */
136 137 void QChartView::mousePressEvent(QMouseEvent *event)
137 138 {
138 139 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isEnabled() && event->button() == Qt::LeftButton) {
139 140
140 141 QRectF plotArea = d_ptr->m_chart->plotArea();
141 142
142 143 if (plotArea.contains(event->pos())) {
143 144 d_ptr->m_rubberBandOrigin = event->pos();
144 145 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin, QSize()));
145 146 d_ptr->m_rubberBand->show();
146 147 event->accept();
147 148 }
148 149 } else {
149 150 QGraphicsView::mousePressEvent(event);
150 151 }
151 152 }
152 153
153 154 /*!
154 155 If the rubber band rectange has been displayed in pressEvent then \a event data is used to update the rubber band geometry.
155 156 Otherwise the default QGraphicsView::mouseMoveEvent implementation is called.
156 157 */
157 158 void QChartView::mouseMoveEvent(QMouseEvent *event)
158 159 {
159 160 if (d_ptr->m_rubberBand && d_ptr->m_rubberBand->isVisible()) {
160 161 QRect rect = d_ptr->m_chart->plotArea().toRect();
161 162 int width = event->pos().x() - d_ptr->m_rubberBandOrigin.x();
162 163 int height = event->pos().y() - d_ptr->m_rubberBandOrigin.y();
163 164 if (!d_ptr->m_rubberBandFlags.testFlag(VerticalRubberBand)) {
164 165 d_ptr->m_rubberBandOrigin.setY(rect.top());
165 166 height = rect.height();
166 167 }
167 168 if (!d_ptr->m_rubberBandFlags.testFlag(HorizonalRubberBand)) {
168 169 d_ptr->m_rubberBandOrigin.setX(rect.left());
169 170 width = rect.width();
170 171 }
171 172 d_ptr->m_rubberBand->setGeometry(QRect(d_ptr->m_rubberBandOrigin.x(), d_ptr->m_rubberBandOrigin.y(), width, height).normalized());
172 173 } else {
173 174 QGraphicsView::mouseMoveEvent(event);
174 175 }
175 176 }
176 177
177 178 /*!
178 179 If left mouse button is released and the rubber band is enabled then \a event is accepted and
179 180 the view is zoomed into the rect specified by the rubber band.
180 181 If it is a right mouse button \a event then the rubber band is dismissed and the zoom is canceled.
181 182 */
182 183 void QChartView::mouseReleaseEvent(QMouseEvent *event)
183 184 {
184 185 if (d_ptr->m_rubberBand) {
185 186 if (event->button() == Qt::LeftButton && d_ptr->m_rubberBand->isVisible()) {
186 187 d_ptr->m_rubberBand->hide();
187 188 QRectF rect = d_ptr->m_rubberBand->geometry();
188 189 // Since plotArea uses QRectF and rubberband uses QRect, we can't just blindly use
189 190 // rubberband's dimensions for vertical and horizontal rubberbands, where one
190 191 // dimension must match the corresponding plotArea dimension exactly.
191 192 if (d_ptr->m_rubberBandFlags == VerticalRubberBand) {
192 193 rect.setX(d_ptr->m_chart->plotArea().x());
193 194 rect.setWidth(d_ptr->m_chart->plotArea().width());
194 195 } else if (d_ptr->m_rubberBandFlags == HorizonalRubberBand) {
195 196 rect.setY(d_ptr->m_chart->plotArea().y());
196 197 rect.setHeight(d_ptr->m_chart->plotArea().height());
197 198 }
198 199 d_ptr->m_chart->zoomIn(rect);
199 200 event->accept();
200 201 }
201 202
202 203 if (event->button() == Qt::RightButton) {
203 204 d_ptr->m_chart->zoomOut();
204 205 event->accept();
205 206 }
206 207 } else {
207 208 QGraphicsView::mouseReleaseEvent(event);
208 209 }
209 210 }
210 211
211 212 /*!
212 213 Resizes and updates the chart area using the \a event data
213 214 */
214 215 void QChartView::resizeEvent(QResizeEvent *event)
215 216 {
216 217 QGraphicsView::resizeEvent(event);
217 218 d_ptr->resize();
218 219 }
219 220
220 221 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
221 222
222 223 QChartViewPrivate::QChartViewPrivate(QChartView *q, QChart *chart)
223 224 : q_ptr(q),
224 225 m_scene(new QGraphicsScene(q)),
225 226 m_chart(chart),
226 227 m_rubberBand(0),
227 228 m_rubberBandFlags(QChartView::NoRubberBand)
228 229 {
229 230 q_ptr->setFrameShape(QFrame::NoFrame);
230 231 q_ptr->setBackgroundRole(QPalette::Window);
231 232 q_ptr->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
232 233 q_ptr->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
233 234 q_ptr->setScene(m_scene);
234 235 q_ptr->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
235 236 if (!m_chart)
236 237 m_chart = new QChart();
237 238 m_scene->addItem(m_chart);
238 239 }
239 240
240 241 QChartViewPrivate::~QChartViewPrivate()
241 242 {
242 243 }
243 244
244 245 void QChartViewPrivate::setChart(QChart *chart)
245 246 {
246 247 Q_ASSERT(chart);
247 248
248 249 if (m_chart == chart)
249 250 return;
250 251
251 252 if (m_chart)
252 253 m_scene->removeItem(m_chart);
253 254
254 255 m_chart = chart;
255 256 m_scene->addItem(m_chart);
256 257
257 258 resize();
258 259 }
259 260
260 261 const qreal rad2deg(57.2957795);
261 262
262 263 void QChartViewPrivate::resize()
263 264 {
264 265 // Flip chart width and height if the view has been rotated
265 266 // more than 45 degrees from the horizontal so it fits better into the view.
266 qreal angle = acos(q_ptr->transform().m11()) * rad2deg;
267 qreal angle = qAcos(q_ptr->transform().m11()) * rad2deg;
267 268 QSize chartSize = q_ptr->size();
268 269
269 270 if (angle > 45.0 && angle < 135.0) {
270 271 chartSize.setHeight(q_ptr->size().width());
271 272 chartSize.setWidth(q_ptr->size().height());
272 273 }
273 274
274 275 m_chart->resize(chartSize);
275 276 q_ptr->setMinimumSize(m_chart->minimumSize().toSize());
276 277 q_ptr->setSceneRect(m_chart->geometry());
277 278 }
278 279
279 280 #include "moc_qchartview.cpp"
280 281
281 282 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now