@@ -251,11 +251,11 void ChartAnimator::updateLayout(XYChartItem *item, QVector<QPointF> &oldPoints, | |||
|
251 | 251 | QTimer::singleShot(0, animation, SLOT(start())); |
|
252 | 252 | } |
|
253 | 253 | |
|
254 |
void ChartAnimator::addAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData, bool |
|
|
254 | void ChartAnimator::addAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData, bool startupAnimation) | |
|
255 | 255 | { |
|
256 | 256 | PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item)); |
|
257 | 257 | Q_ASSERT(animation); |
|
258 |
animation->addSlice(sliceItem, sliceData, |
|
|
258 | animation->addSlice(sliceItem, sliceData, startupAnimation); | |
|
259 | 259 | } |
|
260 | 260 | |
|
261 | 261 | void ChartAnimator::removeAnimation(PieChartItem *item, PieSliceItem *sliceItem) |
@@ -265,14 +265,7 void ChartAnimator::removeAnimation(PieChartItem *item, PieSliceItem *sliceItem) | |||
|
265 | 265 | animation->removeSlice(sliceItem); |
|
266 | 266 | } |
|
267 | 267 | |
|
268 |
void ChartAnimator::update |
|
|
269 | { | |
|
270 | PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item)); | |
|
271 | Q_ASSERT(animation); | |
|
272 | animation->updateValues(layout); | |
|
273 | } | |
|
274 | ||
|
275 | void ChartAnimator::updateLayout(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData) | |
|
268 | void ChartAnimator::updateAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData) | |
|
276 | 269 | { |
|
277 | 270 | PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item)); |
|
278 | 271 | Q_ASSERT(animation); |
@@ -61,8 +61,7 public: | |||
|
61 | 61 | |
|
62 | 62 | void addAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData, bool isEmpty); |
|
63 | 63 | void removeAnimation(PieChartItem *item, PieSliceItem *sliceItem); |
|
64 |
void update |
|
|
65 | void updateLayout(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData); | |
|
64 | void updateAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData); | |
|
66 | 65 | |
|
67 | 66 | void updateLayout(BarChartItem *item, const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout); |
|
68 | 67 |
@@ -36,12 +36,6 PieAnimation::~PieAnimation() | |||
|
36 | 36 | { |
|
37 | 37 | } |
|
38 | 38 | |
|
39 | void PieAnimation::updateValues(const PieLayout &newValues) | |
|
40 | { | |
|
41 | foreach (PieSliceItem *s, newValues.keys()) | |
|
42 | updateValue(s, newValues.value(s)); | |
|
43 | } | |
|
44 | ||
|
45 | 39 | void PieAnimation::updateValue(PieSliceItem *sliceItem, const PieSliceData &sliceData) |
|
46 | 40 | { |
|
47 | 41 | PieSliceAnimation *animation = m_animations.value(sliceItem); |
@@ -55,14 +49,14 void PieAnimation::updateValue(PieSliceItem *sliceItem, const PieSliceData &slic | |||
|
55 | 49 | QTimer::singleShot(0, animation, SLOT(start())); |
|
56 | 50 | } |
|
57 | 51 | |
|
58 |
void PieAnimation::addSlice(PieSliceItem *sliceItem, const PieSliceData &sliceData, bool |
|
|
52 | void PieAnimation::addSlice(PieSliceItem *sliceItem, const PieSliceData &sliceData, bool startupAnimation) | |
|
59 | 53 | { |
|
60 | 54 | PieSliceAnimation *animation = new PieSliceAnimation(sliceItem); |
|
61 | 55 | m_animations.insert(sliceItem, animation); |
|
62 | 56 | |
|
63 | 57 | PieSliceData startValue = sliceData; |
|
64 | 58 | startValue.m_radius = 0; |
|
65 | if (isEmpty) | |
|
59 | if (startupAnimation) | |
|
66 | 60 | startValue.m_startAngle = 0; |
|
67 | 61 | else |
|
68 | 62 | startValue.m_startAngle = sliceData.m_startAngle + (sliceData.m_angleSpan / 2); |
@@ -36,9 +36,8 class PieAnimation : public ChartAnimation | |||
|
36 | 36 | public: |
|
37 | 37 | PieAnimation(PieChartItem *item); |
|
38 | 38 | ~PieAnimation(); |
|
39 | void updateValues(const PieLayout &newValues); | |
|
40 | 39 | void updateValue(PieSliceItem *sliceItem, const PieSliceData &newValue); |
|
41 |
void addSlice(PieSliceItem *sliceItem, const PieSliceData &endValue, bool |
|
|
40 | void addSlice(PieSliceItem *sliceItem, const PieSliceData &endValue, bool startupAnimation); | |
|
42 | 41 | void removeSlice(PieSliceItem *sliceItem); |
|
43 | 42 | |
|
44 | 43 | public: // from QVariantAnimation |
@@ -118,9 +118,7 void PieSliceAnimation::updateCurrentValue(const QVariant &value) | |||
|
118 | 118 | { |
|
119 | 119 | if (state() != QAbstractAnimation::Stopped) { //workaround |
|
120 | 120 | m_currentValue = qVariantValue<PieSliceData>(value); |
|
121 |
m_sliceItem->set |
|
|
122 | m_sliceItem->updateGeometry(); | |
|
123 | m_sliceItem->update(); | |
|
121 | m_sliceItem->setLayout(m_currentValue); | |
|
124 | 122 | } |
|
125 | 123 | } |
|
126 | 124 |
@@ -40,8 +40,8 PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter* presenter) | |||
|
40 | 40 | QPieSeriesPrivate *d = QPieSeriesPrivate::seriesData(*series); |
|
41 | 41 | connect(d, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>))); |
|
42 | 42 | connect(d, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>))); |
|
43 |
connect(d, SIGNAL(piePositionChanged()), this, SLOT( |
|
|
44 |
connect(d, SIGNAL(pieSizeChanged()), this, SLOT( |
|
|
43 | connect(d, SIGNAL(piePositionChanged()), this, SLOT(updateLayout())); | |
|
44 | connect(d, SIGNAL(pieSizeChanged()), this, SLOT(updateLayout())); | |
|
45 | 45 | |
|
46 | 46 | QTimer::singleShot(0, this, SLOT(initialize())); // TODO: get rid of this |
|
47 | 47 | |
@@ -54,13 +54,11 PieChartItem::~PieChartItem() | |||
|
54 | 54 | // slices deleted automatically through QGraphicsItem |
|
55 | 55 | } |
|
56 | 56 | |
|
57 | void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) | |
|
57 | void PieChartItem::handleGeometryChanged(const QRectF& rect) | |
|
58 | 58 | { |
|
59 | Q_UNUSED(painter) | |
|
60 | // TODO: paint shadows for all components | |
|
61 | // - get paths from items & merge & offset and draw with shadow color? | |
|
62 | //painter->setBrush(QBrush(Qt::red)); | |
|
63 | //painter->drawRect(m_debugRect); | |
|
59 | prepareGeometryChange(); | |
|
60 | m_rect = rect; | |
|
61 | updateLayout(); | |
|
64 | 62 | } |
|
65 | 63 | |
|
66 | 64 | void PieChartItem::initialize() |
@@ -68,25 +66,53 void PieChartItem::initialize() | |||
|
68 | 66 | handleSlicesAdded(m_series->slices()); |
|
69 | 67 | } |
|
70 | 68 | |
|
71 | void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices) | |
|
69 | void PieChartItem::updateLayout() | |
|
72 | 70 | { |
|
73 | bool isEmpty = m_slices.isEmpty(); | |
|
71 | // find pie center coordinates | |
|
72 | m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->horizontalPosition())); | |
|
73 | m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->verticalPosition())); | |
|
74 | 74 | |
|
75 | // find maximum radius for pie | |
|
76 | m_pieRadius = m_rect.height() / 2; | |
|
77 | if (m_rect.width() < m_rect.height()) | |
|
78 | m_pieRadius = m_rect.width() / 2; | |
|
79 | ||
|
80 | // apply size factor | |
|
81 | m_pieRadius *= m_series->pieSize(); | |
|
82 | ||
|
83 | // set layouts for existing slice items | |
|
84 | foreach (QPieSlice* slice, m_series->slices()) { | |
|
85 | PieSliceItem *sliceItem = m_sliceItems.value(slice); | |
|
86 | if (sliceItem) { | |
|
87 | PieSliceData sliceData = updateSliceGeometry(slice); | |
|
88 | if (animator()) | |
|
89 | animator()->updateAnimation(this, sliceItem, sliceData); | |
|
90 | else | |
|
91 | sliceItem->setLayout(sliceData); | |
|
92 | } | |
|
93 | } | |
|
94 | ||
|
95 | update(); | |
|
96 | } | |
|
97 | ||
|
98 | void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices) | |
|
99 | { | |
|
75 | 100 | presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series)); |
|
76 | 101 | |
|
77 | foreach (QPieSlice *s, slices) { | |
|
78 | PieSliceItem* item = new PieSliceItem(this); | |
|
79 | m_slices.insert(s, item); | |
|
80 | connect(s, SIGNAL(changed()), this, SLOT(handleSliceChanged())); | |
|
81 | connect(item, SIGNAL(clicked(Qt::MouseButtons)), s, SIGNAL(clicked())); | |
|
82 | connect(item, SIGNAL(hovered(bool)), s, SIGNAL(hovered(bool))); | |
|
102 | bool startupAnimation = m_sliceItems.isEmpty(); | |
|
83 | 103 | |
|
84 | PieSliceData data = sliceData(s); | |
|
104 | foreach (QPieSlice *slice, slices) { | |
|
105 | PieSliceItem* sliceItem = new PieSliceItem(this); | |
|
106 | m_sliceItems.insert(slice, sliceItem); | |
|
107 | connect(slice, SIGNAL(changed()), this, SLOT(handleSliceChanged())); | |
|
108 | connect(sliceItem, SIGNAL(clicked(Qt::MouseButtons)), slice, SIGNAL(clicked())); | |
|
109 | connect(sliceItem, SIGNAL(hovered(bool)), slice, SIGNAL(hovered(bool))); | |
|
85 | 110 | |
|
111 | PieSliceData sliceData = updateSliceGeometry(slice); | |
|
86 | 112 | if (animator()) |
|
87 |
animator()->addAnimation(this, item, |
|
|
113 | animator()->addAnimation(this, sliceItem, sliceData, startupAnimation); | |
|
88 | 114 | else |
|
89 |
setLayout( |
|
|
115 | sliceItem->setLayout(sliceData); | |
|
90 | 116 | } |
|
91 | 117 | } |
|
92 | 118 | |
@@ -95,114 +121,40 void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices) | |||
|
95 | 121 | presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series)); |
|
96 | 122 | |
|
97 | 123 | foreach (QPieSlice *slice, slices) { |
|
98 | ||
|
99 | PieSliceItem *item = m_slices.value(slice); | |
|
100 | Q_ASSERT(item); | |
|
101 | m_slices.remove(slice); | |
|
124 | PieSliceItem *sliceItem = m_sliceItems.value(slice); | |
|
125 | Q_ASSERT(sliceItem); | |
|
126 | m_sliceItems.remove(slice); | |
|
102 | 127 | |
|
103 | 128 | if (animator()) |
|
104 | animator()->removeAnimation(this, item); // animator deletes the PieSliceItem | |
|
129 | animator()->removeAnimation(this, sliceItem); // animator deletes the PieSliceItem | |
|
105 | 130 | else |
|
106 | delete item; | |
|
131 | delete sliceItem; | |
|
107 | 132 | } |
|
108 | 133 | } |
|
109 | 134 | |
|
110 | void PieChartItem::handlePieLayoutChanged() | |
|
111 | { | |
|
112 | PieLayout layout = calculateLayout(); | |
|
113 | applyLayout(layout); | |
|
114 | update(); | |
|
115 | } | |
|
116 | ||
|
117 | 135 | void PieChartItem::handleSliceChanged() |
|
118 | 136 | { |
|
119 | 137 | QPieSlice* slice = qobject_cast<QPieSlice *>(sender()); |
|
120 | Q_ASSERT(m_slices.contains(slice)); | |
|
121 | PieSliceData data = sliceData(slice); | |
|
122 | updateLayout(m_slices.value(slice), data); | |
|
123 | update(); | |
|
124 | } | |
|
125 | ||
|
126 | void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal) | |
|
127 | { | |
|
128 | // TODO | |
|
129 | } | |
|
130 | ||
|
131 | void PieChartItem::handleGeometryChanged(const QRectF& rect) | |
|
132 | { | |
|
133 | prepareGeometryChange(); | |
|
134 | m_rect = rect; | |
|
135 | handlePieLayoutChanged(); | |
|
136 | } | |
|
137 | ||
|
138 | void PieChartItem::calculatePieLayout() | |
|
139 | { | |
|
140 | // find pie center coordinates | |
|
141 | m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->horizontalPosition())); | |
|
142 | m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->verticalPosition())); | |
|
138 | Q_ASSERT(m_sliceItems.contains(slice)); | |
|
143 | 139 | |
|
144 | // find maximum radius for pie | |
|
145 | m_pieRadius = m_rect.height() / 2; | |
|
146 | if (m_rect.width() < m_rect.height()) | |
|
147 | m_pieRadius = m_rect.width() / 2; | |
|
140 | PieSliceItem *sliceItem = m_sliceItems.value(slice); | |
|
141 | PieSliceData sliceData = updateSliceGeometry(slice); | |
|
142 | if (animator()) | |
|
143 | animator()->updateAnimation(this, sliceItem, sliceData); | |
|
144 | else | |
|
145 | sliceItem->setLayout(sliceData); | |
|
148 | 146 | |
|
149 | // apply size factor | |
|
150 | m_pieRadius *= m_series->pieSize(); | |
|
147 | update(); | |
|
151 | 148 | } |
|
152 | 149 | |
|
153 |
PieSliceData PieChartItem:: |
|
|
150 | PieSliceData PieChartItem::updateSliceGeometry(QPieSlice *slice) | |
|
154 | 151 | { |
|
155 | // TODO: This function is kid of useless now. Refactor. | |
|
156 | PieSliceData sliceData = PieSliceData::data(slice); | |
|
152 | PieSliceData &sliceData = PieSliceData::data(slice); | |
|
157 | 153 | sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice); |
|
158 | 154 | sliceData.m_radius = m_pieRadius; |
|
159 | 155 | return sliceData; |
|
160 | 156 | } |
|
161 | 157 | |
|
162 | PieLayout PieChartItem::calculateLayout() | |
|
163 | { | |
|
164 | calculatePieLayout(); | |
|
165 | PieLayout layout; | |
|
166 | foreach (QPieSlice* s, m_series->slices()) { | |
|
167 | if (m_slices.contains(s)) // calculate layout only for those slices that are already visible | |
|
168 | layout.insert(m_slices.value(s), sliceData(s)); | |
|
169 | } | |
|
170 | return layout; | |
|
171 | } | |
|
172 | ||
|
173 | void PieChartItem::applyLayout(const PieLayout &layout) | |
|
174 | { | |
|
175 | if (animator()) | |
|
176 | animator()->updateLayout(this, layout); | |
|
177 | else | |
|
178 | setLayout(layout); | |
|
179 | } | |
|
180 | ||
|
181 | void PieChartItem::updateLayout(PieSliceItem *sliceItem, const PieSliceData &sliceData) | |
|
182 | { | |
|
183 | if (animator()) | |
|
184 | animator()->updateLayout(this, sliceItem, sliceData); | |
|
185 | else | |
|
186 | setLayout(sliceItem, sliceData); | |
|
187 | } | |
|
188 | ||
|
189 | void PieChartItem::setLayout(const PieLayout &layout) | |
|
190 | { | |
|
191 | foreach (PieSliceItem *item, layout.keys()) { | |
|
192 | item->setSliceData(layout.value(item)); | |
|
193 | item->updateGeometry(); | |
|
194 | item->update(); | |
|
195 | } | |
|
196 | } | |
|
197 | ||
|
198 | void PieChartItem::setLayout(PieSliceItem *sliceItem, const PieSliceData &sliceData) | |
|
199 | { | |
|
200 | Q_ASSERT(sliceItem); | |
|
201 | sliceItem->setSliceData(sliceData); | |
|
202 | sliceItem->updateGeometry(); | |
|
203 | sliceItem->update(); | |
|
204 | } | |
|
205 | ||
|
206 | 158 | #include "moc_piechartitem_p.cpp" |
|
207 | 159 | |
|
208 | 160 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -30,42 +30,37 QTCOMMERCIALCHART_BEGIN_NAMESPACE | |||
|
30 | 30 | class QPieSlice; |
|
31 | 31 | class ChartPresenter; |
|
32 | 32 | |
|
33 | typedef QHash<PieSliceItem*, PieSliceData> PieLayout; | |
|
34 | ||
|
35 | 33 | class PieChartItem : public ChartItem |
|
36 | 34 | { |
|
37 | 35 | Q_OBJECT |
|
38 | 36 | |
|
39 | 37 | public: |
|
40 | // TODO: use a generic data class instead of x and y | |
|
41 | PieChartItem(QPieSeries *series, ChartPresenter *presenter); | |
|
38 | explicit PieChartItem(QPieSeries *series, ChartPresenter *presenter); | |
|
42 | 39 | ~PieChartItem(); |
|
43 | 40 | |
|
44 |
|
|
|
41 | // from QGraphicsItem | |
|
45 | 42 | QRectF boundingRect() const { return m_rect; } |
|
46 |
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) |
|
|
43 | void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {} | |
|
47 | 44 | |
|
48 | 45 | public Q_SLOTS: |
|
46 | // from Chart | |
|
47 | virtual void handleGeometryChanged(const QRectF &rect); | |
|
48 | // TODO: Do we have actual need for these at all? What is the use case for pie? | |
|
49 | //virtual void handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY); | |
|
50 | //virtual void rangeXChanged(qreal min, qreal max, int tickXCount); | |
|
51 | //virtual void rangeYChanged(qreal min, qreal max, int tickYCount); | |
|
52 | ||
|
49 | 53 | void initialize(); |
|
54 | void updateLayout(); | |
|
50 | 55 | void handleSlicesAdded(QList<QPieSlice*> slices); |
|
51 | 56 | void handleSlicesRemoved(QList<QPieSlice*> slices); |
|
52 | void handlePieLayoutChanged(); | |
|
53 | 57 | void handleSliceChanged(); |
|
54 | void handleDomainChanged(qreal, qreal, qreal, qreal); | |
|
55 | void handleGeometryChanged(const QRectF& rect); | |
|
56 | 58 | |
|
57 | public: | |
|
58 | void calculatePieLayout(); | |
|
59 | PieSliceData sliceData(QPieSlice *slice); | |
|
60 | PieLayout calculateLayout(); | |
|
61 | void applyLayout(const PieLayout &layout); | |
|
62 | void updateLayout(PieSliceItem *sliceItem, const PieSliceData &sliceData); | |
|
63 | void setLayout(const PieLayout &layout); | |
|
64 | void setLayout(PieSliceItem *sliceItem, const PieSliceData &sliceData); | |
|
59 | private: | |
|
60 | PieSliceData updateSliceGeometry(QPieSlice *slice); | |
|
65 | 61 | |
|
66 | 62 | private: |
|
67 | friend class PieSliceItem; | |
|
68 | QHash<QPieSlice*, PieSliceItem*> m_slices; | |
|
63 | QHash<QPieSlice*, PieSliceItem*> m_sliceItems; | |
|
69 | 64 | QPieSeries *m_series; |
|
70 | 65 | QRectF m_rect; |
|
71 | 66 | QPointF m_pieCenter; |
@@ -98,9 +98,11 void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event) | |||
|
98 | 98 | emit clicked(event->buttons()); |
|
99 | 99 | } |
|
100 | 100 | |
|
101 |
void PieSliceItem::set |
|
|
101 | void PieSliceItem::setLayout(const PieSliceData &sliceData) | |
|
102 | 102 | { |
|
103 | 103 | m_data = sliceData; |
|
104 | updateGeometry(); | |
|
105 | update(); | |
|
104 | 106 | } |
|
105 | 107 | |
|
106 | 108 | void PieSliceItem::updateGeometry() |
@@ -45,7 +45,7 public: | |||
|
45 | 45 | PieSliceItem(QGraphicsItem* parent = 0); |
|
46 | 46 | ~PieSliceItem(); |
|
47 | 47 | |
|
48 |
|
|
|
48 | // from QGraphicsItem | |
|
49 | 49 | QRectF boundingRect() const; |
|
50 | 50 | QPainterPath shape() const; |
|
51 | 51 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); |
@@ -53,14 +53,15 public: // from QGraphicsItem | |||
|
53 | 53 | void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); |
|
54 | 54 | void mousePressEvent(QGraphicsSceneMouseEvent *event); |
|
55 | 55 | |
|
56 | void setLayout(const PieSliceData &sliceData); | |
|
57 | static QPointF sliceCenter(QPointF point, qreal radius, QPieSlice *slice); | |
|
58 | ||
|
56 | 59 | Q_SIGNALS: |
|
57 | 60 | void clicked(Qt::MouseButtons buttons); |
|
58 | 61 | void hovered(bool state); |
|
59 | 62 | |
|
60 | public: | |
|
61 | void setSliceData(PieSliceData sliceData); | |
|
63 | private: | |
|
62 | 64 | void updateGeometry(); |
|
63 | static QPointF sliceCenter(QPointF point, qreal radius, QPieSlice *slice); | |
|
64 | 65 | QPainterPath slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF *armStart); |
|
65 | 66 | QPainterPath labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart); |
|
66 | 67 | QRectF labelTextRect(QFont font, QString text); |
General Comments 0
You need to be logged in to leave comments.
Login now