##// END OF EJS Templates
Add animations to pie. Works but has some visual issues when adding slices.
Jani Honkonen -
r618:249071e508d1
parent child
Show More
@@ -0,0 +1,94
1 #include "PieAnimation_p.h"
2 #include "piesliceanimation_p.h"
3 #include "piechartitem_p.h"
4 #include <QParallelAnimationGroup>
5 #include <QTimer>
6
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8
9 PieAnimation::PieAnimation(PieChartItem *item)
10 :ChartAnimation(item),
11 m_item(item)
12 {
13 }
14
15 PieAnimation::~PieAnimation()
16 {
17 }
18
19 void PieAnimation::setValues(QVector<PieSliceLayout>& newValues)
20 {
21 PieSliceAnimation *animation = 0;
22
23 foreach (PieSliceLayout endLayout, newValues) {
24 animation = m_animations.value(endLayout.m_data);
25 if (animation) {
26 // existing slice
27 animation->stop();
28 animation->updateValue(endLayout);
29 } else {
30 // new slice
31 animation = new PieSliceAnimation(m_item);
32 m_animations.insert(endLayout.m_data, animation);
33 PieSliceLayout startLayout = endLayout;
34 startLayout.m_radius = 0;
35 //startLayout.m_startAngle = 0;
36 //startLayout.m_angleSpan = 0;
37 animation->setValue(startLayout, endLayout);
38 }
39 animation->setDuration(1000);
40 animation->setEasingCurve(QEasingCurve::OutQuart);
41 QTimer::singleShot(0, animation, SLOT(start())); // TODO: use sequential animation?
42 }
43
44 foreach (QPieSlice *s, m_animations.keys()) {
45 bool isFound = false;
46 foreach (PieSliceLayout layout, newValues) {
47 if (s == layout.m_data)
48 isFound = true;
49 }
50 if (!isFound) {
51 // slice has been deleted
52 animation = m_animations.value(s);
53 animation->stop();
54 PieSliceLayout endLayout = m_animations.value(s)->currentSliceValue();
55 endLayout.m_radius = 0;
56 // TODO: find the actual angle where this slice disappears
57 endLayout.m_startAngle = endLayout.m_startAngle + endLayout.m_angleSpan;
58 endLayout.m_angleSpan = 0;
59 animation->updateValue(endLayout);
60 animation->setDuration(1000);
61 animation->setEasingCurve(QEasingCurve::OutQuart);
62 connect(animation, SIGNAL(finished()), this, SLOT(destroySliceAnimationComplete()));
63 QTimer::singleShot(0, animation, SLOT(start()));
64 }
65 }
66 }
67
68 void PieAnimation::updateValue(PieSliceLayout& endLayout)
69 {
70 PieSliceAnimation *animation = m_animations.value(endLayout.m_data);
71 Q_ASSERT(animation);
72 animation->stop();
73 animation->updateValue(endLayout);
74 animation->setDuration(1000);
75 animation->setEasingCurve(QEasingCurve::OutQuart);
76 QTimer::singleShot(0, animation, SLOT(start()));
77 }
78
79 void PieAnimation::updateCurrentValue(const QVariant &)
80 {
81 // nothing to do...
82 }
83
84 void PieAnimation::destroySliceAnimationComplete()
85 {
86 PieSliceAnimation *animation = static_cast<PieSliceAnimation*>(sender());
87 QPieSlice *slice = m_animations.key(animation);
88 m_item->destroySlice(slice);
89 delete m_animations.take(slice);
90 }
91
92 #include "moc_pieanimation_p.cpp"
93
94 QTCOMMERCIALCHART_END_NAMESPACE
@@ -0,0 +1,35
1 #ifndef PIEANIMATION_P_H_
2 #define PIEANIMATION_P_H_
3
4 #include "chartanimation_p.h"
5 #include "piechartitem_p.h"
6 #include "piesliceanimation_p.h"
7
8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9
10 class PieChartItem;
11
12 class PieAnimation : public ChartAnimation
13 {
14 Q_OBJECT
15
16 public:
17 PieAnimation(PieChartItem *item);
18 ~PieAnimation();
19 void setValues(QVector<PieSliceLayout>& newValues);
20 void updateValue(PieSliceLayout& newValue);
21
22 public: // from QVariantAnimation
23 void updateCurrentValue(const QVariant &value);
24
25 public Q_SLOTS:
26 void destroySliceAnimationComplete();
27
28 private:
29 PieChartItem *m_item;
30 QHash<QPieSlice*, PieSliceAnimation*> m_animations;
31 };
32
33 QTCOMMERCIALCHART_END_NAMESPACE
34
35 #endif
@@ -0,0 +1,77
1 #include "PieSliceAnimation_p.h"
2 #include "piechartitem_p.h"
3 #include "qpieslice.h"
4
5 Q_DECLARE_METATYPE(QtCommercialChart::PieSliceLayout)
6
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8
9 qreal linearPos(qreal start, qreal end, qreal pos)
10 {
11 return start + ((end - start) * pos);
12 }
13
14 QPointF linearPos(QPointF start, QPointF end, qreal pos)
15 {
16 qreal x = linearPos(start.x(), end.x(), pos);
17 qreal y = linearPos(start.y(), end.y(), pos);
18 return QPointF(x, y);
19 }
20
21 PieSliceAnimation::PieSliceAnimation(PieChartItem *item)
22 :QVariantAnimation(item),
23 m_item(item)
24 {
25 }
26
27 PieSliceAnimation::~PieSliceAnimation()
28 {
29 }
30
31 void PieSliceAnimation::setValue(PieSliceLayout& startValue, PieSliceLayout& endValue)
32 {
33 if (state() != QAbstractAnimation::Stopped)
34 stop();
35
36 setKeyValueAt(0.0, qVariantFromValue(startValue));
37 setKeyValueAt(1.0, qVariantFromValue(endValue));
38 }
39
40 void PieSliceAnimation::updateValue(PieSliceLayout& endValue)
41 {
42 if (state() != QAbstractAnimation::Stopped)
43 stop();
44
45 //qDebug() << "PieSliceAnimation::updateValue()" << endValue.m_data->label() << currentSliceValue().m_startAngle << endValue.m_startAngle;
46
47 setKeyValueAt(0.0, qVariantFromValue(currentSliceValue()));
48 setKeyValueAt(1.0, qVariantFromValue(endValue));
49 }
50
51 PieSliceLayout PieSliceAnimation::currentSliceValue()
52 {
53 return qVariantValue<PieSliceLayout>(currentValue());
54 }
55
56 QVariant PieSliceAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const
57 {
58 PieSliceLayout startValue = qVariantValue<PieSliceLayout>(start);
59 PieSliceLayout endValue = qVariantValue<PieSliceLayout>(end);
60
61 PieSliceLayout result;
62 result = endValue;
63 result.m_center = linearPos(startValue.m_center, endValue.m_center, progress);
64 result.m_radius = linearPos(startValue.m_radius, endValue.m_radius, progress);
65 result.m_startAngle = linearPos(startValue.m_startAngle, endValue.m_startAngle, progress);
66 result.m_angleSpan = linearPos(startValue.m_angleSpan, endValue.m_angleSpan, progress);
67
68 return qVariantFromValue(result);
69 }
70
71 void PieSliceAnimation::updateCurrentValue(const QVariant &value)
72 {
73 if (state() != QAbstractAnimation::Stopped) //workaround
74 m_item->setLayout(qVariantValue<PieSliceLayout>(value));
75 }
76
77 QTCOMMERCIALCHART_END_NAMESPACE
@@ -0,0 +1,30
1 #ifndef PIESLICEANIMATION_P_H_
2 #define PIESLICEANIMATION_P_H_
3
4 #include "piechartitem_p.h"
5 #include <QVariantAnimation>
6
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8
9 class PieChartItem;
10
11 class PieSliceAnimation : public QVariantAnimation
12 {
13 public:
14 PieSliceAnimation(PieChartItem *item);
15 ~PieSliceAnimation();
16 void setValue(PieSliceLayout& startValue, PieSliceLayout& endValue);
17 void updateValue(PieSliceLayout& endValue);
18 PieSliceLayout currentSliceValue();
19
20 protected:
21 QVariant interpolated(const QVariant &start, const QVariant &end, qreal progress) const;
22 void updateCurrentValue(const QVariant &value);
23
24 private:
25 PieChartItem *m_item;
26 };
27
28 QTCOMMERCIALCHART_END_NAMESPACE
29
30 #endif
@@ -287,6 +287,7 public:
287 // create chart
287 // create chart
288 m_chartView = new QChartView();
288 m_chartView = new QChartView();
289 m_chartView->setChartTitle("Piechart customization");
289 m_chartView->setChartTitle("Piechart customization");
290 m_chartView->setAnimationOptions(QChart::AllAnimations);
290
291
291 // create series
292 // create series
292 m_series = new QPieSeries();
293 m_series = new QPieSeries();
@@ -349,12 +350,15 public:
349 m_endAngle->setValue(m_series->pieEndAngle());
350 m_endAngle->setValue(m_series->pieEndAngle());
350 m_endAngle->setSingleStep(1);
351 m_endAngle->setSingleStep(1);
351
352
353 QPushButton *addSlice = new QPushButton("Add slice");
354
352 QFormLayout* seriesSettingsLayout = new QFormLayout();
355 QFormLayout* seriesSettingsLayout = new QFormLayout();
353 seriesSettingsLayout->addRow("Horizontal position", m_hPosition);
356 seriesSettingsLayout->addRow("Horizontal position", m_hPosition);
354 seriesSettingsLayout->addRow("Vertical position", m_vPosition);
357 seriesSettingsLayout->addRow("Vertical position", m_vPosition);
355 seriesSettingsLayout->addRow("Size factor", m_sizeFactor);
358 seriesSettingsLayout->addRow("Size factor", m_sizeFactor);
356 seriesSettingsLayout->addRow("Start angle", m_startAngle);
359 seriesSettingsLayout->addRow("Start angle", m_startAngle);
357 seriesSettingsLayout->addRow("End angle", m_endAngle);
360 seriesSettingsLayout->addRow("End angle", m_endAngle);
361 seriesSettingsLayout->addRow(addSlice);
358 QGroupBox* seriesSettings = new QGroupBox("Series");
362 QGroupBox* seriesSettings = new QGroupBox("Series");
359 seriesSettings->setLayout(seriesSettingsLayout);
363 seriesSettings->setLayout(seriesSettingsLayout);
360
364
@@ -363,6 +367,7 public:
363 connect(m_sizeFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
367 connect(m_sizeFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
364 connect(m_startAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
368 connect(m_startAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
365 connect(m_endAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
369 connect(m_endAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
370 connect(addSlice, SIGNAL(clicked()), this, SLOT(addSlice()));
366
371
367 // slice settings
372 // slice settings
368 m_sliceName = new QLabel("<click a slice>");
373 m_sliceName = new QLabel("<click a slice>");
@@ -381,6 +386,7 public:
381 m_font = new QPushButton();
386 m_font = new QPushButton();
382 m_labelArmPen = new QPushButton();
387 m_labelArmPen = new QPushButton();
383 m_labelArmPenTool = new PenTool("Label arm pen", this);
388 m_labelArmPenTool = new PenTool("Label arm pen", this);
389 QPushButton *removeSlice = new QPushButton("Remove slice");
384
390
385 QFormLayout* sliceSettingsLayout = new QFormLayout();
391 QFormLayout* sliceSettingsLayout = new QFormLayout();
386 sliceSettingsLayout->addRow("Selected", m_sliceName);
392 sliceSettingsLayout->addRow("Selected", m_sliceName);
@@ -393,6 +399,7 public:
393 sliceSettingsLayout->addRow("Label arm length", m_sliceLabelArmFactor);
399 sliceSettingsLayout->addRow("Label arm length", m_sliceLabelArmFactor);
394 sliceSettingsLayout->addRow("Exploded", m_sliceExploded);
400 sliceSettingsLayout->addRow("Exploded", m_sliceExploded);
395 sliceSettingsLayout->addRow("Explode distance", m_sliceExplodedFactor);
401 sliceSettingsLayout->addRow("Explode distance", m_sliceExplodedFactor);
402 sliceSettingsLayout->addRow(removeSlice);
396 QGroupBox* sliceSettings = new QGroupBox("Slice");
403 QGroupBox* sliceSettings = new QGroupBox("Slice");
397 sliceSettings->setLayout(sliceSettingsLayout);
404 sliceSettings->setLayout(sliceSettingsLayout);
398
405
@@ -409,6 +416,7 public:
409 connect(m_sliceLabelArmFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
416 connect(m_sliceLabelArmFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
410 connect(m_sliceExploded, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
417 connect(m_sliceExploded, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
411 connect(m_sliceExplodedFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
418 connect(m_sliceExplodedFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
419 connect(removeSlice, SIGNAL(clicked()), this, SLOT(removeSlice()));
412
420
413 // create main layout
421 // create main layout
414 QVBoxLayout *settingsLayout = new QVBoxLayout();
422 QVBoxLayout *settingsLayout = new QVBoxLayout();
@@ -513,6 +521,20 public Q_SLOTS:
513 m_font->setText(dialog.currentFont().toString());
521 m_font->setText(dialog.currentFont().toString());
514 }
522 }
515
523
524 void addSlice()
525 {
526 *m_series << new CustomSlice(10.0, "Slice " + QString::number(m_series->count()));
527 }
528
529 void removeSlice()
530 {
531 if (!m_slice)
532 return;
533
534 m_series->remove(m_slice);
535 m_slice = 0;
536 }
537
516 private:
538 private:
517 QComboBox *m_themeComboBox;
539 QComboBox *m_themeComboBox;
518 QCheckBox *m_aaCheckBox;
540 QCheckBox *m_aaCheckBox;
@@ -4,10 +4,14 DEPENDPATH += $$PWD
4 SOURCES += \
4 SOURCES += \
5 $$PWD/axisanimation.cpp \
5 $$PWD/axisanimation.cpp \
6 $$PWD/chartanimator.cpp \
6 $$PWD/chartanimator.cpp \
7 $$PWD/xyanimation.cpp
7 $$PWD/xyanimation.cpp \
8 $$PWD/pieanimation.cpp \
9 $$PWD/piesliceanimation.cpp
8
10
9 PRIVATE_HEADERS += \
11 PRIVATE_HEADERS += \
10 $$PWD/axisanimation_p.h \
12 $$PWD/axisanimation_p.h \
11 $$PWD/chartanimator_p.h \
13 $$PWD/chartanimator_p.h \
12 $$PWD/chartanimation_p.h \
14 $$PWD/chartanimation_p.h \
13 $$PWD/xyanimation_p.h No newline at end of file
15 $$PWD/xyanimation_p.h \
16 $$PWD/pieanimation_p.h \
17 $$PWD/piesliceanimation_p.h
@@ -2,6 +2,7
2 #include "axisanimation_p.h"
2 #include "axisanimation_p.h"
3 #include "xyanimation_p.h"
3 #include "xyanimation_p.h"
4 #include "xychartitem_p.h"
4 #include "xychartitem_p.h"
5 #include "pieanimation_p.h"
5 #include "areachartitem_p.h"
6 #include "areachartitem_p.h"
6 #include <QTimer>
7 #include <QTimer>
7
8
@@ -44,6 +45,18 void ChartAnimator::addAnimation(XYChartItem* item)
44 item->setAnimator(this);
45 item->setAnimator(this);
45 }
46 }
46
47
48 void ChartAnimator::addAnimation(PieChartItem* item)
49 {
50 ChartAnimation* animation = m_animations.value(item);
51
52 if(!animation) {
53 animation = new PieAnimation(item);
54 m_animations.insert(item,animation);
55 }
56
57 item->setAnimator(this);
58 }
59
47 void ChartAnimator::removeAnimation(ChartItem* item)
60 void ChartAnimator::removeAnimation(ChartItem* item)
48 {
61 {
49 item->setAnimator(0);
62 item->setAnimator(0);
@@ -171,6 +184,20 void ChartAnimator::updateLayout(XYChartItem* item, QVector<QPointF>& newPoints)
171 QTimer::singleShot(0,animation,SLOT(start()));
184 QTimer::singleShot(0,animation,SLOT(start()));
172 }
185 }
173
186
187 void ChartAnimator::applyLayout(PieChartItem* item, QVector<PieSliceLayout> &layout)
188 {
189 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
190 Q_ASSERT(animation);
191 animation->setValues(layout);
192 }
193
194 void ChartAnimator::updateLayout(PieChartItem* item, PieSliceLayout &layout)
195 {
196 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
197 Q_ASSERT(animation);
198 animation->updateValue(layout);
199 }
200
174 void ChartAnimator::setState(State state,const QPointF& point)
201 void ChartAnimator::setState(State state,const QPointF& point)
175 {
202 {
176 m_state=state;
203 m_state=state;
@@ -2,6 +2,7
2 #define CHARTANIMATOR_P_H_
2 #define CHARTANIMATOR_P_H_
3 #include "qchartglobal.h"
3 #include "qchartglobal.h"
4 #include "chartanimation_p.h"
4 #include "chartanimation_p.h"
5 #include "piechartitem_p.h"
5 #include <QPointF>
6 #include <QPointF>
6
7
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
@@ -22,6 +23,7 public:
22
23
23 void addAnimation(AxisItem* item);
24 void addAnimation(AxisItem* item);
24 void addAnimation(XYChartItem* item);
25 void addAnimation(XYChartItem* item);
26 void addAnimation(PieChartItem* item);
25
27
26 void removeAnimation(ChartItem* item);
28 void removeAnimation(ChartItem* item);
27
29
@@ -30,6 +32,9 public:
30 void updateLayout(XYChartItem* item, QVector<QPointF>& layout);
32 void updateLayout(XYChartItem* item, QVector<QPointF>& layout);
31 void applyLayout(AxisItem* item, QVector<qreal>& layout);
33 void applyLayout(AxisItem* item, QVector<qreal>& layout);
32
34
35 void applyLayout(PieChartItem* item, QVector<PieSliceLayout> &layout);
36 void updateLayout(PieChartItem* item, PieSliceLayout &layout);
37
33 void setState(State state,const QPointF& point = QPointF());
38 void setState(State state,const QPointF& point = QPointF());
34
39
35 private:
40 private:
@@ -224,7 +224,7 void ChartPresenter::handleSeriesAdded(QSeries* series,Domain* domain)
224 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
224 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
225 PieChartItem* pie = new PieChartItem(m_chart, pieSeries);
225 PieChartItem* pie = new PieChartItem(m_chart, pieSeries);
226 if(m_options.testFlag(QChart::SeriesAnimations)) {
226 if(m_options.testFlag(QChart::SeriesAnimations)) {
227 // m_animator->addAnimation(pie);
227 m_animator->addAnimation(pie);
228 }
228 }
229 m_chartTheme->decorate(pieSeries, m_dataset->seriesIndex(series));
229 m_chartTheme->decorate(pieSeries, m_dataset->seriesIndex(series));
230 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),pie,SLOT(handleGeometryChanged(const QRectF&)));
230 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),pie,SLOT(handleGeometryChanged(const QRectF&)));
@@ -3,6 +3,7
3 #include "qpieslice.h"
3 #include "qpieslice.h"
4 #include "qpieseries.h"
4 #include "qpieseries.h"
5 #include "chartpresenter_p.h"
5 #include "chartpresenter_p.h"
6 #include "chartanimator_p.h"
6 #include <QDebug>
7 #include <QDebug>
7 #include <QPainter>
8 #include <QPainter>
8
9
@@ -36,16 +37,24 void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QW
36
37
37 void PieChartItem::handleSeriesChanged()
38 void PieChartItem::handleSeriesChanged()
38 {
39 {
39 QVector<PieSliceLayout> sliceLayout = calculateLayout();
40 QVector<PieSliceLayout> layout = calculateLayout();
40 applyLayout(sliceLayout);
41 applyLayout(layout);
41 update();
42 update();
42 }
43 }
43
44
44 void PieChartItem::handleSliceChanged()
45 void PieChartItem::handleSliceChanged()
45 {
46 {
46 // TODO: optimize don't need to handle all slices
47 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
47 QVector<PieSliceLayout> sliceLayout = calculateLayout();
48 Q_ASSERT(m_slices.contains(slice));
48 applyLayout(sliceLayout);
49
50 //qDebug() << "PieChartItem::handleSliceChanged" << slice->label();
51
52 // TODO: Optimize. No need to calculate everything.
53 QVector<PieSliceLayout> layout = calculateLayout();
54 foreach (PieSliceLayout sl, layout) {
55 if (sl.m_data == slice)
56 updateLayout(sl);
57 }
49 update();
58 update();
50 }
59 }
51
60
@@ -93,15 +102,23 QVector<PieSliceLayout> PieChartItem::calculateLayout()
93 return layout;
102 return layout;
94 }
103 }
95
104
96 void PieChartItem::applyLayout(const QVector<PieSliceLayout> &layout)
105 void PieChartItem::applyLayout(QVector<PieSliceLayout> &layout)
97 {
106 {
98 //if(m_animator)
107 if (m_animator)
99 // m_animator->applyLayout(this,points);
108 m_animator->applyLayout(this, layout);
100 //else
109 else
101 setLayout(layout);
110 setLayout(layout);
102 }
111 }
103
112
104 void PieChartItem::setLayout(const QVector<PieSliceLayout> &layout)
113 void PieChartItem::updateLayout(PieSliceLayout &layout)
114 {
115 if (m_animator)
116 m_animator->updateLayout(this, layout);
117 else
118 setLayout(layout);
119 }
120
121 void PieChartItem::setLayout(QVector<PieSliceLayout> &layout)
105 {
122 {
106 foreach (PieSliceLayout l, layout) {
123 foreach (PieSliceLayout l, layout) {
107
124
@@ -135,8 +152,32 void PieChartItem::setLayout(const QVector<PieSliceLayout> &layout)
135 }
152 }
136
153
137 if (!found)
154 if (!found)
138 delete m_slices.take(s);
155 destroySlice(s);
156 }
157 }
158
159 void PieChartItem::setLayout(PieSliceLayout &layout)
160 {
161 // find slice
162 PieSlice *slice = m_slices.value(layout.m_data);
163 if (!slice) {
164 slice = new PieSlice(this);
165 m_slices.insert(layout.m_data, slice);
166 connect(layout.m_data, SIGNAL(changed()), this, SLOT(handleSliceChanged()));
167 connect(slice, SIGNAL(clicked()), layout.m_data, SIGNAL(clicked()));
168 connect(slice, SIGNAL(hoverEnter()), layout.m_data, SIGNAL(hoverEnter()));
169 connect(slice, SIGNAL(hoverLeave()), layout.m_data, SIGNAL(hoverLeave()));
139 }
170 }
171 slice->setLayout(layout);
172 if (m_series->m_slices.contains(layout.m_data)) // Slice has been deleted if not found. Animations ongoing...
173 slice->updateData(layout.m_data);
174 slice->updateGeometry();
175 slice->update();
176 }
177
178 void PieChartItem::destroySlice(QPieSlice *slice)
179 {
180 delete m_slices.take(slice);
140 }
181 }
141
182
142 #include "moc_piechartitem_p.cpp"
183 #include "moc_piechartitem_p.cpp"
@@ -28,10 +28,13 public Q_SLOTS:
28 void handleDomainChanged(qreal, qreal, qreal, qreal);
28 void handleDomainChanged(qreal, qreal, qreal, qreal);
29 void handleGeometryChanged(const QRectF& rect);
29 void handleGeometryChanged(const QRectF& rect);
30
30
31 private:
31 public:
32 QVector<PieSliceLayout> calculateLayout();
32 QVector<PieSliceLayout> calculateLayout();
33 void applyLayout(const QVector<PieSliceLayout> &layout);
33 void applyLayout(QVector<PieSliceLayout> &layout);
34 void setLayout(const QVector<PieSliceLayout> &layout);
34 void updateLayout(PieSliceLayout &layout);
35 void setLayout(QVector<PieSliceLayout> &layout);
36 void setLayout(PieSliceLayout &layout);
37 void destroySlice(QPieSlice *slice);
35
38
36 private:
39 private:
37 friend class PieSlice;
40 friend class PieSlice;
@@ -22,8 +22,6 QPointF offset(qreal angle, qreal length)
22
22
23 PieSlice::PieSlice(QGraphicsItem* parent)
23 PieSlice::PieSlice(QGraphicsItem* parent)
24 :QGraphicsObject(parent),
24 :QGraphicsObject(parent),
25 m_startAngle(0),
26 m_angleSpan(0),
27 m_isExploded(false),
25 m_isExploded(false),
28 m_explodeDistanceFactor(0),
26 m_explodeDistanceFactor(0),
29 m_labelVisible(false),
27 m_labelVisible(false),
@@ -41,7 +39,7 PieSlice::~PieSlice()
41
39
42 QRectF PieSlice::boundingRect() const
40 QRectF PieSlice::boundingRect() const
43 {
41 {
44 return m_slicePath.boundingRect();
42 return m_slicePath.boundingRect().united(m_labelTextRect);
45 }
43 }
46
44
47 QPainterPath PieSlice::shape() const
45 QPainterPath PieSlice::shape() const
@@ -90,7 +88,6 void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/)
90 void PieSlice::setLayout(PieSliceLayout layout)
88 void PieSlice::setLayout(PieSliceLayout layout)
91 {
89 {
92 m_layout = layout;
90 m_layout = layout;
93 updateData(layout.m_data);
94 }
91 }
95
92
96 void PieSlice::updateGeometry()
93 void PieSlice::updateGeometry()
@@ -103,7 +100,7 void PieSlice::updateGeometry()
103 // update slice path
100 // update slice path
104 qreal centerAngle;
101 qreal centerAngle;
105 QPointF armStart;
102 QPointF armStart;
106 m_slicePath = slicePath(m_layout.m_center, m_layout.m_radius, m_startAngle, m_angleSpan, &centerAngle, &armStart);
103 m_slicePath = slicePath(m_layout.m_center, m_layout.m_radius, m_layout.m_startAngle, m_layout.m_angleSpan, &centerAngle, &armStart);
107
104
108 // update text rect
105 // update text rect
109 m_labelTextRect = labelTextRect(m_labelFont, m_labelText);
106 m_labelTextRect = labelTextRect(m_labelFont, m_labelText);
@@ -122,8 +119,6 void PieSlice::updateData(const QPieSlice* sliceData)
122 {
119 {
123 // TODO: compare what has changes to avoid unneccesary geometry updates
120 // TODO: compare what has changes to avoid unneccesary geometry updates
124
121
125 m_startAngle = sliceData->startAngle();
126 m_angleSpan = sliceData->m_angleSpan;
127 m_isExploded = sliceData->isExploded();
122 m_isExploded = sliceData->isExploded();
128 m_explodeDistanceFactor = sliceData->explodeDistanceFactor();
123 m_explodeDistanceFactor = sliceData->explodeDistanceFactor();
129 m_slicePen = sliceData->slicePen();
124 m_slicePen = sliceData->slicePen();
@@ -19,7 +19,7 class QPieSlice;
19 class PieSliceLayout
19 class PieSliceLayout
20 {
20 {
21 public:
21 public:
22 QPieSlice* m_data;
22 QPieSlice* m_data; // TODO: get rid of this
23 QPointF m_center;
23 QPointF m_center;
24 qreal m_radius;
24 qreal m_radius;
25 qreal m_startAngle;
25 qreal m_startAngle;
@@ -60,8 +60,6 private:
60 PieSliceLayout m_layout;
60 PieSliceLayout m_layout;
61
61
62 QPainterPath m_slicePath;
62 QPainterPath m_slicePath;
63 qreal m_startAngle;
64 qreal m_angleSpan;
65 bool m_isExploded;
63 bool m_isExploded;
66 qreal m_explodeDistanceFactor;
64 qreal m_explodeDistanceFactor;
67 bool m_labelVisible;
65 bool m_labelVisible;
@@ -511,6 +511,8 void QPieSeries::updateDerivativeData()
511 foreach (QPieSlice* s, m_slices)
511 foreach (QPieSlice* s, m_slices)
512 m_total += s->value();
512 m_total += s->value();
513
513
514 // TODO: emit totalChanged?
515
514 // we must have some values
516 // we must have some values
515 if (m_total == 0) {
517 if (m_total == 0) {
516 qDebug() << "QPieSeries::updateDerivativeData() total == 0";
518 qDebug() << "QPieSeries::updateDerivativeData() total == 0";
@@ -520,31 +522,35 void QPieSeries::updateDerivativeData()
520 // update slice attributes
522 // update slice attributes
521 qreal sliceAngle = m_pieStartAngle;
523 qreal sliceAngle = m_pieStartAngle;
522 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
524 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
525 QVector<QPieSlice*> changed;
523 foreach (QPieSlice* s, m_slices) {
526 foreach (QPieSlice* s, m_slices) {
524
527
525 bool changed = false;
528 bool isChanged = false;
526
529
527 qreal percentage = s->value() / m_total;
530 qreal percentage = s->value() / m_total;
528 if (s->m_percentage != percentage) {
531 if (s->m_percentage != percentage) {
529 s->m_percentage = percentage;
532 s->m_percentage = percentage;
530 changed = true;
533 isChanged = true;
531 }
534 }
532
535
533 qreal sliceSpan = pieSpan * percentage;
536 qreal sliceSpan = pieSpan * percentage;
534 if (s->m_angleSpan != sliceSpan) {
537 if (s->m_angleSpan != sliceSpan) {
535 s->m_angleSpan = sliceSpan;
538 s->m_angleSpan = sliceSpan;
536 changed = true;
539 isChanged = true;
537 }
540 }
538
541
539 if (s->m_startAngle != sliceAngle) {
542 if (s->m_startAngle != sliceAngle) {
540 s->m_startAngle = sliceAngle;
543 s->m_startAngle = sliceAngle;
541 changed = true;
544 isChanged = true;
542 }
545 }
543 sliceAngle += sliceSpan;
546 sliceAngle += sliceSpan;
544
547
545 if (changed)
548 if (isChanged)
546 emit s->changed();
549 changed << s;
547 }
550 }
551
552 foreach (QPieSlice* s, changed)
553 emit s->changed();
548 }
554 }
549
555
550 bool QPieSeries::setModel(QAbstractItemModel* model)
556 bool QPieSeries::setModel(QAbstractItemModel* model)
@@ -124,6 +124,7 private:
124 // TODO: use PIML
124 // TODO: use PIML
125 friend class PieChartItem;
125 friend class PieChartItem;
126 friend class PieSlice;
126 friend class PieSlice;
127 friend class QPieSlice;
127
128
128 QList<QPieSlice*> m_slices;
129 QList<QPieSlice*> m_slices;
129 qreal m_pieRelativeHorPos;
130 qreal m_pieRelativeHorPos;
@@ -1,4 +1,5
1 #include "qpieslice.h"
1 #include "qpieslice.h"
2 #include "qpieseries.h"
2
3
3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4
5
@@ -266,7 +267,12 void QPieSlice::setValue(qreal value)
266 {
267 {
267 if (m_value != value) {
268 if (m_value != value) {
268 m_value = value;
269 m_value = value;
269 emit changed();
270
271 QPieSeries *series = qobject_cast<QPieSeries*>(parent());
272 if (series)
273 series->updateDerivativeData(); // will emit changed()
274 else
275 emit changed();
270 }
276 }
271 }
277 }
272
278
@@ -8,6 +8,7
8 #include <QFont>
8 #include <QFont>
9
9
10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 class QPieSeries;
11
12
12 class QTCOMMERCIALCHART_EXPORT QPieSlice : public QObject
13 class QTCOMMERCIALCHART_EXPORT QPieSlice : public QObject
13 {
14 {
@@ -29,8 +30,6 public:
29 bool isLabelVisible() const;
30 bool isLabelVisible() const;
30 void setExploded(bool exploded);
31 void setExploded(bool exploded);
31 bool isExploded() const;
32 bool isExploded() const;
32 void setExplodeDistanceFactor(qreal factor);
33 qreal explodeDistanceFactor() const;
34
33
35 // generated data
34 // generated data
36 qreal percentage() const;
35 qreal percentage() const;
@@ -48,10 +47,8 public:
48 QFont labelFont() const;
47 QFont labelFont() const;
49 void setLabelArmLengthFactor(qreal factor);
48 void setLabelArmLengthFactor(qreal factor);
50 qreal labelArmLengthFactor() const;
49 qreal labelArmLengthFactor() const;
51
50 void setExplodeDistanceFactor(qreal factor);
52 // TODO: label position in general
51 qreal explodeDistanceFactor() const;
53 // setLabelFlags(inside|outside|labelArmOn|labelArmOff|???)
54 // setLabelOrientation(horizontal|vertical|same as slice center angle|???)
55
52
56 Q_SIGNALS:
53 Q_SIGNALS:
57 void clicked();
54 void clicked();
General Comments 0
You need to be logged in to leave comments. Login now