##// END OF EJS Templates
Fix mouse event handling for pie...
Titta Heikkala -
r2674:e4b34f179cba
parent child
Show More
@@ -1,320 +1,319
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 "piesliceitem_p.h"
21 #include "piesliceitem_p.h"
22 #include "piechartitem_p.h"
22 #include "piechartitem_p.h"
23 #include "qpieseries.h"
23 #include "qpieseries.h"
24 #include "qpieslice.h"
24 #include "qpieslice.h"
25 #include "chartpresenter_p.h"
25 #include "chartpresenter_p.h"
26 #include <QPainter>
26 #include <QPainter>
27 #include <qmath.h>
27 #include <qmath.h>
28 #include <QGraphicsSceneEvent>
28 #include <QGraphicsSceneEvent>
29 #include <QTime>
29 #include <QTime>
30 #include <QTextDocument>
30 #include <QTextDocument>
31 #include <QDebug>
31 #include <QDebug>
32
32
33 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 QTCOMMERCIALCHART_BEGIN_NAMESPACE
34
34
35 QPointF offset(qreal angle, qreal length)
35 QPointF offset(qreal angle, qreal length)
36 {
36 {
37 qreal dx = qSin(angle * (M_PI / 180)) * length;
37 qreal dx = qSin(angle * (M_PI / 180)) * length;
38 qreal dy = qCos(angle * (M_PI / 180)) * length;
38 qreal dy = qCos(angle * (M_PI / 180)) * length;
39 return QPointF(dx, -dy);
39 return QPointF(dx, -dy);
40 }
40 }
41
41
42 PieSliceItem::PieSliceItem(QGraphicsItem *parent)
42 PieSliceItem::PieSliceItem(QGraphicsItem *parent)
43 : QGraphicsObject(parent),
43 : QGraphicsObject(parent),
44 m_hovered(false)
44 m_hovered(false)
45 {
45 {
46 setAcceptHoverEvents(true);
46 setAcceptHoverEvents(true);
47 setAcceptedMouseButtons(Qt::MouseButtonMask);
47 setAcceptedMouseButtons(Qt::MouseButtonMask);
48 setZValue(ChartPresenter::PieSeriesZValue);
48 setZValue(ChartPresenter::PieSeriesZValue);
49 m_labelItem = new QGraphicsTextItem(this);
49 m_labelItem = new QGraphicsTextItem(this);
50 m_labelItem->document()->setDocumentMargin(1.0);
50 m_labelItem->document()->setDocumentMargin(1.0);
51 }
51 }
52
52
53 PieSliceItem::~PieSliceItem()
53 PieSliceItem::~PieSliceItem()
54 {
54 {
55 // If user is hovering over the slice and it gets destroyed we do
55 // If user is hovering over the slice and it gets destroyed we do
56 // not get a hover leave event. So we must emit the signal here.
56 // not get a hover leave event. So we must emit the signal here.
57 if (m_hovered)
57 if (m_hovered)
58 emit hovered(false);
58 emit hovered(false);
59 }
59 }
60
60
61 QRectF PieSliceItem::boundingRect() const
61 QRectF PieSliceItem::boundingRect() const
62 {
62 {
63 return m_boundingRect;
63 return m_boundingRect;
64 }
64 }
65
65
66 QPainterPath PieSliceItem::shape() const
66 QPainterPath PieSliceItem::shape() const
67 {
67 {
68 // Don't include the label and label arm.
68 // Don't include the label and label arm.
69 // This is used to detect a mouse clicks. We do not want clicks from label.
69 // This is used to detect a mouse clicks. We do not want clicks from label.
70 return m_slicePath;
70 return m_slicePath;
71 }
71 }
72
72
73 void PieSliceItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
73 void PieSliceItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
74 {
74 {
75 painter->save();
75 painter->save();
76 painter->setClipRect(parentItem()->boundingRect());
76 painter->setClipRect(parentItem()->boundingRect());
77 painter->setPen(m_data.m_slicePen);
77 painter->setPen(m_data.m_slicePen);
78 painter->setBrush(m_data.m_sliceBrush);
78 painter->setBrush(m_data.m_sliceBrush);
79 painter->drawPath(m_slicePath);
79 painter->drawPath(m_slicePath);
80 painter->restore();
80 painter->restore();
81
81
82 if (m_data.m_isLabelVisible) {
82 if (m_data.m_isLabelVisible) {
83 painter->save();
83 painter->save();
84
84
85 // Pen for label arm not defined in the QPieSeries api, let's use brush's color instead
85 // Pen for label arm not defined in the QPieSeries api, let's use brush's color instead
86 painter->setBrush(m_data.m_labelBrush);
86 painter->setBrush(m_data.m_labelBrush);
87
87
88 if (m_data.m_labelPosition == QPieSlice::LabelOutside) {
88 if (m_data.m_labelPosition == QPieSlice::LabelOutside) {
89 painter->setClipRect(parentItem()->boundingRect());
89 painter->setClipRect(parentItem()->boundingRect());
90 painter->strokePath(m_labelArmPath, m_data.m_labelBrush.color());
90 painter->strokePath(m_labelArmPath, m_data.m_labelBrush.color());
91 }
91 }
92
92
93 painter->restore();
93 painter->restore();
94 }
94 }
95 }
95 }
96
96
97 void PieSliceItem::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/)
97 void PieSliceItem::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/)
98 {
98 {
99 m_hovered = true;
99 m_hovered = true;
100 emit hovered(true);
100 emit hovered(true);
101 }
101 }
102
102
103 void PieSliceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
103 void PieSliceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
104 {
104 {
105 m_hovered = false;
105 m_hovered = false;
106 emit hovered(false);
106 emit hovered(false);
107 }
107 }
108
108
109 void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
109 void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
110 {
110 {
111 emit clicked(event->buttons());
111 emit clicked(event->buttons());
112 QGraphicsItem::mousePressEvent(event);
113 }
112 }
114
113
115 void PieSliceItem::setLayout(const PieSliceData &sliceData)
114 void PieSliceItem::setLayout(const PieSliceData &sliceData)
116 {
115 {
117 m_data = sliceData;
116 m_data = sliceData;
118 updateGeometry();
117 updateGeometry();
119 update();
118 update();
120 }
119 }
121
120
122 void PieSliceItem::updateGeometry()
121 void PieSliceItem::updateGeometry()
123 {
122 {
124 if (m_data.m_radius <= 0)
123 if (m_data.m_radius <= 0)
125 return;
124 return;
126
125
127 prepareGeometryChange();
126 prepareGeometryChange();
128
127
129 // slice path
128 // slice path
130 qreal centerAngle;
129 qreal centerAngle;
131 QPointF armStart;
130 QPointF armStart;
132 m_slicePath = slicePath(m_data.m_center, m_data.m_radius, m_data.m_startAngle, m_data.m_angleSpan, &centerAngle, &armStart);
131 m_slicePath = slicePath(m_data.m_center, m_data.m_radius, m_data.m_startAngle, m_data.m_angleSpan, &centerAngle, &armStart);
133
132
134 m_labelItem->setVisible(m_data.m_isLabelVisible);
133 m_labelItem->setVisible(m_data.m_isLabelVisible);
135
134
136 if (m_data.m_isLabelVisible) {
135 if (m_data.m_isLabelVisible) {
137 // text rect
136 // text rect
138 m_labelTextRect = ChartPresenter::textBoundingRect(m_data.m_labelFont,
137 m_labelTextRect = ChartPresenter::textBoundingRect(m_data.m_labelFont,
139 m_data.m_labelText,
138 m_data.m_labelText,
140 0);
139 0);
141
140
142 QString label(m_data.m_labelText);
141 QString label(m_data.m_labelText);
143 m_labelItem->setDefaultTextColor(m_data.m_labelBrush.color());
142 m_labelItem->setDefaultTextColor(m_data.m_labelBrush.color());
144 m_labelItem->setFont(m_data.m_labelFont);
143 m_labelItem->setFont(m_data.m_labelFont);
145
144
146 // text position
145 // text position
147 if (m_data.m_labelPosition == QPieSlice::LabelOutside) {
146 if (m_data.m_labelPosition == QPieSlice::LabelOutside) {
148 setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
147 setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
149
148
150 // label arm path
149 // label arm path
151 QPointF labelTextStart;
150 QPointF labelTextStart;
152 m_labelArmPath = labelArmPath(armStart, centerAngle,
151 m_labelArmPath = labelArmPath(armStart, centerAngle,
153 m_data.m_radius * m_data.m_labelArmLengthFactor,
152 m_data.m_radius * m_data.m_labelArmLengthFactor,
154 m_labelTextRect.width(), &labelTextStart);
153 m_labelTextRect.width(), &labelTextStart);
155
154
156 m_labelTextRect.moveBottomLeft(labelTextStart);
155 m_labelTextRect.moveBottomLeft(labelTextStart);
157 if (m_labelTextRect.left() < 0)
156 if (m_labelTextRect.left() < 0)
158 m_labelTextRect.setLeft(0);
157 m_labelTextRect.setLeft(0);
159 else if (m_labelTextRect.left() < parentItem()->boundingRect().left())
158 else if (m_labelTextRect.left() < parentItem()->boundingRect().left())
160 m_labelTextRect.setLeft(parentItem()->boundingRect().left());
159 m_labelTextRect.setLeft(parentItem()->boundingRect().left());
161 if (m_labelTextRect.right() > parentItem()->boundingRect().right())
160 if (m_labelTextRect.right() > parentItem()->boundingRect().right())
162 m_labelTextRect.setRight(parentItem()->boundingRect().right());
161 m_labelTextRect.setRight(parentItem()->boundingRect().right());
163
162
164 label = ChartPresenter::truncatedText(m_data.m_labelFont, m_data.m_labelText,
163 label = ChartPresenter::truncatedText(m_data.m_labelFont, m_data.m_labelText,
165 qreal(0.0), m_labelTextRect.width(),
164 qreal(0.0), m_labelTextRect.width(),
166 m_labelTextRect.height(), m_labelTextRect);
165 m_labelTextRect.height(), m_labelTextRect);
167 m_labelArmPath = labelArmPath(armStart, centerAngle,
166 m_labelArmPath = labelArmPath(armStart, centerAngle,
168 m_data.m_radius * m_data.m_labelArmLengthFactor,
167 m_data.m_radius * m_data.m_labelArmLengthFactor,
169 m_labelTextRect.width(), &labelTextStart);
168 m_labelTextRect.width(), &labelTextStart);
170 m_labelTextRect.moveBottomLeft(labelTextStart);
169 m_labelTextRect.moveBottomLeft(labelTextStart);
171
170
172 m_labelItem->setTextWidth(m_labelTextRect.width()
171 m_labelItem->setTextWidth(m_labelTextRect.width()
173 + m_labelItem->document()->documentMargin());
172 + m_labelItem->document()->documentMargin());
174 m_labelItem->setHtml(label);
173 m_labelItem->setHtml(label);
175 m_labelItem->setRotation(0);
174 m_labelItem->setRotation(0);
176 m_labelItem->setPos(m_labelTextRect.x(), m_labelTextRect.y() + 1.0);
175 m_labelItem->setPos(m_labelTextRect.x(), m_labelTextRect.y() + 1.0);
177 } else {
176 } else {
178 // label inside
177 // label inside
179 setFlag(QGraphicsItem::ItemClipsChildrenToShape);
178 setFlag(QGraphicsItem::ItemClipsChildrenToShape);
180 m_labelItem->setTextWidth(m_labelTextRect.width()
179 m_labelItem->setTextWidth(m_labelTextRect.width()
181 + m_labelItem->document()->documentMargin());
180 + m_labelItem->document()->documentMargin());
182 m_labelItem->setHtml(label);
181 m_labelItem->setHtml(label);
183
182
184 QPointF textCenter;
183 QPointF textCenter;
185 if (m_data.m_holeRadius > 0) {
184 if (m_data.m_holeRadius > 0) {
186 textCenter = m_data.m_center + offset(centerAngle, m_data.m_holeRadius
185 textCenter = m_data.m_center + offset(centerAngle, m_data.m_holeRadius
187 + (m_data.m_radius
186 + (m_data.m_radius
188 - m_data.m_holeRadius) / 2);
187 - m_data.m_holeRadius) / 2);
189 } else {
188 } else {
190 textCenter = m_data.m_center + offset(centerAngle, m_data.m_radius / 2);
189 textCenter = m_data.m_center + offset(centerAngle, m_data.m_radius / 2);
191 }
190 }
192 m_labelItem->setPos(textCenter.x() - m_labelItem->boundingRect().width() / 2,
191 m_labelItem->setPos(textCenter.x() - m_labelItem->boundingRect().width() / 2,
193 textCenter.y() - m_labelTextRect.height() / 2);
192 textCenter.y() - m_labelTextRect.height() / 2);
194
193
195 QPointF labelCenter = m_labelItem->boundingRect().center();
194 QPointF labelCenter = m_labelItem->boundingRect().center();
196 m_labelItem->setTransformOriginPoint(labelCenter);
195 m_labelItem->setTransformOriginPoint(labelCenter);
197
196
198 if (m_data.m_labelPosition == QPieSlice::LabelInsideTangential) {
197 if (m_data.m_labelPosition == QPieSlice::LabelInsideTangential) {
199 m_labelItem->setRotation(m_data.m_startAngle + m_data.m_angleSpan / 2);
198 m_labelItem->setRotation(m_data.m_startAngle + m_data.m_angleSpan / 2);
200 } else if (m_data.m_labelPosition == QPieSlice::LabelInsideNormal) {
199 } else if (m_data.m_labelPosition == QPieSlice::LabelInsideNormal) {
201 if (m_data.m_startAngle + m_data.m_angleSpan / 2 < 180)
200 if (m_data.m_startAngle + m_data.m_angleSpan / 2 < 180)
202 m_labelItem->setRotation(m_data.m_startAngle + m_data.m_angleSpan / 2 - 90);
201 m_labelItem->setRotation(m_data.m_startAngle + m_data.m_angleSpan / 2 - 90);
203 else
202 else
204 m_labelItem->setRotation(m_data.m_startAngle + m_data.m_angleSpan / 2 + 90);
203 m_labelItem->setRotation(m_data.m_startAngle + m_data.m_angleSpan / 2 + 90);
205 } else {
204 } else {
206 m_labelItem->setRotation(0);
205 m_labelItem->setRotation(0);
207 }
206 }
208 }
207 }
209 // Hide label if it's outside the bounding rect of parent item
208 // Hide label if it's outside the bounding rect of parent item
210 QRectF labelRect(m_labelItem->boundingRect());
209 QRectF labelRect(m_labelItem->boundingRect());
211 labelRect.moveTopLeft(m_labelItem->pos());
210 labelRect.moveTopLeft(m_labelItem->pos());
212 if ((parentItem()->boundingRect().left()
211 if ((parentItem()->boundingRect().left()
213 < (labelRect.left() + m_labelItem->document()->documentMargin() + 1.0))
212 < (labelRect.left() + m_labelItem->document()->documentMargin() + 1.0))
214 && (parentItem()->boundingRect().right()
213 && (parentItem()->boundingRect().right()
215 > (labelRect.right() - m_labelItem->document()->documentMargin() - 1.0))
214 > (labelRect.right() - m_labelItem->document()->documentMargin() - 1.0))
216 && (parentItem()->boundingRect().top()
215 && (parentItem()->boundingRect().top()
217 < (labelRect.top() + m_labelItem->document()->documentMargin() + 1.0))
216 < (labelRect.top() + m_labelItem->document()->documentMargin() + 1.0))
218 && (parentItem()->boundingRect().bottom()
217 && (parentItem()->boundingRect().bottom()
219 > (labelRect.bottom() - m_labelItem->document()->documentMargin() - 1.0)))
218 > (labelRect.bottom() - m_labelItem->document()->documentMargin() - 1.0)))
220 m_labelItem->show();
219 m_labelItem->show();
221 else
220 else
222 m_labelItem->hide();
221 m_labelItem->hide();
223 }
222 }
224
223
225 // bounding rect
224 // bounding rect
226 if (m_data.m_isLabelVisible)
225 if (m_data.m_isLabelVisible)
227 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
226 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
228 else
227 else
229 m_boundingRect = m_slicePath.boundingRect();
228 m_boundingRect = m_slicePath.boundingRect();
230
229
231 // Inflate bounding rect by 2/3 pen width to make sure it encompasses whole slice also for thick pens
230 // Inflate bounding rect by 2/3 pen width to make sure it encompasses whole slice also for thick pens
232 // and miter joins.
231 // and miter joins.
233 int penWidth = (m_data.m_slicePen.width() * 2) / 3;
232 int penWidth = (m_data.m_slicePen.width() * 2) / 3;
234 m_boundingRect = m_boundingRect.adjusted(-penWidth, -penWidth, penWidth, penWidth);
233 m_boundingRect = m_boundingRect.adjusted(-penWidth, -penWidth, penWidth, penWidth);
235 }
234 }
236
235
237 QPointF PieSliceItem::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
236 QPointF PieSliceItem::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
238 {
237 {
239 if (slice->isExploded()) {
238 if (slice->isExploded()) {
240 qreal centerAngle = slice->startAngle() + (slice->angleSpan() / 2);
239 qreal centerAngle = slice->startAngle() + (slice->angleSpan() / 2);
241 qreal len = radius * slice->explodeDistanceFactor();
240 qreal len = radius * slice->explodeDistanceFactor();
242 point += offset(centerAngle, len);
241 point += offset(centerAngle, len);
243 }
242 }
244 return point;
243 return point;
245 }
244 }
246
245
247 QPainterPath PieSliceItem::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF *armStart)
246 QPainterPath PieSliceItem::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF *armStart)
248 {
247 {
249 // calculate center angle
248 // calculate center angle
250 *centerAngle = startAngle + (angleSpan / 2);
249 *centerAngle = startAngle + (angleSpan / 2);
251
250
252 // calculate slice rectangle
251 // calculate slice rectangle
253 QRectF rect(center.x() - radius, center.y() - radius, radius * 2, radius * 2);
252 QRectF rect(center.x() - radius, center.y() - radius, radius * 2, radius * 2);
254
253
255 // slice path
254 // slice path
256 QPainterPath path;
255 QPainterPath path;
257 if (m_data.m_holeRadius > 0) {
256 if (m_data.m_holeRadius > 0) {
258 QRectF insideRect(center.x() - m_data.m_holeRadius, center.y() - m_data.m_holeRadius, m_data.m_holeRadius * 2, m_data.m_holeRadius * 2);
257 QRectF insideRect(center.x() - m_data.m_holeRadius, center.y() - m_data.m_holeRadius, m_data.m_holeRadius * 2, m_data.m_holeRadius * 2);
259 path.arcMoveTo(rect, -startAngle + 90);
258 path.arcMoveTo(rect, -startAngle + 90);
260 path.arcTo(rect, -startAngle + 90, -angleSpan);
259 path.arcTo(rect, -startAngle + 90, -angleSpan);
261 path.arcTo(insideRect, -startAngle + 90 - angleSpan, angleSpan);
260 path.arcTo(insideRect, -startAngle + 90 - angleSpan, angleSpan);
262 path.closeSubpath();
261 path.closeSubpath();
263 } else {
262 } else {
264 path.moveTo(rect.center());
263 path.moveTo(rect.center());
265 path.arcTo(rect, -startAngle + 90, -angleSpan);
264 path.arcTo(rect, -startAngle + 90, -angleSpan);
266 path.closeSubpath();
265 path.closeSubpath();
267 }
266 }
268
267
269 // calculate label arm start point
268 // calculate label arm start point
270 *armStart = center;
269 *armStart = center;
271 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
270 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
272
271
273 return path;
272 return path;
274 }
273 }
275
274
276 QPainterPath PieSliceItem::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart)
275 QPainterPath PieSliceItem::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart)
277 {
276 {
278 // Normalize the angle to 0-360 range
277 // Normalize the angle to 0-360 range
279 // NOTE: We are using int here on purpose. Depenging on platform and hardware
278 // NOTE: We are using int here on purpose. Depenging on platform and hardware
280 // qreal can be a double, float or something the user gives to the Qt configure
279 // qreal can be a double, float or something the user gives to the Qt configure
281 // (QT_COORD_TYPE). Compilers do not seem to support modulo for double or float
280 // (QT_COORD_TYPE). Compilers do not seem to support modulo for double or float
282 // but there are fmod() and fmodf() functions for that. So instead of some #ifdef
281 // but there are fmod() and fmodf() functions for that. So instead of some #ifdef
283 // that might break we just use int. Precision for this is just fine for our needs.
282 // that might break we just use int. Precision for this is just fine for our needs.
284 int normalized = angle * 10.0;
283 int normalized = angle * 10.0;
285 normalized = normalized % 3600;
284 normalized = normalized % 3600;
286 if (normalized < 0)
285 if (normalized < 0)
287 normalized += 3600;
286 normalized += 3600;
288 angle = (qreal) normalized / 10.0;
287 angle = (qreal) normalized / 10.0;
289
288
290 // prevent label arm pointing straight down because it will look bad
289 // prevent label arm pointing straight down because it will look bad
291 if (angle < 180 && angle > 170)
290 if (angle < 180 && angle > 170)
292 angle = 170;
291 angle = 170;
293 if (angle > 180 && angle < 190)
292 if (angle > 180 && angle < 190)
294 angle = 190;
293 angle = 190;
295
294
296 // line from slice to label
295 // line from slice to label
297 QPointF parm1 = start + offset(angle, length);
296 QPointF parm1 = start + offset(angle, length);
298
297
299 // line to underline the label
298 // line to underline the label
300 QPointF parm2 = parm1;
299 QPointF parm2 = parm1;
301 if (angle < 180) { // arm swings the other way on the left side
300 if (angle < 180) { // arm swings the other way on the left side
302 parm2 += QPointF(textWidth, 0);
301 parm2 += QPointF(textWidth, 0);
303 *textStart = parm1;
302 *textStart = parm1;
304 } else {
303 } else {
305 parm2 += QPointF(-textWidth, 0);
304 parm2 += QPointF(-textWidth, 0);
306 *textStart = parm2;
305 *textStart = parm2;
307 }
306 }
308
307
309 QPainterPath path;
308 QPainterPath path;
310 path.moveTo(start);
309 path.moveTo(start);
311 path.lineTo(parm1);
310 path.lineTo(parm1);
312 path.lineTo(parm2);
311 path.lineTo(parm2);
313
312
314 return path;
313 return path;
315 }
314 }
316
315
317 #include "moc_piesliceitem_p.cpp"
316 #include "moc_piesliceitem_p.cpp"
318
317
319 QTCOMMERCIALCHART_END_NAMESPACE
318 QTCOMMERCIALCHART_END_NAMESPACE
320
319
@@ -1,942 +1,944
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 "qpieseries.h"
21 #include "qpieseries.h"
22 #include "qpieseries_p.h"
22 #include "qpieseries_p.h"
23 #include "qpieslice.h"
23 #include "qpieslice.h"
24 #include "qpieslice_p.h"
24 #include "qpieslice_p.h"
25 #include "pieslicedata_p.h"
25 #include "pieslicedata_p.h"
26 #include "chartdataset_p.h"
26 #include "chartdataset_p.h"
27 #include "charttheme_p.h"
27 #include "charttheme_p.h"
28 #include "qabstractaxis.h"
28 #include "qabstractaxis.h"
29 #include "pieanimation_p.h"
29 #include "pieanimation_p.h"
30 #include "charthelpers_p.h"
30 #include "charthelpers_p.h"
31
31
32 #include "qpielegendmarker.h"
32 #include "qpielegendmarker.h"
33
33
34 QTCOMMERCIALCHART_BEGIN_NAMESPACE
34 QTCOMMERCIALCHART_BEGIN_NAMESPACE
35
35
36 /*!
36 /*!
37 \class QPieSeries
37 \class QPieSeries
38 \inmodule Qt Charts
38 \inmodule Qt Charts
39 \brief Pie series API for Qt Charts.
39 \brief Pie series API for Qt Charts.
40
40
41 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
41 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
42 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
42 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
43 The actual slice size is determined by that relative value.
43 The actual slice size is determined by that relative value.
44
44
45 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0.
45 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0.
46 These relate to the actual chart rectangle.
46 These relate to the actual chart rectangle.
47
47
48 By default the pie is defined as a full pie but it can also be a partial pie.
48 By default the pie is defined as a full pie but it can also be a partial pie.
49 This can be done by setting a starting angle and angle span to the series.
49 This can be done by setting a starting angle and angle span to the series.
50 Full pie is 360 degrees where 0 is at 12 a'clock.
50 Full pie is 360 degrees where 0 is at 12 a'clock.
51
51
52 See the \l {PieChart Example} {pie chart example} or \l {DonutChart Example} {donut chart example} to learn how to use QPieSeries.
52 See the \l {PieChart Example} {pie chart example} or \l {DonutChart Example} {donut chart example} to learn how to use QPieSeries.
53 \table 100%
53 \table 100%
54 \row
54 \row
55 \li \image examples_piechart.png
55 \li \image examples_piechart.png
56 \li \image examples_donutchart.png
56 \li \image examples_donutchart.png
57 \endtable
57 \endtable
58 */
58 */
59 #ifdef QDOC_QT5
59 #ifdef QDOC_QT5
60 /*!
60 /*!
61 \qmltype PieSeries
61 \qmltype PieSeries
62 \instantiates QPieSeries
62 \instantiates QPieSeries
63 \inqmlmodule QtCommercial.Chart
63 \inqmlmodule QtCommercial.Chart
64
64
65 \include doc/src/pieseries.qdocinc
65 \include doc/src/pieseries.qdocinc
66 */
66 */
67 #else
67 #else
68 /*!
68 /*!
69 \qmlclass PieSeries QPieSeries
69 \qmlclass PieSeries QPieSeries
70
70
71 \include ../doc/src/pieseries.qdocinc
71 \include ../doc/src/pieseries.qdocinc
72 */
72 */
73 #endif
73 #endif
74
74
75 /*!
75 /*!
76 \property QPieSeries::horizontalPosition
76 \property QPieSeries::horizontalPosition
77 \brief Defines the horizontal position of the pie.
77 \brief Defines the horizontal position of the pie.
78
78
79 The value is a relative value to the chart rectangle where:
79 The value is a relative value to the chart rectangle where:
80
80
81 \list
81 \list
82 \li 0.0 is the absolute left.
82 \li 0.0 is the absolute left.
83 \li 1.0 is the absolute right.
83 \li 1.0 is the absolute right.
84 \endlist
84 \endlist
85 Default value is 0.5 (center).
85 Default value is 0.5 (center).
86 \sa verticalPosition
86 \sa verticalPosition
87 */
87 */
88
88
89 /*!
89 /*!
90 \qmlproperty real PieSeries::horizontalPosition
90 \qmlproperty real PieSeries::horizontalPosition
91
91
92 Defines the horizontal position of the pie.
92 Defines the horizontal position of the pie.
93
93
94 The value is a relative value to the chart rectangle where:
94 The value is a relative value to the chart rectangle where:
95
95
96 \list
96 \list
97 \li 0.0 is the absolute left.
97 \li 0.0 is the absolute left.
98 \li 1.0 is the absolute right.
98 \li 1.0 is the absolute right.
99 \endlist
99 \endlist
100 Default value is 0.5 (center).
100 Default value is 0.5 (center).
101 \sa verticalPosition
101 \sa verticalPosition
102 */
102 */
103
103
104 /*!
104 /*!
105 \property QPieSeries::verticalPosition
105 \property QPieSeries::verticalPosition
106 \brief Defines the vertical position of the pie.
106 \brief Defines the vertical position of the pie.
107
107
108 The value is a relative value to the chart rectangle where:
108 The value is a relative value to the chart rectangle where:
109
109
110 \list
110 \list
111 \li 0.0 is the absolute top.
111 \li 0.0 is the absolute top.
112 \li 1.0 is the absolute bottom.
112 \li 1.0 is the absolute bottom.
113 \endlist
113 \endlist
114 Default value is 0.5 (center).
114 Default value is 0.5 (center).
115 \sa horizontalPosition
115 \sa horizontalPosition
116 */
116 */
117
117
118 /*!
118 /*!
119 \qmlproperty real PieSeries::verticalPosition
119 \qmlproperty real PieSeries::verticalPosition
120
120
121 Defines the vertical position of the pie.
121 Defines the vertical position of the pie.
122
122
123 The value is a relative value to the chart rectangle where:
123 The value is a relative value to the chart rectangle where:
124
124
125 \list
125 \list
126 \li 0.0 is the absolute top.
126 \li 0.0 is the absolute top.
127 \li 1.0 is the absolute bottom.
127 \li 1.0 is the absolute bottom.
128 \endlist
128 \endlist
129 Default value is 0.5 (center).
129 Default value is 0.5 (center).
130 \sa horizontalPosition
130 \sa horizontalPosition
131 */
131 */
132
132
133 /*!
133 /*!
134 \property QPieSeries::size
134 \property QPieSeries::size
135 \brief Defines the pie size.
135 \brief Defines the pie size.
136
136
137 The value is a relative value to the chart rectangle where:
137 The value is a relative value to the chart rectangle where:
138
138
139 \list
139 \list
140 \li 0.0 is the minimum size (pie not drawn).
140 \li 0.0 is the minimum size (pie not drawn).
141 \li 1.0 is the maximum size that can fit the chart.
141 \li 1.0 is the maximum size that can fit the chart.
142 \endlist
142 \endlist
143
143
144 When setting this property the holeSize property is adjusted if necessary, to ensure that the hole size is not greater than the outer size.
144 When setting this property the holeSize property is adjusted if necessary, to ensure that the hole size is not greater than the outer size.
145
145
146 Default value is 0.7.
146 Default value is 0.7.
147 */
147 */
148
148
149 /*!
149 /*!
150 \qmlproperty real PieSeries::size
150 \qmlproperty real PieSeries::size
151
151
152 Defines the pie size.
152 Defines the pie size.
153
153
154 The value is a relative value to the chart rectangle where:
154 The value is a relative value to the chart rectangle where:
155
155
156 \list
156 \list
157 \li 0.0 is the minimum size (pie not drawn).
157 \li 0.0 is the minimum size (pie not drawn).
158 \li 1.0 is the maximum size that can fit the chart.
158 \li 1.0 is the maximum size that can fit the chart.
159 \endlist
159 \endlist
160
160
161 Default value is 0.7.
161 Default value is 0.7.
162 */
162 */
163
163
164 /*!
164 /*!
165 \property QPieSeries::holeSize
165 \property QPieSeries::holeSize
166 \brief Defines the donut hole size.
166 \brief Defines the donut hole size.
167
167
168 The value is a relative value to the chart rectangle where:
168 The value is a relative value to the chart rectangle where:
169
169
170 \list
170 \list
171 \li 0.0 is the minimum size (full pie drawn, without any hole inside).
171 \li 0.0 is the minimum size (full pie drawn, without any hole inside).
172 \li 1.0 is the maximum size that can fit the chart. (donut has no width)
172 \li 1.0 is the maximum size that can fit the chart. (donut has no width)
173 \endlist
173 \endlist
174
174
175 The value is never greater then size property.
175 The value is never greater then size property.
176 Default value is 0.0.
176 Default value is 0.0.
177 */
177 */
178
178
179 /*!
179 /*!
180 \qmlproperty real PieSeries::holeSize
180 \qmlproperty real PieSeries::holeSize
181
181
182 Defines the donut hole size.
182 Defines the donut hole size.
183
183
184 The value is a relative value to the chart rectangle where:
184 The value is a relative value to the chart rectangle where:
185
185
186 \list
186 \list
187 \li 0.0 is the minimum size (full pie drawn, without any hole inside).
187 \li 0.0 is the minimum size (full pie drawn, without any hole inside).
188 \li 1.0 is the maximum size that can fit the chart. (donut has no width)
188 \li 1.0 is the maximum size that can fit the chart. (donut has no width)
189 \endlist
189 \endlist
190
190
191 When setting this property the size property is adjusted if necessary, to ensure that the inner size is not greater than the outer size.
191 When setting this property the size property is adjusted if necessary, to ensure that the inner size is not greater than the outer size.
192
192
193 Default value is 0.0.
193 Default value is 0.0.
194 */
194 */
195
195
196 /*!
196 /*!
197 \property QPieSeries::startAngle
197 \property QPieSeries::startAngle
198 \brief Defines the starting angle of the pie.
198 \brief Defines the starting angle of the pie.
199
199
200 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
200 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
201
201
202 Default is value is 0.
202 Default is value is 0.
203 */
203 */
204
204
205 /*!
205 /*!
206 \qmlproperty real PieSeries::startAngle
206 \qmlproperty real PieSeries::startAngle
207
207
208 Defines the starting angle of the pie.
208 Defines the starting angle of the pie.
209
209
210 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
210 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
211
211
212 Default is value is 0.
212 Default is value is 0.
213 */
213 */
214
214
215 /*!
215 /*!
216 \property QPieSeries::endAngle
216 \property QPieSeries::endAngle
217 \brief Defines the ending angle of the pie.
217 \brief Defines the ending angle of the pie.
218
218
219 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
219 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
220
220
221 Default is value is 360.
221 Default is value is 360.
222 */
222 */
223
223
224 /*!
224 /*!
225 \qmlproperty real PieSeries::endAngle
225 \qmlproperty real PieSeries::endAngle
226
226
227 Defines the ending angle of the pie.
227 Defines the ending angle of the pie.
228
228
229 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
229 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
230
230
231 Default is value is 360.
231 Default is value is 360.
232 */
232 */
233
233
234 /*!
234 /*!
235 \property QPieSeries::count
235 \property QPieSeries::count
236
236
237 Number of slices in the series.
237 Number of slices in the series.
238 */
238 */
239
239
240 /*!
240 /*!
241 \qmlproperty int PieSeries::count
241 \qmlproperty int PieSeries::count
242
242
243 Number of slices in the series.
243 Number of slices in the series.
244 */
244 */
245
245
246 /*!
246 /*!
247 \fn void QPieSeries::countChanged()
247 \fn void QPieSeries::countChanged()
248 Emitted when the slice count has changed.
248 Emitted when the slice count has changed.
249 \sa count
249 \sa count
250 */
250 */
251 /*!
251 /*!
252 \qmlsignal PieSeries::onCountChanged()
252 \qmlsignal PieSeries::onCountChanged()
253 Emitted when the slice count has changed.
253 Emitted when the slice count has changed.
254 */
254 */
255
255
256 /*!
256 /*!
257 \property QPieSeries::sum
257 \property QPieSeries::sum
258
258
259 Sum of all slices.
259 Sum of all slices.
260
260
261 The series keeps track of the sum of all slices it holds.
261 The series keeps track of the sum of all slices it holds.
262 */
262 */
263
263
264 /*!
264 /*!
265 \qmlproperty real PieSeries::sum
265 \qmlproperty real PieSeries::sum
266
266
267 Sum of all slices.
267 Sum of all slices.
268
268
269 The series keeps track of the sum of all slices it holds.
269 The series keeps track of the sum of all slices it holds.
270 */
270 */
271
271
272 /*!
272 /*!
273 \fn void QPieSeries::sumChanged()
273 \fn void QPieSeries::sumChanged()
274 Emitted when the sum of all slices has changed.
274 Emitted when the sum of all slices has changed.
275 \sa sum
275 \sa sum
276 */
276 */
277 /*!
277 /*!
278 \qmlsignal PieSeries::onSumChanged()
278 \qmlsignal PieSeries::onSumChanged()
279 Emitted when the sum of all slices has changed. This may happen for example if you add or remove slices, or if you
279 Emitted when the sum of all slices has changed. This may happen for example if you add or remove slices, or if you
280 change value of a slice.
280 change value of a slice.
281 */
281 */
282
282
283 /*!
283 /*!
284 \fn void QPieSeries::added(QList<QPieSlice*> slices)
284 \fn void QPieSeries::added(QList<QPieSlice*> slices)
285
285
286 This signal is emitted when \a slices have been added to the series.
286 This signal is emitted when \a slices have been added to the series.
287
287
288 \sa append(), insert()
288 \sa append(), insert()
289 */
289 */
290 /*!
290 /*!
291 \qmlsignal PieSeries::onAdded(PieSlice slice)
291 \qmlsignal PieSeries::onAdded(PieSlice slice)
292 Emitted when \a slice has been added to the series.
292 Emitted when \a slice has been added to the series.
293 */
293 */
294
294
295 /*!
295 /*!
296 \fn void QPieSeries::removed(QList<QPieSlice*> slices)
296 \fn void QPieSeries::removed(QList<QPieSlice*> slices)
297 This signal is emitted when \a slices have been removed from the series.
297 This signal is emitted when \a slices have been removed from the series.
298 \sa remove()
298 \sa remove()
299 */
299 */
300 /*!
300 /*!
301 \qmlsignal PieSeries::onRemoved(PieSlice slice)
301 \qmlsignal PieSeries::onRemoved(PieSlice slice)
302 Emitted when \a slice has been removed from the series.
302 Emitted when \a slice has been removed from the series.
303 */
303 */
304
304
305 /*!
305 /*!
306 \fn void QPieSeries::clicked(QPieSlice* slice)
306 \fn void QPieSeries::clicked(QPieSlice* slice)
307 This signal is emitted when a \a slice has been clicked.
307 This signal is emitted when a \a slice has been clicked.
308 \sa QPieSlice::clicked()
308 \sa QPieSlice::clicked()
309 */
309 */
310 /*!
310 /*!
311 \qmlsignal PieSeries::onClicked(PieSlice slice)
311 \qmlsignal PieSeries::onClicked(PieSlice slice)
312 This signal is emitted when a \a slice has been clicked.
312 This signal is emitted when a \a slice has been clicked.
313 */
313 */
314
314
315 /*!
315 /*!
316 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
316 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
317 This signal is emitted when user has hovered over or away from the \a slice.
317 This signal is emitted when user has hovered over or away from the \a slice.
318 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
318 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
319 \sa QPieSlice::hovered()
319 \sa QPieSlice::hovered()
320 */
320 */
321 /*!
321 /*!
322 \qmlsignal PieSeries::onHovered(PieSlice slice, bool state)
322 \qmlsignal PieSeries::onHovered(PieSlice slice, bool state)
323 This signal is emitted when user has hovered over or away from the \a slice. \a state is true when user has hovered
323 This signal is emitted when user has hovered over or away from the \a slice. \a state is true when user has hovered
324 over the slice and false when hover has moved away from the slice.
324 over the slice and false when hover has moved away from the slice.
325 */
325 */
326
326
327 /*!
327 /*!
328 \qmlmethod PieSlice PieSeries::at(int index)
328 \qmlmethod PieSlice PieSeries::at(int index)
329 Returns slice at \a index. Returns null if the index is not valid.
329 Returns slice at \a index. Returns null if the index is not valid.
330 */
330 */
331
331
332 /*!
332 /*!
333 \qmlmethod PieSlice PieSeries::find(string label)
333 \qmlmethod PieSlice PieSeries::find(string label)
334 Returns the first slice with \a label. Returns null if the index is not valid.
334 Returns the first slice with \a label. Returns null if the index is not valid.
335 */
335 */
336
336
337 /*!
337 /*!
338 \qmlmethod PieSlice PieSeries::append(string label, real value)
338 \qmlmethod PieSlice PieSeries::append(string label, real value)
339 Adds a new slice with \a label and \a value to the pie.
339 Adds a new slice with \a label and \a value to the pie.
340 */
340 */
341
341
342 /*!
342 /*!
343 \qmlmethod bool PieSeries::remove(PieSlice slice)
343 \qmlmethod bool PieSeries::remove(PieSlice slice)
344 Removes the \a slice from the pie. Returns true if the removal was successful, false otherwise.
344 Removes the \a slice from the pie. Returns true if the removal was successful, false otherwise.
345 */
345 */
346
346
347 /*!
347 /*!
348 \qmlmethod PieSeries::clear()
348 \qmlmethod PieSeries::clear()
349 Removes all slices from the pie.
349 Removes all slices from the pie.
350 */
350 */
351
351
352 /*!
352 /*!
353 Constructs a series object which is a child of \a parent.
353 Constructs a series object which is a child of \a parent.
354 */
354 */
355 QPieSeries::QPieSeries(QObject *parent)
355 QPieSeries::QPieSeries(QObject *parent)
356 : QAbstractSeries(*new QPieSeriesPrivate(this), parent)
356 : QAbstractSeries(*new QPieSeriesPrivate(this), parent)
357 {
357 {
358 Q_D(QPieSeries);
358 Q_D(QPieSeries);
359 QObject::connect(this, SIGNAL(countChanged()), d, SIGNAL(countChanged()));
359 QObject::connect(this, SIGNAL(countChanged()), d, SIGNAL(countChanged()));
360 }
360 }
361
361
362 /*!
362 /*!
363 Destroys the series and its slices.
363 Destroys the series and its slices.
364 */
364 */
365 QPieSeries::~QPieSeries()
365 QPieSeries::~QPieSeries()
366 {
366 {
367 // NOTE: d_prt destroyed by QObject
367 // NOTE: d_prt destroyed by QObject
368 clear();
368 clear();
369 }
369 }
370
370
371 /*!
371 /*!
372 Returns QAbstractSeries::SeriesTypePie.
372 Returns QAbstractSeries::SeriesTypePie.
373 */
373 */
374 QAbstractSeries::SeriesType QPieSeries::type() const
374 QAbstractSeries::SeriesType QPieSeries::type() const
375 {
375 {
376 return QAbstractSeries::SeriesTypePie;
376 return QAbstractSeries::SeriesTypePie;
377 }
377 }
378
378
379 /*!
379 /*!
380 Appends a single \a slice to the series.
380 Appends a single \a slice to the series.
381 Slice ownership is passed to the series.
381 Slice ownership is passed to the series.
382
382
383 Returns true if append was succesfull.
383 Returns true if append was succesfull.
384 */
384 */
385 bool QPieSeries::append(QPieSlice *slice)
385 bool QPieSeries::append(QPieSlice *slice)
386 {
386 {
387 return append(QList<QPieSlice *>() << slice);
387 return append(QList<QPieSlice *>() << slice);
388 }
388 }
389
389
390 /*!
390 /*!
391 Appends an array of \a slices to the series.
391 Appends an array of \a slices to the series.
392 Slice ownership is passed to the series.
392 Slice ownership is passed to the series.
393
393
394 Returns true if append was successful.
394 Returns true if append was successful.
395 */
395 */
396 bool QPieSeries::append(QList<QPieSlice *> slices)
396 bool QPieSeries::append(QList<QPieSlice *> slices)
397 {
397 {
398 Q_D(QPieSeries);
398 Q_D(QPieSeries);
399
399
400 if (slices.count() == 0)
400 if (slices.count() == 0)
401 return false;
401 return false;
402
402
403 foreach (QPieSlice *s, slices) {
403 foreach (QPieSlice *s, slices) {
404 if (!s || d->m_slices.contains(s))
404 if (!s || d->m_slices.contains(s))
405 return false;
405 return false;
406 if (s->series()) // already added to some series
406 if (s->series()) // already added to some series
407 return false;
407 return false;
408 if (!isValidValue(s->value()))
408 if (!isValidValue(s->value()))
409 return false;
409 return false;
410 }
410 }
411
411
412 foreach (QPieSlice *s, slices) {
412 foreach (QPieSlice *s, slices) {
413 s->setParent(this);
413 s->setParent(this);
414 QPieSlicePrivate::fromSlice(s)->m_series = this;
414 QPieSlicePrivate::fromSlice(s)->m_series = this;
415 d->m_slices << s;
415 d->m_slices << s;
416 }
416 }
417
417
418 d->updateDerivativeData();
418 d->updateDerivativeData();
419
419
420 foreach(QPieSlice * s, slices) {
420 foreach(QPieSlice * s, slices) {
421 connect(s, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
421 connect(s, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
422 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
422 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
423 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
423 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
424 }
424 }
425
425
426 emit added(slices);
426 emit added(slices);
427 emit countChanged();
427 emit countChanged();
428
428
429 return true;
429 return true;
430 }
430 }
431
431
432 /*!
432 /*!
433 Appends a single \a slice to the series and returns a reference to the series.
433 Appends a single \a slice to the series and returns a reference to the series.
434 Slice ownership is passed to the series.
434 Slice ownership is passed to the series.
435 */
435 */
436 QPieSeries &QPieSeries::operator << (QPieSlice *slice)
436 QPieSeries &QPieSeries::operator << (QPieSlice *slice)
437 {
437 {
438 append(slice);
438 append(slice);
439 return *this;
439 return *this;
440 }
440 }
441
441
442
442
443 /*!
443 /*!
444 Appends a single slice to the series with give \a value and \a label.
444 Appends a single slice to the series with give \a value and \a label.
445 Slice ownership is passed to the series.
445 Slice ownership is passed to the series.
446 Returns NULL if value is NaN, Inf or -Inf and no slice is added to the series.
446 Returns NULL if value is NaN, Inf or -Inf and no slice is added to the series.
447 */
447 */
448 QPieSlice *QPieSeries::append(QString label, qreal value)
448 QPieSlice *QPieSeries::append(QString label, qreal value)
449 {
449 {
450 if (isValidValue(value)) {
450 if (isValidValue(value)) {
451 QPieSlice *slice = new QPieSlice(label, value);
451 QPieSlice *slice = new QPieSlice(label, value);
452 append(slice);
452 append(slice);
453 return slice;
453 return slice;
454 } else {
454 } else {
455 return 0;
455 return 0;
456 }
456 }
457 }
457 }
458
458
459 /*!
459 /*!
460 Inserts a single \a slice to the series before the slice at \a index position.
460 Inserts a single \a slice to the series before the slice at \a index position.
461 Slice ownership is passed to the series.
461 Slice ownership is passed to the series.
462
462
463 Returns true if insert was successful.
463 Returns true if insert was successful.
464 */
464 */
465 bool QPieSeries::insert(int index, QPieSlice *slice)
465 bool QPieSeries::insert(int index, QPieSlice *slice)
466 {
466 {
467 Q_D(QPieSeries);
467 Q_D(QPieSeries);
468
468
469 if (index < 0 || index > d->m_slices.count())
469 if (index < 0 || index > d->m_slices.count())
470 return false;
470 return false;
471
471
472 if (!slice || d->m_slices.contains(slice))
472 if (!slice || d->m_slices.contains(slice))
473 return false;
473 return false;
474
474
475 if (slice->series()) // already added to some series
475 if (slice->series()) // already added to some series
476 return false;
476 return false;
477
477
478 if (!isValidValue(slice->value()))
478 if (!isValidValue(slice->value()))
479 return false;
479 return false;
480
480
481 slice->setParent(this);
481 slice->setParent(this);
482 QPieSlicePrivate::fromSlice(slice)->m_series = this;
482 QPieSlicePrivate::fromSlice(slice)->m_series = this;
483 d->m_slices.insert(index, slice);
483 d->m_slices.insert(index, slice);
484
484
485 d->updateDerivativeData();
485 d->updateDerivativeData();
486
486
487 connect(slice, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
487 connect(slice, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
488 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
488 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
489 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
489 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
490
490
491 emit added(QList<QPieSlice *>() << slice);
491 emit added(QList<QPieSlice *>() << slice);
492 emit countChanged();
492 emit countChanged();
493
493
494 return true;
494 return true;
495 }
495 }
496
496
497 /*!
497 /*!
498 Removes a single \a slice from the series and deletes the slice.
498 Removes a single \a slice from the series and deletes the slice.
499
499
500 Do not reference the pointer after this call.
500 Do not reference the pointer after this call.
501
501
502 Returns true if remove was successful.
502 Returns true if remove was successful.
503 */
503 */
504 bool QPieSeries::remove(QPieSlice *slice)
504 bool QPieSeries::remove(QPieSlice *slice)
505 {
505 {
506 Q_D(QPieSeries);
506 Q_D(QPieSeries);
507
507
508 if (!d->m_slices.removeOne(slice))
508 if (!d->m_slices.removeOne(slice))
509 return false;
509 return false;
510
510
511 d->updateDerivativeData();
511 d->updateDerivativeData();
512
512
513 emit removed(QList<QPieSlice *>() << slice);
513 emit removed(QList<QPieSlice *>() << slice);
514 emit countChanged();
514 emit countChanged();
515
515
516 delete slice;
516 delete slice;
517 slice = 0;
517 slice = 0;
518
518
519 return true;
519 return true;
520 }
520 }
521
521
522 /*!
522 /*!
523 Takes a single \a slice from the series. Does not destroy the slice object.
523 Takes a single \a slice from the series. Does not destroy the slice object.
524
524
525 \note The series remains as the slice's parent object. You must set the
525 \note The series remains as the slice's parent object. You must set the
526 parent object to take full ownership.
526 parent object to take full ownership.
527
527
528 Returns true if take was successful.
528 Returns true if take was successful.
529 */
529 */
530 bool QPieSeries::take(QPieSlice *slice)
530 bool QPieSeries::take(QPieSlice *slice)
531 {
531 {
532 Q_D(QPieSeries);
532 Q_D(QPieSeries);
533
533
534 if (!d->m_slices.removeOne(slice))
534 if (!d->m_slices.removeOne(slice))
535 return false;
535 return false;
536
536
537 QPieSlicePrivate::fromSlice(slice)->m_series = 0;
537 QPieSlicePrivate::fromSlice(slice)->m_series = 0;
538 slice->disconnect(d);
538 slice->disconnect(d);
539
539
540 d->updateDerivativeData();
540 d->updateDerivativeData();
541
541
542 emit removed(QList<QPieSlice *>() << slice);
542 emit removed(QList<QPieSlice *>() << slice);
543 emit countChanged();
543 emit countChanged();
544
544
545 return true;
545 return true;
546 }
546 }
547
547
548 /*!
548 /*!
549 Clears all slices from the series.
549 Clears all slices from the series.
550 */
550 */
551 void QPieSeries::clear()
551 void QPieSeries::clear()
552 {
552 {
553 Q_D(QPieSeries);
553 Q_D(QPieSeries);
554 if (d->m_slices.count() == 0)
554 if (d->m_slices.count() == 0)
555 return;
555 return;
556
556
557 QList<QPieSlice *> slices = d->m_slices;
557 QList<QPieSlice *> slices = d->m_slices;
558 foreach (QPieSlice *s, d->m_slices)
558 foreach (QPieSlice *s, d->m_slices)
559 d->m_slices.removeOne(s);
559 d->m_slices.removeOne(s);
560
560
561 d->updateDerivativeData();
561 d->updateDerivativeData();
562
562
563 emit removed(slices);
563 emit removed(slices);
564 emit countChanged();
564 emit countChanged();
565
565
566 foreach (QPieSlice *s, slices)
566 foreach (QPieSlice *s, slices)
567 delete s;
567 delete s;
568 }
568 }
569
569
570 /*!
570 /*!
571 Returns a list of slices that belong to this series.
571 Returns a list of slices that belong to this series.
572 */
572 */
573 QList<QPieSlice *> QPieSeries::slices() const
573 QList<QPieSlice *> QPieSeries::slices() const
574 {
574 {
575 Q_D(const QPieSeries);
575 Q_D(const QPieSeries);
576 return d->m_slices;
576 return d->m_slices;
577 }
577 }
578
578
579 /*!
579 /*!
580 returns the number of the slices in this series.
580 returns the number of the slices in this series.
581 */
581 */
582 int QPieSeries::count() const
582 int QPieSeries::count() const
583 {
583 {
584 Q_D(const QPieSeries);
584 Q_D(const QPieSeries);
585 return d->m_slices.count();
585 return d->m_slices.count();
586 }
586 }
587
587
588 /*!
588 /*!
589 Returns true is the series is empty.
589 Returns true is the series is empty.
590 */
590 */
591 bool QPieSeries::isEmpty() const
591 bool QPieSeries::isEmpty() const
592 {
592 {
593 Q_D(const QPieSeries);
593 Q_D(const QPieSeries);
594 return d->m_slices.isEmpty();
594 return d->m_slices.isEmpty();
595 }
595 }
596
596
597 /*!
597 /*!
598 Returns the sum of all slice values in this series.
598 Returns the sum of all slice values in this series.
599
599
600 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
600 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
601 */
601 */
602 qreal QPieSeries::sum() const
602 qreal QPieSeries::sum() const
603 {
603 {
604 Q_D(const QPieSeries);
604 Q_D(const QPieSeries);
605 return d->m_sum;
605 return d->m_sum;
606 }
606 }
607
607
608 void QPieSeries::setHoleSize(qreal holeSize)
608 void QPieSeries::setHoleSize(qreal holeSize)
609 {
609 {
610 Q_D(QPieSeries);
610 Q_D(QPieSeries);
611 holeSize = qBound((qreal)0.0, holeSize, (qreal)1.0);
611 holeSize = qBound((qreal)0.0, holeSize, (qreal)1.0);
612 d->setSizes(holeSize, qMax(d->m_pieRelativeSize, holeSize));
612 d->setSizes(holeSize, qMax(d->m_pieRelativeSize, holeSize));
613 }
613 }
614
614
615 qreal QPieSeries::holeSize() const
615 qreal QPieSeries::holeSize() const
616 {
616 {
617 Q_D(const QPieSeries);
617 Q_D(const QPieSeries);
618 return d->m_holeRelativeSize;
618 return d->m_holeRelativeSize;
619 }
619 }
620
620
621 void QPieSeries::setHorizontalPosition(qreal relativePosition)
621 void QPieSeries::setHorizontalPosition(qreal relativePosition)
622 {
622 {
623 Q_D(QPieSeries);
623 Q_D(QPieSeries);
624
624
625 if (relativePosition < 0.0)
625 if (relativePosition < 0.0)
626 relativePosition = 0.0;
626 relativePosition = 0.0;
627 if (relativePosition > 1.0)
627 if (relativePosition > 1.0)
628 relativePosition = 1.0;
628 relativePosition = 1.0;
629
629
630 if (!qFuzzyCompare(d->m_pieRelativeHorPos, relativePosition)) {
630 if (!qFuzzyCompare(d->m_pieRelativeHorPos, relativePosition)) {
631 d->m_pieRelativeHorPos = relativePosition;
631 d->m_pieRelativeHorPos = relativePosition;
632 emit d->horizontalPositionChanged();
632 emit d->horizontalPositionChanged();
633 }
633 }
634 }
634 }
635
635
636 qreal QPieSeries::horizontalPosition() const
636 qreal QPieSeries::horizontalPosition() const
637 {
637 {
638 Q_D(const QPieSeries);
638 Q_D(const QPieSeries);
639 return d->m_pieRelativeHorPos;
639 return d->m_pieRelativeHorPos;
640 }
640 }
641
641
642 void QPieSeries::setVerticalPosition(qreal relativePosition)
642 void QPieSeries::setVerticalPosition(qreal relativePosition)
643 {
643 {
644 Q_D(QPieSeries);
644 Q_D(QPieSeries);
645
645
646 if (relativePosition < 0.0)
646 if (relativePosition < 0.0)
647 relativePosition = 0.0;
647 relativePosition = 0.0;
648 if (relativePosition > 1.0)
648 if (relativePosition > 1.0)
649 relativePosition = 1.0;
649 relativePosition = 1.0;
650
650
651 if (!qFuzzyCompare(d->m_pieRelativeVerPos, relativePosition)) {
651 if (!qFuzzyCompare(d->m_pieRelativeVerPos, relativePosition)) {
652 d->m_pieRelativeVerPos = relativePosition;
652 d->m_pieRelativeVerPos = relativePosition;
653 emit d->verticalPositionChanged();
653 emit d->verticalPositionChanged();
654 }
654 }
655 }
655 }
656
656
657 qreal QPieSeries::verticalPosition() const
657 qreal QPieSeries::verticalPosition() const
658 {
658 {
659 Q_D(const QPieSeries);
659 Q_D(const QPieSeries);
660 return d->m_pieRelativeVerPos;
660 return d->m_pieRelativeVerPos;
661 }
661 }
662
662
663 void QPieSeries::setPieSize(qreal relativeSize)
663 void QPieSeries::setPieSize(qreal relativeSize)
664 {
664 {
665 Q_D(QPieSeries);
665 Q_D(QPieSeries);
666 relativeSize = qBound((qreal)0.0, relativeSize, (qreal)1.0);
666 relativeSize = qBound((qreal)0.0, relativeSize, (qreal)1.0);
667 d->setSizes(qMin(d->m_holeRelativeSize, relativeSize), relativeSize);
667 d->setSizes(qMin(d->m_holeRelativeSize, relativeSize), relativeSize);
668
668
669 }
669 }
670
670
671 qreal QPieSeries::pieSize() const
671 qreal QPieSeries::pieSize() const
672 {
672 {
673 Q_D(const QPieSeries);
673 Q_D(const QPieSeries);
674 return d->m_pieRelativeSize;
674 return d->m_pieRelativeSize;
675 }
675 }
676
676
677
677
678 void QPieSeries::setPieStartAngle(qreal angle)
678 void QPieSeries::setPieStartAngle(qreal angle)
679 {
679 {
680 Q_D(QPieSeries);
680 Q_D(QPieSeries);
681 if (qFuzzyCompare(d->m_pieStartAngle, angle))
681 if (qFuzzyCompare(d->m_pieStartAngle, angle))
682 return;
682 return;
683 d->m_pieStartAngle = angle;
683 d->m_pieStartAngle = angle;
684 d->updateDerivativeData();
684 d->updateDerivativeData();
685 emit d->pieStartAngleChanged();
685 emit d->pieStartAngleChanged();
686 }
686 }
687
687
688 qreal QPieSeries::pieStartAngle() const
688 qreal QPieSeries::pieStartAngle() const
689 {
689 {
690 Q_D(const QPieSeries);
690 Q_D(const QPieSeries);
691 return d->m_pieStartAngle;
691 return d->m_pieStartAngle;
692 }
692 }
693
693
694 /*!
694 /*!
695 Sets the end angle of the pie.
695 Sets the end angle of the pie.
696
696
697 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
697 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
698
698
699 \a angle must be greater than start angle.
699 \a angle must be greater than start angle.
700
700
701 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
701 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
702 */
702 */
703 void QPieSeries::setPieEndAngle(qreal angle)
703 void QPieSeries::setPieEndAngle(qreal angle)
704 {
704 {
705 Q_D(QPieSeries);
705 Q_D(QPieSeries);
706 if (qFuzzyCompare(d->m_pieEndAngle, angle))
706 if (qFuzzyCompare(d->m_pieEndAngle, angle))
707 return;
707 return;
708 d->m_pieEndAngle = angle;
708 d->m_pieEndAngle = angle;
709 d->updateDerivativeData();
709 d->updateDerivativeData();
710 emit d->pieEndAngleChanged();
710 emit d->pieEndAngleChanged();
711 }
711 }
712
712
713 /*!
713 /*!
714 Returns the end angle of the pie.
714 Returns the end angle of the pie.
715
715
716 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
716 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
717
717
718 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
718 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
719 */
719 */
720 qreal QPieSeries::pieEndAngle() const
720 qreal QPieSeries::pieEndAngle() const
721 {
721 {
722 Q_D(const QPieSeries);
722 Q_D(const QPieSeries);
723 return d->m_pieEndAngle;
723 return d->m_pieEndAngle;
724 }
724 }
725
725
726 /*!
726 /*!
727 Sets the all the slice labels \a visible or invisible.
727 Sets the all the slice labels \a visible or invisible.
728
728
729 Note that this affects only the current slices in the series.
729 Note that this affects only the current slices in the series.
730 If user adds a new slice the default label visibility is false.
730 If user adds a new slice the default label visibility is false.
731
731
732 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
732 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
733 */
733 */
734 void QPieSeries::setLabelsVisible(bool visible)
734 void QPieSeries::setLabelsVisible(bool visible)
735 {
735 {
736 Q_D(QPieSeries);
736 Q_D(QPieSeries);
737 foreach (QPieSlice *s, d->m_slices)
737 foreach (QPieSlice *s, d->m_slices)
738 s->setLabelVisible(visible);
738 s->setLabelVisible(visible);
739 }
739 }
740
740
741 /*!
741 /*!
742 Sets the all the slice labels \a position
742 Sets the all the slice labels \a position
743
743
744 Note that this affects only the current slices in the series.
744 Note that this affects only the current slices in the series.
745 If user adds a new slice the default label position is LabelOutside
745 If user adds a new slice the default label position is LabelOutside
746
746
747 \sa QPieSlice::labelPosition(), QPieSlice::setLabelPosition()
747 \sa QPieSlice::labelPosition(), QPieSlice::setLabelPosition()
748 */
748 */
749 void QPieSeries::setLabelsPosition(QPieSlice::LabelPosition position)
749 void QPieSeries::setLabelsPosition(QPieSlice::LabelPosition position)
750 {
750 {
751 Q_D(QPieSeries);
751 Q_D(QPieSeries);
752 foreach (QPieSlice *s, d->m_slices)
752 foreach (QPieSlice *s, d->m_slices)
753 s->setLabelPosition(position);
753 s->setLabelPosition(position);
754 }
754 }
755
755
756 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
756 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
757
757
758
758
759 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
759 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
760 QAbstractSeriesPrivate(parent),
760 QAbstractSeriesPrivate(parent),
761 m_pieRelativeHorPos(0.5),
761 m_pieRelativeHorPos(0.5),
762 m_pieRelativeVerPos(0.5),
762 m_pieRelativeVerPos(0.5),
763 m_pieRelativeSize(0.7),
763 m_pieRelativeSize(0.7),
764 m_pieStartAngle(0),
764 m_pieStartAngle(0),
765 m_pieEndAngle(360),
765 m_pieEndAngle(360),
766 m_sum(0),
766 m_sum(0),
767 m_holeRelativeSize(0.0)
767 m_holeRelativeSize(0.0)
768 {
768 {
769 }
769 }
770
770
771 QPieSeriesPrivate::~QPieSeriesPrivate()
771 QPieSeriesPrivate::~QPieSeriesPrivate()
772 {
772 {
773 }
773 }
774
774
775 void QPieSeriesPrivate::updateDerivativeData()
775 void QPieSeriesPrivate::updateDerivativeData()
776 {
776 {
777 // calculate sum of all slices
777 // calculate sum of all slices
778 qreal sum = 0;
778 qreal sum = 0;
779 foreach (QPieSlice *s, m_slices)
779 foreach (QPieSlice *s, m_slices)
780 sum += s->value();
780 sum += s->value();
781
781
782 if (!qFuzzyCompare(m_sum, sum)) {
782 if (!qFuzzyCompare(m_sum, sum)) {
783 m_sum = sum;
783 m_sum = sum;
784 emit q_func()->sumChanged();
784 emit q_func()->sumChanged();
785 }
785 }
786
786
787 // nothing to show..
787 // nothing to show..
788 if (qFuzzyCompare(m_sum, 0))
788 if (qFuzzyCompare(m_sum, 0))
789 return;
789 return;
790
790
791 // update slice attributes
791 // update slice attributes
792 qreal sliceAngle = m_pieStartAngle;
792 qreal sliceAngle = m_pieStartAngle;
793 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
793 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
794 QVector<QPieSlice *> changed;
794 QVector<QPieSlice *> changed;
795 foreach (QPieSlice *s, m_slices) {
795 foreach (QPieSlice *s, m_slices) {
796 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
796 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
797 d->setPercentage(s->value() / m_sum);
797 d->setPercentage(s->value() / m_sum);
798 d->setStartAngle(sliceAngle);
798 d->setStartAngle(sliceAngle);
799 d->setAngleSpan(pieSpan * s->percentage());
799 d->setAngleSpan(pieSpan * s->percentage());
800 sliceAngle += s->angleSpan();
800 sliceAngle += s->angleSpan();
801 }
801 }
802
802
803
803
804 emit calculatedDataChanged();
804 emit calculatedDataChanged();
805 }
805 }
806
806
807 void QPieSeriesPrivate::setSizes(qreal innerSize, qreal outerSize)
807 void QPieSeriesPrivate::setSizes(qreal innerSize, qreal outerSize)
808 {
808 {
809 bool changed = false;
809 bool changed = false;
810
810
811 if (!qFuzzyCompare(m_holeRelativeSize, innerSize)) {
811 if (!qFuzzyCompare(m_holeRelativeSize, innerSize)) {
812 m_holeRelativeSize = innerSize;
812 m_holeRelativeSize = innerSize;
813 changed = true;
813 changed = true;
814 }
814 }
815
815
816 if (!qFuzzyCompare(m_pieRelativeSize, outerSize)) {
816 if (!qFuzzyCompare(m_pieRelativeSize, outerSize)) {
817 m_pieRelativeSize = outerSize;
817 m_pieRelativeSize = outerSize;
818 changed = true;
818 changed = true;
819 }
819 }
820
820
821 if (changed)
821 if (changed)
822 emit pieSizeChanged();
822 emit pieSizeChanged();
823 }
823 }
824
824
825 QPieSeriesPrivate *QPieSeriesPrivate::fromSeries(QPieSeries *series)
825 QPieSeriesPrivate *QPieSeriesPrivate::fromSeries(QPieSeries *series)
826 {
826 {
827 return series->d_func();
827 return series->d_func();
828 }
828 }
829
829
830 void QPieSeriesPrivate::sliceValueChanged()
830 void QPieSeriesPrivate::sliceValueChanged()
831 {
831 {
832 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
832 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
833 updateDerivativeData();
833 updateDerivativeData();
834 }
834 }
835
835
836 void QPieSeriesPrivate::sliceClicked()
836 void QPieSeriesPrivate::sliceClicked()
837 {
837 {
838 QPieSlice *slice = qobject_cast<QPieSlice *>(sender());
838 QPieSlice *slice = qobject_cast<QPieSlice *>(sender());
839 Q_ASSERT(m_slices.contains(slice));
839 Q_ASSERT(m_slices.contains(slice));
840 Q_Q(QPieSeries);
840 Q_Q(QPieSeries);
841 emit q->clicked(slice);
841 emit q->clicked(slice);
842 }
842 }
843
843
844 void QPieSeriesPrivate::sliceHovered(bool state)
844 void QPieSeriesPrivate::sliceHovered(bool state)
845 {
845 {
846 QPieSlice *slice = qobject_cast<QPieSlice *>(sender());
846 QPieSlice *slice = qobject_cast<QPieSlice *>(sender());
847 Q_ASSERT(m_slices.contains(slice));
847 if (!m_slices.isEmpty()) {
848 Q_Q(QPieSeries);
848 Q_ASSERT(m_slices.contains(slice));
849 emit q->hovered(slice, state);
849 Q_Q(QPieSeries);
850 emit q->hovered(slice, state);
851 }
850 }
852 }
851
853
852 void QPieSeriesPrivate::initializeDomain()
854 void QPieSeriesPrivate::initializeDomain()
853 {
855 {
854 // does not apply to pie
856 // does not apply to pie
855 }
857 }
856
858
857 void QPieSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
859 void QPieSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
858 {
860 {
859 Q_Q(QPieSeries);
861 Q_Q(QPieSeries);
860 PieChartItem *pie = new PieChartItem(q,parent);
862 PieChartItem *pie = new PieChartItem(q,parent);
861 m_item.reset(pie);
863 m_item.reset(pie);
862 QAbstractSeriesPrivate::initializeGraphics(parent);
864 QAbstractSeriesPrivate::initializeGraphics(parent);
863 }
865 }
864
866
865 void QPieSeriesPrivate::initializeAnimations(QtCommercialChart::QChart::AnimationOptions options)
867 void QPieSeriesPrivate::initializeAnimations(QtCommercialChart::QChart::AnimationOptions options)
866 {
868 {
867 PieChartItem *item = static_cast<PieChartItem *>(m_item.data());
869 PieChartItem *item = static_cast<PieChartItem *>(m_item.data());
868 Q_ASSERT(item);
870 Q_ASSERT(item);
869 if (item->animation())
871 if (item->animation())
870 item->animation()->stopAndDestroyLater();
872 item->animation()->stopAndDestroyLater();
871
873
872 if (options.testFlag(QChart::SeriesAnimations))
874 if (options.testFlag(QChart::SeriesAnimations))
873 item->setAnimation(new PieAnimation(item));
875 item->setAnimation(new PieAnimation(item));
874 else
876 else
875 item->setAnimation(0);
877 item->setAnimation(0);
876 QAbstractSeriesPrivate::initializeAnimations(options);
878 QAbstractSeriesPrivate::initializeAnimations(options);
877 }
879 }
878
880
879 QList<QLegendMarker*> QPieSeriesPrivate::createLegendMarkers(QLegend* legend)
881 QList<QLegendMarker*> QPieSeriesPrivate::createLegendMarkers(QLegend* legend)
880 {
882 {
881 Q_Q(QPieSeries);
883 Q_Q(QPieSeries);
882 QList<QLegendMarker*> markers;
884 QList<QLegendMarker*> markers;
883 foreach(QPieSlice* slice, q->slices()) {
885 foreach(QPieSlice* slice, q->slices()) {
884 QPieLegendMarker* marker = new QPieLegendMarker(q,slice,legend);
886 QPieLegendMarker* marker = new QPieLegendMarker(q,slice,legend);
885 markers << marker;
887 markers << marker;
886 }
888 }
887 return markers;
889 return markers;
888 }
890 }
889
891
890 void QPieSeriesPrivate::initializeAxes()
892 void QPieSeriesPrivate::initializeAxes()
891 {
893 {
892
894
893 }
895 }
894
896
895 QAbstractAxis::AxisType QPieSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
897 QAbstractAxis::AxisType QPieSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
896 {
898 {
897 Q_UNUSED(orientation);
899 Q_UNUSED(orientation);
898 return QAbstractAxis::AxisTypeNoAxis;
900 return QAbstractAxis::AxisTypeNoAxis;
899 }
901 }
900
902
901 QAbstractAxis* QPieSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
903 QAbstractAxis* QPieSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
902 {
904 {
903 Q_UNUSED(orientation);
905 Q_UNUSED(orientation);
904 return 0;
906 return 0;
905 }
907 }
906
908
907 void QPieSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
909 void QPieSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
908 {
910 {
909 //Q_Q(QPieSeries);
911 //Q_Q(QPieSeries);
910 //const QList<QColor>& colors = theme->seriesColors();
912 //const QList<QColor>& colors = theme->seriesColors();
911 const QList<QGradient>& gradients = theme->seriesGradients();
913 const QList<QGradient>& gradients = theme->seriesGradients();
912
914
913 for (int i(0); i < m_slices.count(); i++) {
915 for (int i(0); i < m_slices.count(); i++) {
914
916
915 QColor penColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0);
917 QColor penColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0);
916
918
917 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
919 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
918 qreal pos = (qreal)(i + 1) / (qreal) m_slices.count();
920 qreal pos = (qreal)(i + 1) / (qreal) m_slices.count();
919 QColor brushColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), pos);
921 QColor brushColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), pos);
920
922
921 QPieSlice *s = m_slices.at(i);
923 QPieSlice *s = m_slices.at(i);
922 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
924 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
923
925
924 if (forced || d->m_data.m_slicePen.isThemed())
926 if (forced || d->m_data.m_slicePen.isThemed())
925 d->setPen(penColor, true);
927 d->setPen(penColor, true);
926
928
927 if (forced || d->m_data.m_sliceBrush.isThemed())
929 if (forced || d->m_data.m_sliceBrush.isThemed())
928 d->setBrush(brushColor, true);
930 d->setBrush(brushColor, true);
929
931
930 if (forced || d->m_data.m_labelBrush.isThemed())
932 if (forced || d->m_data.m_labelBrush.isThemed())
931 d->setLabelBrush(theme->labelBrush().color(), true);
933 d->setLabelBrush(theme->labelBrush().color(), true);
932
934
933 if (forced || d->m_data.m_labelFont.isThemed())
935 if (forced || d->m_data.m_labelFont.isThemed())
934 d->setLabelFont(theme->labelFont(), true);
936 d->setLabelFont(theme->labelFont(), true);
935 }
937 }
936 }
938 }
937
939
938
940
939 #include "moc_qpieseries.cpp"
941 #include "moc_qpieseries.cpp"
940 #include "moc_qpieseries_p.cpp"
942 #include "moc_qpieseries_p.cpp"
941
943
942 QTCOMMERCIALCHART_END_NAMESPACE
944 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now