##// 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
@@ -1,560 +1,582
1 #include <QtGui/QApplication>
1 #include <QtGui/QApplication>
2 #include <QMainWindow>
2 #include <QMainWindow>
3 #include <qchartglobal.h>
3 #include <qchartglobal.h>
4 #include <qchartview.h>
4 #include <qchartview.h>
5 #include <qpieseries.h>
5 #include <qpieseries.h>
6 #include <qpieslice.h>
6 #include <qpieslice.h>
7 #include <QGridLayout>
7 #include <QGridLayout>
8 #include <QFormLayout>
8 #include <QFormLayout>
9 #include <QComboBox>
9 #include <QComboBox>
10 #include <QSpinBox>
10 #include <QSpinBox>
11 #include <QCheckBox>
11 #include <QCheckBox>
12 #include <QGroupBox>
12 #include <QGroupBox>
13 #include <QLabel>
13 #include <QLabel>
14 #include <QPushButton>
14 #include <QPushButton>
15 #include <QColorDialog>
15 #include <QColorDialog>
16 #include <QFontDialog>
16 #include <QFontDialog>
17
17
18 QTCOMMERCIALCHART_USE_NAMESPACE
18 QTCOMMERCIALCHART_USE_NAMESPACE
19
19
20 class PenTool : public QWidget
20 class PenTool : public QWidget
21 {
21 {
22 Q_OBJECT
22 Q_OBJECT
23
23
24 public:
24 public:
25 explicit PenTool(QString title, QWidget *parent = 0)
25 explicit PenTool(QString title, QWidget *parent = 0)
26 :QWidget(parent)
26 :QWidget(parent)
27 {
27 {
28 setWindowTitle(title);
28 setWindowTitle(title);
29 setWindowFlags(Qt::Tool);
29 setWindowFlags(Qt::Tool);
30
30
31 m_colorButton = new QPushButton();
31 m_colorButton = new QPushButton();
32
32
33 m_widthSpinBox = new QDoubleSpinBox();
33 m_widthSpinBox = new QDoubleSpinBox();
34
34
35 m_styleCombo = new QComboBox();
35 m_styleCombo = new QComboBox();
36 m_styleCombo->addItem("NoPen");
36 m_styleCombo->addItem("NoPen");
37 m_styleCombo->addItem("SolidLine");
37 m_styleCombo->addItem("SolidLine");
38 m_styleCombo->addItem("DashLine");
38 m_styleCombo->addItem("DashLine");
39 m_styleCombo->addItem("DotLine");
39 m_styleCombo->addItem("DotLine");
40 m_styleCombo->addItem("DashDotLine");
40 m_styleCombo->addItem("DashDotLine");
41 m_styleCombo->addItem("DashDotDotLine");
41 m_styleCombo->addItem("DashDotDotLine");
42
42
43 m_capStyleCombo = new QComboBox();
43 m_capStyleCombo = new QComboBox();
44 m_capStyleCombo->addItem("FlatCap", Qt::FlatCap);
44 m_capStyleCombo->addItem("FlatCap", Qt::FlatCap);
45 m_capStyleCombo->addItem("SquareCap", Qt::SquareCap);
45 m_capStyleCombo->addItem("SquareCap", Qt::SquareCap);
46 m_capStyleCombo->addItem("RoundCap", Qt::RoundCap);
46 m_capStyleCombo->addItem("RoundCap", Qt::RoundCap);
47
47
48 m_joinStyleCombo = new QComboBox();
48 m_joinStyleCombo = new QComboBox();
49 m_joinStyleCombo->addItem("MiterJoin", Qt::MiterJoin);
49 m_joinStyleCombo->addItem("MiterJoin", Qt::MiterJoin);
50 m_joinStyleCombo->addItem("BevelJoin", Qt::BevelJoin);
50 m_joinStyleCombo->addItem("BevelJoin", Qt::BevelJoin);
51 m_joinStyleCombo->addItem("RoundJoin", Qt::RoundJoin);
51 m_joinStyleCombo->addItem("RoundJoin", Qt::RoundJoin);
52 m_joinStyleCombo->addItem("SvgMiterJoin", Qt::SvgMiterJoin);
52 m_joinStyleCombo->addItem("SvgMiterJoin", Qt::SvgMiterJoin);
53
53
54 QFormLayout *layout = new QFormLayout();
54 QFormLayout *layout = new QFormLayout();
55 layout->addRow("Color", m_colorButton);
55 layout->addRow("Color", m_colorButton);
56 layout->addRow("Width", m_widthSpinBox);
56 layout->addRow("Width", m_widthSpinBox);
57 layout->addRow("Style", m_styleCombo);
57 layout->addRow("Style", m_styleCombo);
58 layout->addRow("Cap style", m_capStyleCombo);
58 layout->addRow("Cap style", m_capStyleCombo);
59 layout->addRow("Join style", m_joinStyleCombo);
59 layout->addRow("Join style", m_joinStyleCombo);
60 setLayout(layout);
60 setLayout(layout);
61
61
62 connect(m_colorButton, SIGNAL(clicked()), this, SLOT(showColorDialog()));
62 connect(m_colorButton, SIGNAL(clicked()), this, SLOT(showColorDialog()));
63 connect(m_widthSpinBox, SIGNAL(valueChanged(double)), this, SLOT(updateWidth(double)));
63 connect(m_widthSpinBox, SIGNAL(valueChanged(double)), this, SLOT(updateWidth(double)));
64 connect(m_styleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateStyle(int)));
64 connect(m_styleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateStyle(int)));
65 connect(m_capStyleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateCapStyle(int)));
65 connect(m_capStyleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateCapStyle(int)));
66 connect(m_joinStyleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateJoinStyle(int)));
66 connect(m_joinStyleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateJoinStyle(int)));
67 }
67 }
68
68
69 void setPen(QPen pen)
69 void setPen(QPen pen)
70 {
70 {
71 m_pen = pen;
71 m_pen = pen;
72 m_colorButton->setText(m_pen.color().name());
72 m_colorButton->setText(m_pen.color().name());
73 m_widthSpinBox->setValue(m_pen.widthF());
73 m_widthSpinBox->setValue(m_pen.widthF());
74 m_styleCombo->setCurrentIndex(m_pen.style()); // index matches the enum
74 m_styleCombo->setCurrentIndex(m_pen.style()); // index matches the enum
75 m_capStyleCombo->setCurrentIndex(m_capStyleCombo->findData(m_pen.capStyle()));
75 m_capStyleCombo->setCurrentIndex(m_capStyleCombo->findData(m_pen.capStyle()));
76 m_joinStyleCombo->setCurrentIndex(m_joinStyleCombo->findData(m_pen.joinStyle()));
76 m_joinStyleCombo->setCurrentIndex(m_joinStyleCombo->findData(m_pen.joinStyle()));
77 }
77 }
78
78
79 QPen pen() const
79 QPen pen() const
80 {
80 {
81 return m_pen;
81 return m_pen;
82 }
82 }
83
83
84 QString name()
84 QString name()
85 {
85 {
86 return name(m_pen);
86 return name(m_pen);
87 }
87 }
88
88
89 static QString name(const QPen &pen)
89 static QString name(const QPen &pen)
90 {
90 {
91 return pen.color().name() + ":" + QString::number(pen.widthF());
91 return pen.color().name() + ":" + QString::number(pen.widthF());
92 }
92 }
93
93
94 Q_SIGNALS:
94 Q_SIGNALS:
95 void changed();
95 void changed();
96
96
97 public Q_SLOTS:
97 public Q_SLOTS:
98
98
99 void showColorDialog()
99 void showColorDialog()
100 {
100 {
101 QColorDialog dialog(m_pen.color());
101 QColorDialog dialog(m_pen.color());
102 dialog.show();
102 dialog.show();
103 dialog.exec();
103 dialog.exec();
104 m_pen.setColor(dialog.selectedColor());
104 m_pen.setColor(dialog.selectedColor());
105 m_colorButton->setText(m_pen.color().name());
105 m_colorButton->setText(m_pen.color().name());
106 emit changed();
106 emit changed();
107 }
107 }
108
108
109 void updateWidth(double width)
109 void updateWidth(double width)
110 {
110 {
111 if (width != m_pen.widthF()) {
111 if (width != m_pen.widthF()) {
112 m_pen.setWidthF(width);
112 m_pen.setWidthF(width);
113 emit changed();
113 emit changed();
114 }
114 }
115 }
115 }
116
116
117 void updateStyle(int style)
117 void updateStyle(int style)
118 {
118 {
119 if (m_pen.style() != style) {
119 if (m_pen.style() != style) {
120 m_pen.setStyle((Qt::PenStyle) style);
120 m_pen.setStyle((Qt::PenStyle) style);
121 emit changed();
121 emit changed();
122 }
122 }
123 }
123 }
124
124
125 void updateCapStyle(int index)
125 void updateCapStyle(int index)
126 {
126 {
127 Qt::PenCapStyle capStyle = (Qt::PenCapStyle) m_capStyleCombo->itemData(index).toInt();
127 Qt::PenCapStyle capStyle = (Qt::PenCapStyle) m_capStyleCombo->itemData(index).toInt();
128 if (m_pen.capStyle() != capStyle) {
128 if (m_pen.capStyle() != capStyle) {
129 m_pen.setCapStyle(capStyle);
129 m_pen.setCapStyle(capStyle);
130 emit changed();
130 emit changed();
131 }
131 }
132 }
132 }
133
133
134 void updateJoinStyle(int index)
134 void updateJoinStyle(int index)
135 {
135 {
136 Qt::PenJoinStyle joinStyle = (Qt::PenJoinStyle) m_joinStyleCombo->itemData(index).toInt();
136 Qt::PenJoinStyle joinStyle = (Qt::PenJoinStyle) m_joinStyleCombo->itemData(index).toInt();
137 if (m_pen.joinStyle() != joinStyle) {
137 if (m_pen.joinStyle() != joinStyle) {
138 m_pen.setJoinStyle(joinStyle);
138 m_pen.setJoinStyle(joinStyle);
139 emit changed();
139 emit changed();
140 }
140 }
141 }
141 }
142
142
143 private:
143 private:
144 QPen m_pen;
144 QPen m_pen;
145 QPushButton *m_colorButton;
145 QPushButton *m_colorButton;
146 QDoubleSpinBox *m_widthSpinBox;
146 QDoubleSpinBox *m_widthSpinBox;
147 QComboBox *m_styleCombo;
147 QComboBox *m_styleCombo;
148 QComboBox *m_capStyleCombo;
148 QComboBox *m_capStyleCombo;
149 QComboBox *m_joinStyleCombo;
149 QComboBox *m_joinStyleCombo;
150 };
150 };
151
151
152 class BrushTool : public QWidget
152 class BrushTool : public QWidget
153 {
153 {
154 Q_OBJECT
154 Q_OBJECT
155
155
156 public:
156 public:
157 explicit BrushTool(QString title, QWidget *parent = 0)
157 explicit BrushTool(QString title, QWidget *parent = 0)
158 :QWidget(parent)
158 :QWidget(parent)
159 {
159 {
160 setWindowTitle(title);
160 setWindowTitle(title);
161 setWindowFlags(Qt::Tool);
161 setWindowFlags(Qt::Tool);
162
162
163 m_colorButton = new QPushButton();
163 m_colorButton = new QPushButton();
164 m_styleCombo = new QComboBox();
164 m_styleCombo = new QComboBox();
165 m_styleCombo->addItem("Nobrush", Qt::NoBrush);
165 m_styleCombo->addItem("Nobrush", Qt::NoBrush);
166 m_styleCombo->addItem("Solidpattern", Qt::SolidPattern);
166 m_styleCombo->addItem("Solidpattern", Qt::SolidPattern);
167 m_styleCombo->addItem("Dense1pattern", Qt::Dense1Pattern);
167 m_styleCombo->addItem("Dense1pattern", Qt::Dense1Pattern);
168 m_styleCombo->addItem("Dense2attern", Qt::Dense2Pattern);
168 m_styleCombo->addItem("Dense2attern", Qt::Dense2Pattern);
169 m_styleCombo->addItem("Dense3Pattern", Qt::Dense3Pattern);
169 m_styleCombo->addItem("Dense3Pattern", Qt::Dense3Pattern);
170 m_styleCombo->addItem("Dense4Pattern", Qt::Dense4Pattern);
170 m_styleCombo->addItem("Dense4Pattern", Qt::Dense4Pattern);
171 m_styleCombo->addItem("Dense5Pattern", Qt::Dense5Pattern);
171 m_styleCombo->addItem("Dense5Pattern", Qt::Dense5Pattern);
172 m_styleCombo->addItem("Dense6Pattern", Qt::Dense6Pattern);
172 m_styleCombo->addItem("Dense6Pattern", Qt::Dense6Pattern);
173 m_styleCombo->addItem("Dense7Pattern", Qt::Dense7Pattern);
173 m_styleCombo->addItem("Dense7Pattern", Qt::Dense7Pattern);
174 m_styleCombo->addItem("HorPattern", Qt::HorPattern);
174 m_styleCombo->addItem("HorPattern", Qt::HorPattern);
175 m_styleCombo->addItem("VerPattern", Qt::VerPattern);
175 m_styleCombo->addItem("VerPattern", Qt::VerPattern);
176 m_styleCombo->addItem("CrossPattern", Qt::CrossPattern);
176 m_styleCombo->addItem("CrossPattern", Qt::CrossPattern);
177 m_styleCombo->addItem("BDiagPattern", Qt::BDiagPattern);
177 m_styleCombo->addItem("BDiagPattern", Qt::BDiagPattern);
178 m_styleCombo->addItem("FDiagPattern", Qt::FDiagPattern);
178 m_styleCombo->addItem("FDiagPattern", Qt::FDiagPattern);
179 m_styleCombo->addItem("DiagCrossPattern", Qt::DiagCrossPattern);
179 m_styleCombo->addItem("DiagCrossPattern", Qt::DiagCrossPattern);
180
180
181 QFormLayout *layout = new QFormLayout();
181 QFormLayout *layout = new QFormLayout();
182 layout->addRow("Color", m_colorButton);
182 layout->addRow("Color", m_colorButton);
183 layout->addRow("Style", m_styleCombo);
183 layout->addRow("Style", m_styleCombo);
184 setLayout(layout);
184 setLayout(layout);
185
185
186 connect(m_colorButton, SIGNAL(clicked()), this, SLOT(showColorDialog()));
186 connect(m_colorButton, SIGNAL(clicked()), this, SLOT(showColorDialog()));
187 connect(m_styleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateStyle()));
187 connect(m_styleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateStyle()));
188 }
188 }
189
189
190 void setBrush(QBrush brush)
190 void setBrush(QBrush brush)
191 {
191 {
192 m_brush = brush;
192 m_brush = brush;
193 m_colorButton->setText(m_brush.color().name());
193 m_colorButton->setText(m_brush.color().name());
194 m_styleCombo->setCurrentIndex(m_brush.style()); // index matches the enum
194 m_styleCombo->setCurrentIndex(m_brush.style()); // index matches the enum
195 }
195 }
196
196
197 QBrush brush() const
197 QBrush brush() const
198 {
198 {
199 return m_brush;
199 return m_brush;
200 }
200 }
201
201
202 QString name()
202 QString name()
203 {
203 {
204 return name(m_brush);
204 return name(m_brush);
205 }
205 }
206
206
207 static QString name(const QBrush &brush)
207 static QString name(const QBrush &brush)
208 {
208 {
209 return brush.color().name();
209 return brush.color().name();
210 }
210 }
211
211
212 Q_SIGNALS:
212 Q_SIGNALS:
213 void changed();
213 void changed();
214
214
215 public Q_SLOTS:
215 public Q_SLOTS:
216
216
217 void showColorDialog()
217 void showColorDialog()
218 {
218 {
219 QColorDialog dialog(m_brush.color());
219 QColorDialog dialog(m_brush.color());
220 dialog.show();
220 dialog.show();
221 dialog.exec();
221 dialog.exec();
222 m_brush.setColor(dialog.selectedColor());
222 m_brush.setColor(dialog.selectedColor());
223 m_colorButton->setText(m_brush.color().name());
223 m_colorButton->setText(m_brush.color().name());
224 emit changed();
224 emit changed();
225 }
225 }
226
226
227 void updateStyle()
227 void updateStyle()
228 {
228 {
229 Qt::BrushStyle style = (Qt::BrushStyle) m_styleCombo->itemData(m_styleCombo->currentIndex()).toInt();
229 Qt::BrushStyle style = (Qt::BrushStyle) m_styleCombo->itemData(m_styleCombo->currentIndex()).toInt();
230 if (m_brush.style() != style) {
230 if (m_brush.style() != style) {
231 m_brush.setStyle(style);
231 m_brush.setStyle(style);
232 emit changed();
232 emit changed();
233 }
233 }
234 }
234 }
235
235
236 private:
236 private:
237 QBrush m_brush;
237 QBrush m_brush;
238 QPushButton *m_colorButton;
238 QPushButton *m_colorButton;
239 QComboBox *m_styleCombo;
239 QComboBox *m_styleCombo;
240 };
240 };
241
241
242 class CustomSlice : public QPieSlice
242 class CustomSlice : public QPieSlice
243 {
243 {
244 Q_OBJECT
244 Q_OBJECT
245 public:
245 public:
246 CustomSlice(qreal value, QString label)
246 CustomSlice(qreal value, QString label)
247 :QPieSlice(value, label)
247 :QPieSlice(value, label)
248 {
248 {
249 connect(this, SIGNAL(hoverEnter()), this, SLOT(handleHoverEnter()));
249 connect(this, SIGNAL(hoverEnter()), this, SLOT(handleHoverEnter()));
250 connect(this, SIGNAL(hoverLeave()), this, SLOT(handleHoverLeave()));
250 connect(this, SIGNAL(hoverLeave()), this, SLOT(handleHoverLeave()));
251 }
251 }
252
252
253 public:
253 public:
254 QBrush originalBrush()
254 QBrush originalBrush()
255 {
255 {
256 return m_originalBrush;
256 return m_originalBrush;
257 }
257 }
258
258
259 public Q_SLOTS:
259 public Q_SLOTS:
260
260
261 void handleHoverEnter()
261 void handleHoverEnter()
262 {
262 {
263 QBrush brush = this->sliceBrush();
263 QBrush brush = this->sliceBrush();
264 m_originalBrush = brush;
264 m_originalBrush = brush;
265 brush.setColor(brush.color().lighter());
265 brush.setColor(brush.color().lighter());
266 setSliceBrush(brush);
266 setSliceBrush(brush);
267 }
267 }
268
268
269 void handleHoverLeave()
269 void handleHoverLeave()
270 {
270 {
271 setSliceBrush(m_originalBrush);
271 setSliceBrush(m_originalBrush);
272 }
272 }
273
273
274 private:
274 private:
275 QBrush m_originalBrush;
275 QBrush m_originalBrush;
276 };
276 };
277
277
278 class MainWidget : public QWidget
278 class MainWidget : public QWidget
279 {
279 {
280 Q_OBJECT
280 Q_OBJECT
281
281
282 public:
282 public:
283 explicit MainWidget(QWidget* parent = 0)
283 explicit MainWidget(QWidget* parent = 0)
284 :QWidget(parent),
284 :QWidget(parent),
285 m_slice(0)
285 m_slice(0)
286 {
286 {
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();
293 *m_series << new CustomSlice(10.0, "Slice 1");
294 *m_series << new CustomSlice(10.0, "Slice 1");
294 *m_series << new CustomSlice(20.0, "Slice 2");
295 *m_series << new CustomSlice(20.0, "Slice 2");
295 *m_series << new CustomSlice(30.0, "Slice 3");
296 *m_series << new CustomSlice(30.0, "Slice 3");
296 *m_series << new CustomSlice(40.0, "Slice 4");
297 *m_series << new CustomSlice(40.0, "Slice 4");
297 *m_series << new CustomSlice(50.0, "Slice 5");
298 *m_series << new CustomSlice(50.0, "Slice 5");
298 m_chartView->addSeries(m_series);
299 m_chartView->addSeries(m_series);
299
300
300 connect(m_series, SIGNAL(clicked(QPieSlice*)), this, SLOT(handleSliceClicked(QPieSlice*)));
301 connect(m_series, SIGNAL(clicked(QPieSlice*)), this, SLOT(handleSliceClicked(QPieSlice*)));
301
302
302 // chart settings
303 // chart settings
303 m_themeComboBox = new QComboBox();
304 m_themeComboBox = new QComboBox();
304 m_themeComboBox->addItem("Default", QChart::ChartThemeDefault);
305 m_themeComboBox->addItem("Default", QChart::ChartThemeDefault);
305 m_themeComboBox->addItem("Vanilla", QChart::ChartThemeVanilla);
306 m_themeComboBox->addItem("Vanilla", QChart::ChartThemeVanilla);
306 m_themeComboBox->addItem("Icy", QChart::ChartThemeIcy);
307 m_themeComboBox->addItem("Icy", QChart::ChartThemeIcy);
307 m_themeComboBox->addItem("Grayscale", QChart::ChartThemeGrayscale);
308 m_themeComboBox->addItem("Grayscale", QChart::ChartThemeGrayscale);
308 m_themeComboBox->addItem("Scientific", QChart::ChartThemeScientific);
309 m_themeComboBox->addItem("Scientific", QChart::ChartThemeScientific);
309
310
310 m_aaCheckBox = new QCheckBox();
311 m_aaCheckBox = new QCheckBox();
311
312
312 QFormLayout* chartSettingsLayout = new QFormLayout();
313 QFormLayout* chartSettingsLayout = new QFormLayout();
313 chartSettingsLayout->addRow("Theme", m_themeComboBox);
314 chartSettingsLayout->addRow("Theme", m_themeComboBox);
314 chartSettingsLayout->addRow("Antialiasing", m_aaCheckBox);
315 chartSettingsLayout->addRow("Antialiasing", m_aaCheckBox);
315 QGroupBox* chartSettings = new QGroupBox("Chart");
316 QGroupBox* chartSettings = new QGroupBox("Chart");
316 chartSettings->setLayout(chartSettingsLayout);
317 chartSettings->setLayout(chartSettingsLayout);
317
318
318 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this ,SLOT(updateChartSettings()));
319 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this ,SLOT(updateChartSettings()));
319 connect(m_aaCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
320 connect(m_aaCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
320
321
321 // series settings
322 // series settings
322 m_hPosition = new QDoubleSpinBox();
323 m_hPosition = new QDoubleSpinBox();
323 m_hPosition->setMinimum(0.0);
324 m_hPosition->setMinimum(0.0);
324 m_hPosition->setMaximum(1.0);
325 m_hPosition->setMaximum(1.0);
325 m_hPosition->setSingleStep(0.1);
326 m_hPosition->setSingleStep(0.1);
326 m_hPosition->setValue(m_series->pieHorizontalPosition());
327 m_hPosition->setValue(m_series->pieHorizontalPosition());
327
328
328 m_vPosition = new QDoubleSpinBox();
329 m_vPosition = new QDoubleSpinBox();
329 m_vPosition->setMinimum(0.0);
330 m_vPosition->setMinimum(0.0);
330 m_vPosition->setMaximum(1.0);
331 m_vPosition->setMaximum(1.0);
331 m_vPosition->setSingleStep(0.1);
332 m_vPosition->setSingleStep(0.1);
332 m_vPosition->setValue(m_series->pieVerticalPosition());
333 m_vPosition->setValue(m_series->pieVerticalPosition());
333
334
334 m_sizeFactor = new QDoubleSpinBox();
335 m_sizeFactor = new QDoubleSpinBox();
335 m_sizeFactor->setMinimum(0.0);
336 m_sizeFactor->setMinimum(0.0);
336 m_sizeFactor->setMaximum(1.0);
337 m_sizeFactor->setMaximum(1.0);
337 m_sizeFactor->setSingleStep(0.1);
338 m_sizeFactor->setSingleStep(0.1);
338 m_sizeFactor->setValue(m_series->pieSize());
339 m_sizeFactor->setValue(m_series->pieSize());
339
340
340 m_startAngle = new QDoubleSpinBox();
341 m_startAngle = new QDoubleSpinBox();
341 m_startAngle->setMinimum(0.0);
342 m_startAngle->setMinimum(0.0);
342 m_startAngle->setMaximum(360);
343 m_startAngle->setMaximum(360);
343 m_startAngle->setValue(m_series->pieStartAngle());
344 m_startAngle->setValue(m_series->pieStartAngle());
344 m_startAngle->setSingleStep(1);
345 m_startAngle->setSingleStep(1);
345
346
346 m_endAngle = new QDoubleSpinBox();
347 m_endAngle = new QDoubleSpinBox();
347 m_endAngle->setMinimum(0.0);
348 m_endAngle->setMinimum(0.0);
348 m_endAngle->setMaximum(360);
349 m_endAngle->setMaximum(360);
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
361 connect(m_vPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
365 connect(m_vPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
362 connect(m_hPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
366 connect(m_hPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
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>");
369 m_sliceValue = new QDoubleSpinBox();
374 m_sliceValue = new QDoubleSpinBox();
370 m_sliceValue->setMaximum(1000);
375 m_sliceValue->setMaximum(1000);
371 m_sliceLabelVisible = new QCheckBox();
376 m_sliceLabelVisible = new QCheckBox();
372 m_sliceLabelArmFactor = new QDoubleSpinBox();
377 m_sliceLabelArmFactor = new QDoubleSpinBox();
373 m_sliceLabelArmFactor->setSingleStep(0.01);
378 m_sliceLabelArmFactor->setSingleStep(0.01);
374 m_sliceExploded = new QCheckBox();
379 m_sliceExploded = new QCheckBox();
375 m_sliceExplodedFactor = new QDoubleSpinBox();
380 m_sliceExplodedFactor = new QDoubleSpinBox();
376 m_sliceExplodedFactor->setSingleStep(0.01);
381 m_sliceExplodedFactor->setSingleStep(0.01);
377 m_pen = new QPushButton();
382 m_pen = new QPushButton();
378 m_penTool = new PenTool("Slice pen", this);
383 m_penTool = new PenTool("Slice pen", this);
379 m_brush = new QPushButton();
384 m_brush = new QPushButton();
380 m_brushTool = new BrushTool("Slice brush", this);
385 m_brushTool = new BrushTool("Slice brush", this);
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);
387 sliceSettingsLayout->addRow("Value", m_sliceValue);
393 sliceSettingsLayout->addRow("Value", m_sliceValue);
388 sliceSettingsLayout->addRow("Pen", m_pen);
394 sliceSettingsLayout->addRow("Pen", m_pen);
389 sliceSettingsLayout->addRow("Brush", m_brush);
395 sliceSettingsLayout->addRow("Brush", m_brush);
390 sliceSettingsLayout->addRow("Label visible", m_sliceLabelVisible);
396 sliceSettingsLayout->addRow("Label visible", m_sliceLabelVisible);
391 sliceSettingsLayout->addRow("Label font", m_font);
397 sliceSettingsLayout->addRow("Label font", m_font);
392 sliceSettingsLayout->addRow("Label arm pen", m_labelArmPen);
398 sliceSettingsLayout->addRow("Label arm pen", m_labelArmPen);
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
399 connect(m_sliceValue, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
406 connect(m_sliceValue, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
400 connect(m_pen, SIGNAL(clicked()), m_penTool, SLOT(show()));
407 connect(m_pen, SIGNAL(clicked()), m_penTool, SLOT(show()));
401 connect(m_penTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
408 connect(m_penTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
402 connect(m_brush, SIGNAL(clicked()), m_brushTool, SLOT(show()));
409 connect(m_brush, SIGNAL(clicked()), m_brushTool, SLOT(show()));
403 connect(m_brushTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
410 connect(m_brushTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
404 connect(m_font, SIGNAL(clicked()), this, SLOT(showFontDialog()));
411 connect(m_font, SIGNAL(clicked()), this, SLOT(showFontDialog()));
405 connect(m_labelArmPen, SIGNAL(clicked()), m_labelArmPenTool, SLOT(show()));
412 connect(m_labelArmPen, SIGNAL(clicked()), m_labelArmPenTool, SLOT(show()));
406 connect(m_labelArmPenTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
413 connect(m_labelArmPenTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
407 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
414 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
408 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
415 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
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();
415 settingsLayout->addWidget(chartSettings);
423 settingsLayout->addWidget(chartSettings);
416 settingsLayout->addWidget(seriesSettings);
424 settingsLayout->addWidget(seriesSettings);
417 settingsLayout->addWidget(sliceSettings);
425 settingsLayout->addWidget(sliceSettings);
418 settingsLayout->addStretch();
426 settingsLayout->addStretch();
419
427
420 QGridLayout* baseLayout = new QGridLayout();
428 QGridLayout* baseLayout = new QGridLayout();
421 baseLayout->addLayout(settingsLayout, 0, 0);
429 baseLayout->addLayout(settingsLayout, 0, 0);
422 baseLayout->addWidget(m_chartView, 0, 1);
430 baseLayout->addWidget(m_chartView, 0, 1);
423 setLayout(baseLayout);
431 setLayout(baseLayout);
424
432
425 updateSerieSettings();
433 updateSerieSettings();
426 }
434 }
427
435
428 public Q_SLOTS:
436 public Q_SLOTS:
429
437
430 void updateChartSettings()
438 void updateChartSettings()
431 {
439 {
432 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
440 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
433 m_chartView->setChartTheme(theme);
441 m_chartView->setChartTheme(theme);
434 m_chartView->setRenderHint(QPainter::Antialiasing, m_aaCheckBox->isChecked());
442 m_chartView->setRenderHint(QPainter::Antialiasing, m_aaCheckBox->isChecked());
435 }
443 }
436
444
437 void updateSerieSettings()
445 void updateSerieSettings()
438 {
446 {
439 m_series->setPiePosition(m_vPosition->value(), m_hPosition->value());
447 m_series->setPiePosition(m_vPosition->value(), m_hPosition->value());
440 m_series->setPieSize(m_sizeFactor->value());
448 m_series->setPieSize(m_sizeFactor->value());
441 m_series->setPieStartAngle(m_startAngle->value());
449 m_series->setPieStartAngle(m_startAngle->value());
442 m_series->setPieEndAngle(m_endAngle->value());
450 m_series->setPieEndAngle(m_endAngle->value());
443 }
451 }
444
452
445 void updateSliceSettings()
453 void updateSliceSettings()
446 {
454 {
447 if (!m_slice)
455 if (!m_slice)
448 return;
456 return;
449
457
450 m_slice->setValue(m_sliceValue->value());
458 m_slice->setValue(m_sliceValue->value());
451
459
452 m_slice->setSlicePen(m_penTool->pen());
460 m_slice->setSlicePen(m_penTool->pen());
453 m_slice->setSliceBrush(m_brushTool->brush());
461 m_slice->setSliceBrush(m_brushTool->brush());
454
462
455 m_slice->setLabelArmPen(m_labelArmPenTool->pen());
463 m_slice->setLabelArmPen(m_labelArmPenTool->pen());
456 m_slice->setLabelVisible(m_sliceLabelVisible->isChecked());
464 m_slice->setLabelVisible(m_sliceLabelVisible->isChecked());
457 m_slice->setLabelArmLengthFactor(m_sliceLabelArmFactor->value());
465 m_slice->setLabelArmLengthFactor(m_sliceLabelArmFactor->value());
458
466
459 m_slice->setExploded(m_sliceExploded->isChecked());
467 m_slice->setExploded(m_sliceExploded->isChecked());
460 m_slice->setExplodeDistanceFactor(m_sliceExplodedFactor->value());
468 m_slice->setExplodeDistanceFactor(m_sliceExplodedFactor->value());
461 }
469 }
462
470
463 void handleSliceClicked(QPieSlice* slice)
471 void handleSliceClicked(QPieSlice* slice)
464 {
472 {
465 m_slice = static_cast<CustomSlice*>(slice);
473 m_slice = static_cast<CustomSlice*>(slice);
466
474
467 // name
475 // name
468 m_sliceName->setText(slice->label());
476 m_sliceName->setText(slice->label());
469
477
470 // value
478 // value
471 m_sliceValue->blockSignals(true);
479 m_sliceValue->blockSignals(true);
472 m_sliceValue->setValue(slice->value());
480 m_sliceValue->setValue(slice->value());
473 m_sliceValue->blockSignals(false);
481 m_sliceValue->blockSignals(false);
474
482
475 // pen
483 // pen
476 m_pen->setText(PenTool::name(m_slice->slicePen()));
484 m_pen->setText(PenTool::name(m_slice->slicePen()));
477 m_penTool->setPen(m_slice->slicePen());
485 m_penTool->setPen(m_slice->slicePen());
478
486
479 // brush
487 // brush
480 m_brush->setText(m_slice->originalBrush().color().name());
488 m_brush->setText(m_slice->originalBrush().color().name());
481 m_brushTool->setBrush(m_slice->originalBrush());
489 m_brushTool->setBrush(m_slice->originalBrush());
482
490
483 // label
491 // label
484 m_labelArmPen->setText(PenTool::name(m_slice->labelArmPen()));
492 m_labelArmPen->setText(PenTool::name(m_slice->labelArmPen()));
485 m_labelArmPenTool->setPen(m_slice->labelArmPen());
493 m_labelArmPenTool->setPen(m_slice->labelArmPen());
486 m_font->setText(slice->labelFont().toString());
494 m_font->setText(slice->labelFont().toString());
487 m_sliceLabelVisible->blockSignals(true);
495 m_sliceLabelVisible->blockSignals(true);
488 m_sliceLabelVisible->setChecked(slice->isLabelVisible());
496 m_sliceLabelVisible->setChecked(slice->isLabelVisible());
489 m_sliceLabelVisible->blockSignals(false);
497 m_sliceLabelVisible->blockSignals(false);
490 m_sliceLabelArmFactor->blockSignals(true);
498 m_sliceLabelArmFactor->blockSignals(true);
491 m_sliceLabelArmFactor->setValue(slice->labelArmLengthFactor());
499 m_sliceLabelArmFactor->setValue(slice->labelArmLengthFactor());
492 m_sliceLabelArmFactor->blockSignals(false);
500 m_sliceLabelArmFactor->blockSignals(false);
493
501
494 // exploded
502 // exploded
495 m_sliceExploded->blockSignals(true);
503 m_sliceExploded->blockSignals(true);
496 m_sliceExploded->setChecked(slice->isExploded());
504 m_sliceExploded->setChecked(slice->isExploded());
497 m_sliceExploded->blockSignals(false);
505 m_sliceExploded->blockSignals(false);
498 m_sliceExplodedFactor->blockSignals(true);
506 m_sliceExplodedFactor->blockSignals(true);
499 m_sliceExplodedFactor->setValue(slice->explodeDistanceFactor());
507 m_sliceExplodedFactor->setValue(slice->explodeDistanceFactor());
500 m_sliceExplodedFactor->blockSignals(false);
508 m_sliceExplodedFactor->blockSignals(false);
501 }
509 }
502
510
503 void showFontDialog()
511 void showFontDialog()
504 {
512 {
505 if (!m_slice)
513 if (!m_slice)
506 return;
514 return;
507
515
508 QFontDialog dialog(m_slice->labelFont());
516 QFontDialog dialog(m_slice->labelFont());
509 dialog.show();
517 dialog.show();
510 dialog.exec();
518 dialog.exec();
511
519
512 m_slice->setLabelFont(dialog.currentFont());
520 m_slice->setLabelFont(dialog.currentFont());
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;
519
541
520 QChartView* m_chartView;
542 QChartView* m_chartView;
521 QPieSeries* m_series;
543 QPieSeries* m_series;
522 CustomSlice* m_slice;
544 CustomSlice* m_slice;
523
545
524 QDoubleSpinBox* m_hPosition;
546 QDoubleSpinBox* m_hPosition;
525 QDoubleSpinBox* m_vPosition;
547 QDoubleSpinBox* m_vPosition;
526 QDoubleSpinBox* m_sizeFactor;
548 QDoubleSpinBox* m_sizeFactor;
527 QDoubleSpinBox* m_startAngle;
549 QDoubleSpinBox* m_startAngle;
528 QDoubleSpinBox* m_endAngle;
550 QDoubleSpinBox* m_endAngle;
529
551
530 QLabel* m_sliceName;
552 QLabel* m_sliceName;
531 QDoubleSpinBox* m_sliceValue;
553 QDoubleSpinBox* m_sliceValue;
532 QCheckBox* m_sliceLabelVisible;
554 QCheckBox* m_sliceLabelVisible;
533 QDoubleSpinBox* m_sliceLabelArmFactor;
555 QDoubleSpinBox* m_sliceLabelArmFactor;
534 QCheckBox* m_sliceExploded;
556 QCheckBox* m_sliceExploded;
535 QDoubleSpinBox* m_sliceExplodedFactor;
557 QDoubleSpinBox* m_sliceExplodedFactor;
536 QPushButton *m_brush;
558 QPushButton *m_brush;
537 BrushTool *m_brushTool;
559 BrushTool *m_brushTool;
538 QPushButton *m_pen;
560 QPushButton *m_pen;
539 PenTool *m_penTool;
561 PenTool *m_penTool;
540 QPushButton *m_font;
562 QPushButton *m_font;
541 QPushButton *m_labelArmPen;
563 QPushButton *m_labelArmPen;
542 PenTool *m_labelArmPenTool;
564 PenTool *m_labelArmPenTool;
543 };
565 };
544
566
545 int main(int argc, char *argv[])
567 int main(int argc, char *argv[])
546 {
568 {
547 QApplication a(argc, argv);
569 QApplication a(argc, argv);
548
570
549 QMainWindow window;
571 QMainWindow window;
550
572
551 MainWidget* widget = new MainWidget();
573 MainWidget* widget = new MainWidget();
552
574
553 window.setCentralWidget(widget);
575 window.setCentralWidget(widget);
554 window.resize(900, 600);
576 window.resize(900, 600);
555 window.show();
577 window.show();
556
578
557 return a.exec();
579 return a.exec();
558 }
580 }
559
581
560 #include "main.moc"
582 #include "main.moc"
@@ -1,13 +1,17
1 INCLUDEPATH += $$PWD
1 INCLUDEPATH += $$PWD
2 DEPENDPATH += $$PWD
2 DEPENDPATH += $$PWD
3
3
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
@@ -1,180 +1,207
1 #include "chartanimator_p.h"
1 #include "chartanimator_p.h"
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
8 Q_DECLARE_METATYPE(QVector<QPointF>)
9 Q_DECLARE_METATYPE(QVector<QPointF>)
9 Q_DECLARE_METATYPE(QVector<qreal>)
10 Q_DECLARE_METATYPE(QVector<qreal>)
10
11
11 QTCOMMERCIALCHART_BEGIN_NAMESPACE
12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
12
13
13 const static int duration = 1000;
14 const static int duration = 1000;
14
15
15 ChartAnimator::ChartAnimator(QObject *parent):QObject(parent)
16 ChartAnimator::ChartAnimator(QObject *parent):QObject(parent)
16 {
17 {
17 }
18 }
18
19
19 ChartAnimator::~ChartAnimator()
20 ChartAnimator::~ChartAnimator()
20 {
21 {
21 }
22 }
22
23
23 void ChartAnimator::addAnimation(AxisItem* item)
24 void ChartAnimator::addAnimation(AxisItem* item)
24 {
25 {
25 ChartAnimation* animation = m_animations.value(item);
26 ChartAnimation* animation = m_animations.value(item);
26
27
27 if(!animation) {
28 if(!animation) {
28 animation = new AxisAnimation(item);
29 animation = new AxisAnimation(item);
29 m_animations.insert(item,animation);
30 m_animations.insert(item,animation);
30 }
31 }
31
32
32 item->setAnimator(this);
33 item->setAnimator(this);
33 }
34 }
34
35
35 void ChartAnimator::addAnimation(XYChartItem* item)
36 void ChartAnimator::addAnimation(XYChartItem* item)
36 {
37 {
37 ChartAnimation* animation = m_animations.value(item);
38 ChartAnimation* animation = m_animations.value(item);
38
39
39 if(!animation) {
40 if(!animation) {
40 animation = new XYAnimation(item);
41 animation = new XYAnimation(item);
41 m_animations.insert(item,animation);
42 m_animations.insert(item,animation);
42 }
43 }
43
44
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);
50 m_animations.remove(item);
63 m_animations.remove(item);
51 }
64 }
52
65
53 void ChartAnimator::applyLayout(AxisItem* item , QVector<qreal>& newLayout)
66 void ChartAnimator::applyLayout(AxisItem* item , QVector<qreal>& newLayout)
54 {
67 {
55 AxisAnimation* animation = static_cast<AxisAnimation*>(m_animations.value(item));
68 AxisAnimation* animation = static_cast<AxisAnimation*>(m_animations.value(item));
56
69
57 Q_ASSERT(animation);
70 Q_ASSERT(animation);
58
71
59 QVector<qreal> oldLayout = item->layout();
72 QVector<qreal> oldLayout = item->layout();
60
73
61 if(newLayout.count()==0) return;
74 if(newLayout.count()==0) return;
62
75
63 switch(m_state)
76 switch(m_state)
64 {
77 {
65 case ZoomOutState: {
78 case ZoomOutState: {
66 QRectF rect = item->geometry();
79 QRectF rect = item->geometry();
67 oldLayout.resize(newLayout.count());
80 oldLayout.resize(newLayout.count());
68
81
69 for(int i=0,j=oldLayout.count()-1;i<(oldLayout.count()+1)/2;i++,j--)
82 for(int i=0,j=oldLayout.count()-1;i<(oldLayout.count()+1)/2;i++,j--)
70 {
83 {
71 oldLayout[i]= item->axisType()==AxisItem::X_AXIS?rect.left():rect.bottom();
84 oldLayout[i]= item->axisType()==AxisItem::X_AXIS?rect.left():rect.bottom();
72 oldLayout[j]= item->axisType()==AxisItem::X_AXIS?rect.right():rect.top();
85 oldLayout[j]= item->axisType()==AxisItem::X_AXIS?rect.right():rect.top();
73 }
86 }
74 }
87 }
75 break;
88 break;
76 case ZoomInState: {
89 case ZoomInState: {
77 int index = qMin(oldLayout.count()*(item->axisType()==AxisItem::X_AXIS?m_point.x():(1 -m_point.y())),newLayout.count()-1.0);
90 int index = qMin(oldLayout.count()*(item->axisType()==AxisItem::X_AXIS?m_point.x():(1 -m_point.y())),newLayout.count()-1.0);
78 oldLayout.resize(newLayout.count());
91 oldLayout.resize(newLayout.count());
79
92
80 for(int i=0;i<oldLayout.count();i++)
93 for(int i=0;i<oldLayout.count();i++)
81 {
94 {
82 oldLayout[i]= oldLayout[index];
95 oldLayout[i]= oldLayout[index];
83 }
96 }
84 }
97 }
85 break;
98 break;
86 case ScrollDownState:
99 case ScrollDownState:
87 case ScrollRightState: {
100 case ScrollRightState: {
88 oldLayout.resize(newLayout.count());
101 oldLayout.resize(newLayout.count());
89
102
90 for(int i=0, j=i+1;i<oldLayout.count()-1;i++,j++)
103 for(int i=0, j=i+1;i<oldLayout.count()-1;i++,j++)
91 {
104 {
92 oldLayout[i]= oldLayout[j];
105 oldLayout[i]= oldLayout[j];
93 }
106 }
94 }
107 }
95 break;
108 break;
96 case ScrollUpState:
109 case ScrollUpState:
97 case ScrollLeftState: {
110 case ScrollLeftState: {
98 oldLayout.resize(newLayout.count());
111 oldLayout.resize(newLayout.count());
99
112
100 for(int i=oldLayout.count()-1, j=i-1;i>0;i--,j--)
113 for(int i=oldLayout.count()-1, j=i-1;i>0;i--,j--)
101 {
114 {
102 oldLayout[i]= oldLayout[j];
115 oldLayout[i]= oldLayout[j];
103 }
116 }
104 }
117 }
105 break;
118 break;
106 default: {
119 default: {
107 oldLayout.resize(newLayout.count());
120 oldLayout.resize(newLayout.count());
108 QRectF rect = item->geometry();
121 QRectF rect = item->geometry();
109 for(int i=0, j=oldLayout.count()-1;i<oldLayout.count();i++,j--)
122 for(int i=0, j=oldLayout.count()-1;i<oldLayout.count();i++,j--)
110 {
123 {
111 oldLayout[i]= item->axisType()==AxisItem::X_AXIS?rect.left():rect.top();
124 oldLayout[i]= item->axisType()==AxisItem::X_AXIS?rect.left():rect.top();
112 }
125 }
113 }
126 }
114 break;
127 break;
115 }
128 }
116
129
117
130
118 if(animation->state()!=QAbstractAnimation::Stopped) {
131 if(animation->state()!=QAbstractAnimation::Stopped) {
119 animation->stop();
132 animation->stop();
120 }
133 }
121
134
122 animation->setDuration(duration);
135 animation->setDuration(duration);
123 animation->setEasingCurve(QEasingCurve::OutQuart);
136 animation->setEasingCurve(QEasingCurve::OutQuart);
124 QVariantAnimation::KeyValues value;
137 QVariantAnimation::KeyValues value;
125 animation->setKeyValues(value); //workaround for wrong interpolation call
138 animation->setKeyValues(value); //workaround for wrong interpolation call
126 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
139 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
127 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
140 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
128
141
129 QTimer::singleShot(0,animation,SLOT(start()));
142 QTimer::singleShot(0,animation,SLOT(start()));
130 }
143 }
131
144
132 void ChartAnimator::applyLayout(XYChartItem* item, QVector<QPointF>& newPoints)
145 void ChartAnimator::applyLayout(XYChartItem* item, QVector<QPointF>& newPoints)
133 {
146 {
134
147
135 XYAnimation* animation = static_cast<XYAnimation*>(m_animations.value(item));
148 XYAnimation* animation = static_cast<XYAnimation*>(m_animations.value(item));
136
149
137 Q_ASSERT(animation);
150 Q_ASSERT(animation);
138
151
139 QVector<QPointF> oldPoints = item->points();
152 QVector<QPointF> oldPoints = item->points();
140
153
141 if(newPoints.count()==0) return;
154 if(newPoints.count()==0) return;
142
155
143 bool empty = oldPoints.count()==0;
156 bool empty = oldPoints.count()==0;
144 oldPoints.resize(newPoints.size());
157 oldPoints.resize(newPoints.size());
145
158
146 if(animation->state()!=QAbstractAnimation::Stopped) {
159 if(animation->state()!=QAbstractAnimation::Stopped) {
147 animation->stop();
160 animation->stop();
148 }
161 }
149
162
150 animation->setDuration(duration);
163 animation->setDuration(duration);
151 if(!empty)
164 if(!empty)
152 animation->setAnimationType(XYAnimation::MoveDownAnimation);
165 animation->setAnimationType(XYAnimation::MoveDownAnimation);
153 else
166 else
154 animation->setAnimationType(XYAnimation::LineDrawAnimation);
167 animation->setAnimationType(XYAnimation::LineDrawAnimation);
155 animation->setEasingCurve(QEasingCurve::OutQuart);
168 animation->setEasingCurve(QEasingCurve::OutQuart);
156 animation->setValues(oldPoints,newPoints);
169 animation->setValues(oldPoints,newPoints);
157 QTimer::singleShot(0,animation,SLOT(start()));
170 QTimer::singleShot(0,animation,SLOT(start()));
158 }
171 }
159
172
160 void ChartAnimator::updateLayout(XYChartItem* item, QVector<QPointF>& newPoints)
173 void ChartAnimator::updateLayout(XYChartItem* item, QVector<QPointF>& newPoints)
161 {
174 {
162 XYAnimation* animation = static_cast<XYAnimation*>(m_animations.value(item));
175 XYAnimation* animation = static_cast<XYAnimation*>(m_animations.value(item));
163
176
164 Q_ASSERT(animation);
177 Q_ASSERT(animation);
165
178
166 animation->setDuration(duration);
179 animation->setDuration(duration);
167 animation->setAnimationType(XYAnimation::MoveDownAnimation);
180 animation->setAnimationType(XYAnimation::MoveDownAnimation);
168 animation->setEasingCurve(QEasingCurve::OutQuart);
181 animation->setEasingCurve(QEasingCurve::OutQuart);
169 animation->updateValues(newPoints);
182 animation->updateValues(newPoints);
170
183
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;
177 m_point=point;
204 m_point=point;
178 }
205 }
179
206
180 QTCOMMERCIALCHART_END_NAMESPACE
207 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,43 +1,48
1 #ifndef CHARTANIMATOR_P_H_
1 #ifndef CHARTANIMATOR_P_H_
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
8
9
9 class ChartItem;
10 class ChartItem;
10 class XYChartItem;
11 class XYChartItem;
11 class AxisItem;
12 class AxisItem;
12 class AreaChartItem;
13 class AreaChartItem;
13
14
14
15
15 class ChartAnimator : public QObject {
16 class ChartAnimator : public QObject {
16
17
17 public:
18 public:
18 //TODO: this should be flags in case of two state at the time
19 //TODO: this should be flags in case of two state at the time
19 enum State{ShowState, ScrollUpState, ScrollDownState, ScrollLeftState,ScrollRightState,ZoomInState,ZoomOutState};
20 enum State{ShowState, ScrollUpState, ScrollDownState, ScrollLeftState,ScrollRightState,ZoomInState,ZoomOutState};
20 ChartAnimator(QObject *parent = 0);
21 ChartAnimator(QObject *parent = 0);
21 virtual ~ChartAnimator();
22 virtual ~ChartAnimator();
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
28 void animationStarted();
30 void animationStarted();
29 void applyLayout(XYChartItem* item, QVector<QPointF>& layout);
31 void applyLayout(XYChartItem* item, QVector<QPointF>& layout);
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:
36 QMap<ChartItem*,ChartAnimation*> m_animations;
41 QMap<ChartItem*,ChartAnimation*> m_animations;
37 State m_state;
42 State m_state;
38 QPointF m_point;
43 QPointF m_point;
39 };
44 };
40
45
41 QTCOMMERCIALCHART_END_NAMESPACE
46 QTCOMMERCIALCHART_END_NAMESPACE
42
47
43 #endif
48 #endif
@@ -1,401 +1,401
1 #include "qchart.h"
1 #include "qchart.h"
2 #include "qchartaxis.h"
2 #include "qchartaxis.h"
3 #include "chartpresenter_p.h"
3 #include "chartpresenter_p.h"
4 #include "chartdataset_p.h"
4 #include "chartdataset_p.h"
5 #include "charttheme_p.h"
5 #include "charttheme_p.h"
6 #include "chartanimator_p.h"
6 #include "chartanimator_p.h"
7 //series
7 //series
8 #include "qbarseries.h"
8 #include "qbarseries.h"
9 #include "qstackedbarseries.h"
9 #include "qstackedbarseries.h"
10 #include "qpercentbarseries.h"
10 #include "qpercentbarseries.h"
11 #include "qlineseries.h"
11 #include "qlineseries.h"
12 #include "qareaseries.h"
12 #include "qareaseries.h"
13 #include "qpieseries.h"
13 #include "qpieseries.h"
14 #include "qscatterseries.h"
14 #include "qscatterseries.h"
15 #include "qsplineseries.h"
15 #include "qsplineseries.h"
16 //items
16 //items
17 #include "axisitem_p.h"
17 #include "axisitem_p.h"
18 #include "areachartitem_p.h"
18 #include "areachartitem_p.h"
19 #include "barpresenter_p.h"
19 #include "barpresenter_p.h"
20 #include "stackedbarpresenter_p.h"
20 #include "stackedbarpresenter_p.h"
21 #include "percentbarpresenter_p.h"
21 #include "percentbarpresenter_p.h"
22 #include "linechartitem_p.h"
22 #include "linechartitem_p.h"
23 #include "piechartitem_p.h"
23 #include "piechartitem_p.h"
24 #include "scatterchartitem_p.h"
24 #include "scatterchartitem_p.h"
25 #include "splinechartitem_p.h"
25 #include "splinechartitem_p.h"
26
26
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28
28
29 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
29 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
30 m_chart(chart),
30 m_chart(chart),
31 m_animator(0),
31 m_animator(0),
32 m_dataset(dataset),
32 m_dataset(dataset),
33 m_chartTheme(0),
33 m_chartTheme(0),
34 m_zoomIndex(0),
34 m_zoomIndex(0),
35 m_marginSize(0),
35 m_marginSize(0),
36 m_rect(QRectF(QPoint(0,0),m_chart->size())),
36 m_rect(QRectF(QPoint(0,0),m_chart->size())),
37 m_options(QChart::NoAnimation)
37 m_options(QChart::NoAnimation)
38 {
38 {
39 createConnections();
39 createConnections();
40 setChartTheme(QChart::ChartThemeDefault);
40 setChartTheme(QChart::ChartThemeDefault);
41 }
41 }
42
42
43 ChartPresenter::~ChartPresenter()
43 ChartPresenter::~ChartPresenter()
44 {
44 {
45 delete m_chartTheme;
45 delete m_chartTheme;
46 }
46 }
47
47
48 void ChartPresenter::createConnections()
48 void ChartPresenter::createConnections()
49 {
49 {
50 QObject::connect(m_chart,SIGNAL(geometryChanged()),this,SLOT(handleGeometryChanged()));
50 QObject::connect(m_chart,SIGNAL(geometryChanged()),this,SLOT(handleGeometryChanged()));
51 QObject::connect(m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),this,SLOT(handleSeriesAdded(QSeries*,Domain*)));
51 QObject::connect(m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),this,SLOT(handleSeriesAdded(QSeries*,Domain*)));
52 QObject::connect(m_dataset,SIGNAL(seriesRemoved(QSeries*)),this,SLOT(handleSeriesRemoved(QSeries*)));
52 QObject::connect(m_dataset,SIGNAL(seriesRemoved(QSeries*)),this,SLOT(handleSeriesRemoved(QSeries*)));
53 QObject::connect(m_dataset,SIGNAL(axisAdded(QChartAxis*,Domain*)),this,SLOT(handleAxisAdded(QChartAxis*,Domain*)));
53 QObject::connect(m_dataset,SIGNAL(axisAdded(QChartAxis*,Domain*)),this,SLOT(handleAxisAdded(QChartAxis*,Domain*)));
54 QObject::connect(m_dataset,SIGNAL(axisRemoved(QChartAxis*)),this,SLOT(handleAxisRemoved(QChartAxis*)));
54 QObject::connect(m_dataset,SIGNAL(axisRemoved(QChartAxis*)),this,SLOT(handleAxisRemoved(QChartAxis*)));
55 }
55 }
56
56
57
57
58 QRectF ChartPresenter::geometry() const
58 QRectF ChartPresenter::geometry() const
59 {
59 {
60 return m_rect;
60 return m_rect;
61 }
61 }
62
62
63 void ChartPresenter::handleGeometryChanged()
63 void ChartPresenter::handleGeometryChanged()
64 {
64 {
65 QRectF rect(QPoint(0,0),m_chart->size());
65 QRectF rect(QPoint(0,0),m_chart->size());
66 rect.adjust(m_marginSize,m_marginSize, -m_marginSize, -m_marginSize);
66 rect.adjust(m_marginSize,m_marginSize, -m_marginSize, -m_marginSize);
67
67
68 //rewrite zoom stack
68 //rewrite zoom stack
69 for(int i=0;i<m_zoomStack.count();i++){
69 for(int i=0;i<m_zoomStack.count();i++){
70 QRectF r = m_zoomStack[i];
70 QRectF r = m_zoomStack[i];
71 qreal w = rect.width()/m_rect.width();
71 qreal w = rect.width()/m_rect.width();
72 qreal h = rect.height()/m_rect.height();
72 qreal h = rect.height()/m_rect.height();
73 QPointF tl = r.topLeft();
73 QPointF tl = r.topLeft();
74 tl.setX(tl.x()*w);
74 tl.setX(tl.x()*w);
75 tl.setY(tl.y()*h);
75 tl.setY(tl.y()*h);
76 QPointF br = r.bottomRight();
76 QPointF br = r.bottomRight();
77 br.setX(br.x()*w);
77 br.setX(br.x()*w);
78 br.setY(br.y()*h);
78 br.setY(br.y()*h);
79 r.setTopLeft(tl);
79 r.setTopLeft(tl);
80 r.setBottomRight(br);
80 r.setBottomRight(br);
81 m_zoomStack[i]=r;
81 m_zoomStack[i]=r;
82 }
82 }
83
83
84 m_rect = rect;
84 m_rect = rect;
85 Q_ASSERT(m_rect.isValid());
85 Q_ASSERT(m_rect.isValid());
86 emit geometryChanged(m_rect);
86 emit geometryChanged(m_rect);
87 }
87 }
88
88
89 int ChartPresenter::margin() const
89 int ChartPresenter::margin() const
90 {
90 {
91 return m_marginSize;
91 return m_marginSize;
92 }
92 }
93
93
94 void ChartPresenter::setMargin(int margin)
94 void ChartPresenter::setMargin(int margin)
95 {
95 {
96 m_marginSize = margin;
96 m_marginSize = margin;
97 }
97 }
98
98
99 void ChartPresenter::handleAxisAdded(QChartAxis* axis,Domain* domain)
99 void ChartPresenter::handleAxisAdded(QChartAxis* axis,Domain* domain)
100 {
100 {
101 AxisItem* item = new AxisItem(axis,this,axis==m_dataset->axisX()?AxisItem::X_AXIS : AxisItem::Y_AXIS,m_chart);
101 AxisItem* item = new AxisItem(axis,this,axis==m_dataset->axisX()?AxisItem::X_AXIS : AxisItem::Y_AXIS,m_chart);
102
102
103 if(m_options.testFlag(QChart::GridAxisAnimations)){
103 if(m_options.testFlag(QChart::GridAxisAnimations)){
104 m_animator->addAnimation(item);
104 m_animator->addAnimation(item);
105 }
105 }
106
106
107 if(axis==m_dataset->axisX()){
107 if(axis==m_dataset->axisX()){
108 m_chartTheme->decorate(axis,true);
108 m_chartTheme->decorate(axis,true);
109 QObject::connect(domain,SIGNAL(rangeXChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
109 QObject::connect(domain,SIGNAL(rangeXChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
110 //initialize
110 //initialize
111 item->handleRangeChanged(domain->minX(),domain->maxX(),domain->tickXCount());
111 item->handleRangeChanged(domain->minX(),domain->maxX(),domain->tickXCount());
112
112
113 }
113 }
114 else{
114 else{
115 m_chartTheme->decorate(axis,false);
115 m_chartTheme->decorate(axis,false);
116 QObject::connect(domain,SIGNAL(rangeYChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
116 QObject::connect(domain,SIGNAL(rangeYChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
117 //initialize
117 //initialize
118 item->handleRangeChanged(domain->minY(),domain->maxY(),domain->tickYCount());
118 item->handleRangeChanged(domain->minY(),domain->maxY(),domain->tickYCount());
119 }
119 }
120
120
121 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
121 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
122 //initialize
122 //initialize
123 item->handleGeometryChanged(m_rect);
123 item->handleGeometryChanged(m_rect);
124 m_axisItems.insert(axis, item);
124 m_axisItems.insert(axis, item);
125 }
125 }
126
126
127 void ChartPresenter::handleAxisRemoved(QChartAxis* axis)
127 void ChartPresenter::handleAxisRemoved(QChartAxis* axis)
128 {
128 {
129 AxisItem* item = m_axisItems.take(axis);
129 AxisItem* item = m_axisItems.take(axis);
130 Q_ASSERT(item);
130 Q_ASSERT(item);
131 if(m_animator) m_animator->removeAnimation(item);
131 if(m_animator) m_animator->removeAnimation(item);
132 delete item;
132 delete item;
133 }
133 }
134
134
135
135
136 void ChartPresenter::handleSeriesAdded(QSeries* series,Domain* domain)
136 void ChartPresenter::handleSeriesAdded(QSeries* series,Domain* domain)
137 {
137 {
138 ChartItem *item = 0 ;
138 ChartItem *item = 0 ;
139
139
140 switch(series->type())
140 switch(series->type())
141 {
141 {
142 case QSeries::SeriesTypeLine: {
142 case QSeries::SeriesTypeLine: {
143
143
144 QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
144 QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
145 LineChartItem* line = new LineChartItem(lineSeries,m_chart);
145 LineChartItem* line = new LineChartItem(lineSeries,m_chart);
146 if(m_options.testFlag(QChart::SeriesAnimations)) {
146 if(m_options.testFlag(QChart::SeriesAnimations)) {
147 m_animator->addAnimation(line);
147 m_animator->addAnimation(line);
148 }
148 }
149 m_chartTheme->decorate(lineSeries, m_dataset->seriesIndex(series));
149 m_chartTheme->decorate(lineSeries, m_dataset->seriesIndex(series));
150 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),line,SLOT(handleGeometryChanged(const QRectF&)));
150 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),line,SLOT(handleGeometryChanged(const QRectF&)));
151 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),line,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
151 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),line,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
152 item = line;
152 item = line;
153 break;
153 break;
154 }
154 }
155
155
156 case QSeries::SeriesTypeArea: {
156 case QSeries::SeriesTypeArea: {
157
157
158 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
158 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
159 AreaChartItem* area = new AreaChartItem(areaSeries,m_chart);
159 AreaChartItem* area = new AreaChartItem(areaSeries,m_chart);
160 if(m_options.testFlag(QChart::SeriesAnimations)) {
160 if(m_options.testFlag(QChart::SeriesAnimations)) {
161 m_animator->addAnimation(area->upperLineItem());
161 m_animator->addAnimation(area->upperLineItem());
162 if(areaSeries->lowerSeries()) m_animator->addAnimation(area->lowerLineItem());
162 if(areaSeries->lowerSeries()) m_animator->addAnimation(area->lowerLineItem());
163 }
163 }
164 m_chartTheme->decorate(areaSeries, m_dataset->seriesIndex(series));
164 m_chartTheme->decorate(areaSeries, m_dataset->seriesIndex(series));
165 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),area,SLOT(handleGeometryChanged(const QRectF&)));
165 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),area,SLOT(handleGeometryChanged(const QRectF&)));
166 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),area,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
166 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),area,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
167 item=area;
167 item=area;
168 break;
168 break;
169 }
169 }
170
170
171 case QSeries::SeriesTypeBar: {
171 case QSeries::SeriesTypeBar: {
172 QBarSeries* barSeries = static_cast<QBarSeries*>(series);
172 QBarSeries* barSeries = static_cast<QBarSeries*>(series);
173 BarPresenter* bar = new BarPresenter(barSeries,m_chart);
173 BarPresenter* bar = new BarPresenter(barSeries,m_chart);
174 if(m_options.testFlag(QChart::SeriesAnimations)) {
174 if(m_options.testFlag(QChart::SeriesAnimations)) {
175 // m_animator->addAnimation(bar);
175 // m_animator->addAnimation(bar);
176 }
176 }
177 m_chartTheme->decorate(barSeries, m_dataset->seriesIndex(barSeries));
177 m_chartTheme->decorate(barSeries, m_dataset->seriesIndex(barSeries));
178 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
178 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
179 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
179 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
180 item=bar;
180 item=bar;
181 break;
181 break;
182 }
182 }
183
183
184 case QSeries::SeriesTypeStackedBar: {
184 case QSeries::SeriesTypeStackedBar: {
185 QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
185 QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
186 StackedBarPresenter* bar = new StackedBarPresenter(stackedBarSeries,m_chart);
186 StackedBarPresenter* bar = new StackedBarPresenter(stackedBarSeries,m_chart);
187 if(m_options.testFlag(QChart::SeriesAnimations)) {
187 if(m_options.testFlag(QChart::SeriesAnimations)) {
188 // m_animator->addAnimation(bar);
188 // m_animator->addAnimation(bar);
189 }
189 }
190 m_chartTheme->decorate(stackedBarSeries, m_dataset->seriesIndex(stackedBarSeries));
190 m_chartTheme->decorate(stackedBarSeries, m_dataset->seriesIndex(stackedBarSeries));
191 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
191 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
192 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
192 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
193 item=bar;
193 item=bar;
194 break;
194 break;
195 }
195 }
196
196
197 case QSeries::SeriesTypePercentBar: {
197 case QSeries::SeriesTypePercentBar: {
198 QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
198 QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
199 PercentBarPresenter* bar = new PercentBarPresenter(percentBarSeries,m_chart);
199 PercentBarPresenter* bar = new PercentBarPresenter(percentBarSeries,m_chart);
200 if(m_options.testFlag(QChart::SeriesAnimations)) {
200 if(m_options.testFlag(QChart::SeriesAnimations)) {
201 // m_animator->addAnimation(bar);
201 // m_animator->addAnimation(bar);
202 }
202 }
203 m_chartTheme->decorate(percentBarSeries, m_dataset->seriesIndex(percentBarSeries));
203 m_chartTheme->decorate(percentBarSeries, m_dataset->seriesIndex(percentBarSeries));
204 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
204 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
205 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
205 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
206 item=bar;
206 item=bar;
207 break;
207 break;
208 }
208 }
209
209
210 case QSeries::SeriesTypeScatter: {
210 case QSeries::SeriesTypeScatter: {
211 QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
211 QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
212 ScatterChartItem *scatter = new ScatterChartItem(scatterSeries, m_chart);
212 ScatterChartItem *scatter = new ScatterChartItem(scatterSeries, m_chart);
213 if(m_options.testFlag(QChart::SeriesAnimations)) {
213 if(m_options.testFlag(QChart::SeriesAnimations)) {
214 m_animator->addAnimation(scatter);
214 m_animator->addAnimation(scatter);
215 }
215 }
216 m_chartTheme->decorate(scatterSeries, m_dataset->seriesIndex(series));
216 m_chartTheme->decorate(scatterSeries, m_dataset->seriesIndex(series));
217 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),scatter,SLOT(handleGeometryChanged(const QRectF&)));
217 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),scatter,SLOT(handleGeometryChanged(const QRectF&)));
218 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),scatter,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
218 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),scatter,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
219 item = scatter;
219 item = scatter;
220 break;
220 break;
221 }
221 }
222
222
223 case QSeries::SeriesTypePie: {
223 case QSeries::SeriesTypePie: {
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&)));
231 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),pie,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
231 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),pie,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
232 // Hide all from background when there is only piechart
232 // Hide all from background when there is only piechart
233 // TODO: refactor this ugly code... should be one setting for this
233 // TODO: refactor this ugly code... should be one setting for this
234 if (m_chartItems.count() == 0) {
234 if (m_chartItems.count() == 0) {
235 m_chart->axisX()->hide();
235 m_chart->axisX()->hide();
236 m_chart->axisY()->hide();
236 m_chart->axisY()->hide();
237 m_chart->setChartBackgroundBrush(Qt::transparent);
237 m_chart->setChartBackgroundBrush(Qt::transparent);
238 }
238 }
239 item=pie;
239 item=pie;
240 break;
240 break;
241 }
241 }
242
242
243 case QSeries::SeriesTypeSpline: {
243 case QSeries::SeriesTypeSpline: {
244 QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
244 QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
245 SplineChartItem* spline = new SplineChartItem(splineSeries, m_chart);
245 SplineChartItem* spline = new SplineChartItem(splineSeries, m_chart);
246 if(m_options.testFlag(QChart::SeriesAnimations)) {
246 if(m_options.testFlag(QChart::SeriesAnimations)) {
247 m_animator->addAnimation(spline);
247 m_animator->addAnimation(spline);
248 }
248 }
249 m_chartTheme->decorate(splineSeries, m_dataset->seriesIndex(series));
249 m_chartTheme->decorate(splineSeries, m_dataset->seriesIndex(series));
250 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),spline,SLOT(handleGeometryChanged(const QRectF&)));
250 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),spline,SLOT(handleGeometryChanged(const QRectF&)));
251 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),spline,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
251 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),spline,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
252 item=spline;
252 item=spline;
253 break;
253 break;
254 }
254 }
255 default: {
255 default: {
256 qDebug()<< "Series type" << series->type() << "not implemented.";
256 qDebug()<< "Series type" << series->type() << "not implemented.";
257 break;
257 break;
258 }
258 }
259 }
259 }
260
260
261 //initialize
261 //initialize
262 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
262 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
263 if(m_rect.isValid()) item->handleGeometryChanged(m_rect);
263 if(m_rect.isValid()) item->handleGeometryChanged(m_rect);
264 m_chartItems.insert(series,item);
264 m_chartItems.insert(series,item);
265 zoomReset();
265 zoomReset();
266 }
266 }
267
267
268 void ChartPresenter::handleSeriesRemoved(QSeries* series)
268 void ChartPresenter::handleSeriesRemoved(QSeries* series)
269 {
269 {
270 ChartItem* item = m_chartItems.take(series);
270 ChartItem* item = m_chartItems.take(series);
271 Q_ASSERT(item);
271 Q_ASSERT(item);
272 if(m_animator) {
272 if(m_animator) {
273 //small hack to handle area animations
273 //small hack to handle area animations
274 if(series->type()==QSeries::SeriesTypeArea){
274 if(series->type()==QSeries::SeriesTypeArea){
275 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
275 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
276 AreaChartItem* area = static_cast<AreaChartItem*>(item);
276 AreaChartItem* area = static_cast<AreaChartItem*>(item);
277 m_animator->removeAnimation(area->upperLineItem());
277 m_animator->removeAnimation(area->upperLineItem());
278 if(areaSeries->lowerSeries()) m_animator->addAnimation(area->lowerLineItem());
278 if(areaSeries->lowerSeries()) m_animator->addAnimation(area->lowerLineItem());
279 }else
279 }else
280 m_animator->removeAnimation(item);
280 m_animator->removeAnimation(item);
281 }
281 }
282 delete item;
282 delete item;
283 }
283 }
284
284
285 void ChartPresenter::setChartTheme(QChart::ChartTheme theme)
285 void ChartPresenter::setChartTheme(QChart::ChartTheme theme)
286 {
286 {
287 if(m_chartTheme && m_chartTheme->id() == theme) return;
287 if(m_chartTheme && m_chartTheme->id() == theme) return;
288 delete m_chartTheme;
288 delete m_chartTheme;
289 m_chartTheme = ChartTheme::createTheme(theme);
289 m_chartTheme = ChartTheme::createTheme(theme);
290 m_chartTheme->decorate(m_chart);
290 m_chartTheme->decorate(m_chart);
291 m_chartTheme->decorate(m_chart->legend());
291 m_chartTheme->decorate(m_chart->legend());
292 resetAllElements();
292 resetAllElements();
293 }
293 }
294
294
295 QChart::ChartTheme ChartPresenter::chartTheme()
295 QChart::ChartTheme ChartPresenter::chartTheme()
296 {
296 {
297 return m_chartTheme->id();
297 return m_chartTheme->id();
298 }
298 }
299
299
300 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
300 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
301 {
301 {
302 if(m_options!=options) {
302 if(m_options!=options) {
303
303
304 m_options=options;
304 m_options=options;
305
305
306 if(m_options!=QChart::NoAnimation && !m_animator) {
306 if(m_options!=QChart::NoAnimation && !m_animator) {
307 m_animator= new ChartAnimator(this);
307 m_animator= new ChartAnimator(this);
308
308
309 }
309 }
310 resetAllElements();
310 resetAllElements();
311 }
311 }
312
312
313 }
313 }
314
314
315 void ChartPresenter::resetAllElements()
315 void ChartPresenter::resetAllElements()
316 {
316 {
317 QList<QChartAxis*> axisList = m_axisItems.uniqueKeys();
317 QList<QChartAxis*> axisList = m_axisItems.uniqueKeys();
318 QList<QSeries*> seriesList = m_chartItems.uniqueKeys();
318 QList<QSeries*> seriesList = m_chartItems.uniqueKeys();
319
319
320 foreach(QChartAxis* axis, axisList) {
320 foreach(QChartAxis* axis, axisList) {
321 handleAxisRemoved(axis);
321 handleAxisRemoved(axis);
322 handleAxisAdded(axis,m_dataset->domain(axis));
322 handleAxisAdded(axis,m_dataset->domain(axis));
323 }
323 }
324 foreach(QSeries* series, seriesList) {
324 foreach(QSeries* series, seriesList) {
325 handleSeriesRemoved(series);
325 handleSeriesRemoved(series);
326 handleSeriesAdded(series,m_dataset->domain(series));
326 handleSeriesAdded(series,m_dataset->domain(series));
327 }
327 }
328 }
328 }
329
329
330 void ChartPresenter::zoomIn()
330 void ChartPresenter::zoomIn()
331 {
331 {
332 QRectF rect = geometry();
332 QRectF rect = geometry();
333 rect.setWidth(rect.width()/2);
333 rect.setWidth(rect.width()/2);
334 rect.setHeight(rect.height()/2);
334 rect.setHeight(rect.height()/2);
335 rect.moveCenter(geometry().center());
335 rect.moveCenter(geometry().center());
336 zoomIn(rect);
336 zoomIn(rect);
337 }
337 }
338
338
339 void ChartPresenter::zoomIn(const QRectF& rect)
339 void ChartPresenter::zoomIn(const QRectF& rect)
340 {
340 {
341 QRectF r = rect.normalized();
341 QRectF r = rect.normalized();
342 r.translate(-m_marginSize, -m_marginSize);
342 r.translate(-m_marginSize, -m_marginSize);
343 if(m_animator) {
343 if(m_animator) {
344
344
345 QPointF point(r.center().x()/geometry().width(),r.center().y()/geometry().height());
345 QPointF point(r.center().x()/geometry().width(),r.center().y()/geometry().height());
346 m_animator->setState(ChartAnimator::ZoomInState,point);
346 m_animator->setState(ChartAnimator::ZoomInState,point);
347 }
347 }
348 m_dataset->zoomInDomain(r,geometry().size());
348 m_dataset->zoomInDomain(r,geometry().size());
349 m_zoomStack<<r;
349 m_zoomStack<<r;
350 m_zoomIndex++;
350 m_zoomIndex++;
351 if(m_animator) {
351 if(m_animator) {
352 m_animator->setState(ChartAnimator::ShowState);
352 m_animator->setState(ChartAnimator::ShowState);
353 }
353 }
354 }
354 }
355
355
356 void ChartPresenter::zoomOut()
356 void ChartPresenter::zoomOut()
357 {
357 {
358 if(m_zoomIndex==0) return;
358 if(m_zoomIndex==0) return;
359 if(m_animator)
359 if(m_animator)
360 {
360 {
361 m_animator->setState(ChartAnimator::ZoomOutState);
361 m_animator->setState(ChartAnimator::ZoomOutState);
362 }
362 }
363 m_dataset->zoomOutDomain(m_zoomStack[m_zoomIndex-1],geometry().size());
363 m_dataset->zoomOutDomain(m_zoomStack[m_zoomIndex-1],geometry().size());
364 m_zoomIndex--;
364 m_zoomIndex--;
365 m_zoomStack.resize(m_zoomIndex);
365 m_zoomStack.resize(m_zoomIndex);
366 if(m_animator){
366 if(m_animator){
367 m_animator->setState(ChartAnimator::ShowState);
367 m_animator->setState(ChartAnimator::ShowState);
368 }
368 }
369 }
369 }
370
370
371 void ChartPresenter::zoomReset()
371 void ChartPresenter::zoomReset()
372 {
372 {
373 m_zoomIndex=0;
373 m_zoomIndex=0;
374 m_zoomStack.resize(m_zoomIndex);
374 m_zoomStack.resize(m_zoomIndex);
375 }
375 }
376
376
377 void ChartPresenter::scroll(int dx,int dy)
377 void ChartPresenter::scroll(int dx,int dy)
378 {
378 {
379 if(m_animator){
379 if(m_animator){
380 if(dx<0) m_animator->setState(ChartAnimator::ScrollLeftState,QPointF());
380 if(dx<0) m_animator->setState(ChartAnimator::ScrollLeftState,QPointF());
381 if(dx>0) m_animator->setState(ChartAnimator::ScrollRightState,QPointF());
381 if(dx>0) m_animator->setState(ChartAnimator::ScrollRightState,QPointF());
382 if(dy<0) m_animator->setState(ChartAnimator::ScrollUpState,QPointF());
382 if(dy<0) m_animator->setState(ChartAnimator::ScrollUpState,QPointF());
383 if(dy>0) m_animator->setState(ChartAnimator::ScrollDownState,QPointF());
383 if(dy>0) m_animator->setState(ChartAnimator::ScrollDownState,QPointF());
384 }
384 }
385
385
386 m_dataset->scrollDomain(dx,dy,geometry().size());
386 m_dataset->scrollDomain(dx,dy,geometry().size());
387
387
388 if(m_animator){
388 if(m_animator){
389 m_animator->setState(ChartAnimator::ShowState);
389 m_animator->setState(ChartAnimator::ShowState);
390 }
390 }
391 }
391 }
392
392
393 QChart::AnimationOptions ChartPresenter::animationOptions() const
393 QChart::AnimationOptions ChartPresenter::animationOptions() const
394 {
394 {
395 return m_options;
395 return m_options;
396 }
396 }
397
397
398
398
399 #include "moc_chartpresenter_p.cpp"
399 #include "moc_chartpresenter_p.cpp"
400
400
401 QTCOMMERCIALCHART_END_NAMESPACE
401 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,144 +1,185
1 #include "piechartitem_p.h"
1 #include "piechartitem_p.h"
2 #include "pieslice_p.h"
2 #include "pieslice_p.h"
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
9
10
10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11
12
12 PieChartItem::PieChartItem(QGraphicsItem *parent, QPieSeries *series)
13 PieChartItem::PieChartItem(QGraphicsItem *parent, QPieSeries *series)
13 :ChartItem(parent),
14 :ChartItem(parent),
14 m_series(series)
15 m_series(series)
15 {
16 {
16 Q_ASSERT(series);
17 Q_ASSERT(series);
17 connect(series, SIGNAL(changed()), this, SLOT(handleSeriesChanged()));
18 connect(series, SIGNAL(changed()), this, SLOT(handleSeriesChanged()));
18
19
19 // Note: the following does not affect as long as the item does not have anything to paint
20 // Note: the following does not affect as long as the item does not have anything to paint
20 setZValue(ChartPresenter::PieSeriesZValue);
21 setZValue(ChartPresenter::PieSeriesZValue);
21 }
22 }
22
23
23 PieChartItem::~PieChartItem()
24 PieChartItem::~PieChartItem()
24 {
25 {
25 // slices deleted automatically through QGraphicsItem
26 // slices deleted automatically through QGraphicsItem
26 }
27 }
27
28
28 void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
29 void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
29 {
30 {
30 Q_UNUSED(painter)
31 Q_UNUSED(painter)
31 // TODO: paint shadows for all components
32 // TODO: paint shadows for all components
32 // - get paths from items & merge & offset and draw with shadow color?
33 // - get paths from items & merge & offset and draw with shadow color?
33 //painter->setBrush(QBrush(Qt::red));
34 //painter->setBrush(QBrush(Qt::red));
34 //painter->drawRect(m_debugRect);
35 //painter->drawRect(m_debugRect);
35 }
36 }
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
52 void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal)
61 void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal)
53 {
62 {
54 // TODO
63 // TODO
55 }
64 }
56
65
57 void PieChartItem::handleGeometryChanged(const QRectF& rect)
66 void PieChartItem::handleGeometryChanged(const QRectF& rect)
58 {
67 {
59 prepareGeometryChange();
68 prepareGeometryChange();
60 m_rect = rect;
69 m_rect = rect;
61 QVector<PieSliceLayout> sliceLayout = calculateLayout();
70 QVector<PieSliceLayout> sliceLayout = calculateLayout();
62 applyLayout(sliceLayout);
71 applyLayout(sliceLayout);
63 update();
72 update();
64 }
73 }
65
74
66
75
67 QVector<PieSliceLayout> PieChartItem::calculateLayout()
76 QVector<PieSliceLayout> PieChartItem::calculateLayout()
68 {
77 {
69 // find pie center coordinates
78 // find pie center coordinates
70 QPointF center;
79 QPointF center;
71 center.setX(m_rect.left() + (m_rect.width() * m_series->pieHorizontalPosition()));
80 center.setX(m_rect.left() + (m_rect.width() * m_series->pieHorizontalPosition()));
72 center.setY(m_rect.top() + (m_rect.height() * m_series->pieVerticalPosition()));
81 center.setY(m_rect.top() + (m_rect.height() * m_series->pieVerticalPosition()));
73
82
74 // find maximum radius for pie
83 // find maximum radius for pie
75 qreal radius = m_rect.height() / 2;
84 qreal radius = m_rect.height() / 2;
76 if (m_rect.width() < m_rect.height())
85 if (m_rect.width() < m_rect.height())
77 radius = m_rect.width() / 2;
86 radius = m_rect.width() / 2;
78
87
79 // apply size factor
88 // apply size factor
80 radius *= m_series->pieSize();
89 radius *= m_series->pieSize();
81
90
82 QVector<PieSliceLayout> layout;
91 QVector<PieSliceLayout> layout;
83 foreach (QPieSlice* s, m_series->slices()) {
92 foreach (QPieSlice* s, m_series->slices()) {
84 PieSliceLayout sliceLayout;
93 PieSliceLayout sliceLayout;
85 sliceLayout.m_data = s;
94 sliceLayout.m_data = s;
86 sliceLayout.m_center = PieSlice::sliceCenter(center, radius, s);
95 sliceLayout.m_center = PieSlice::sliceCenter(center, radius, s);
87 sliceLayout.m_radius = radius;
96 sliceLayout.m_radius = radius;
88 sliceLayout.m_startAngle = s->startAngle();
97 sliceLayout.m_startAngle = s->startAngle();
89 sliceLayout.m_angleSpan = s->m_angleSpan;
98 sliceLayout.m_angleSpan = s->m_angleSpan;
90 layout << sliceLayout;
99 layout << sliceLayout;
91 }
100 }
92
101
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
108 // find slice
125 // find slice
109 PieSlice *slice = m_slices.value(l.m_data);
126 PieSlice *slice = m_slices.value(l.m_data);
110 if (!slice) {
127 if (!slice) {
111 // add a new slice
128 // add a new slice
112 slice = new PieSlice(this);
129 slice = new PieSlice(this);
113 m_slices.insert(l.m_data, slice);
130 m_slices.insert(l.m_data, slice);
114
131
115 // connect signals
132 // connect signals
116 connect(l.m_data, SIGNAL(changed()), this, SLOT(handleSliceChanged()));
133 connect(l.m_data, SIGNAL(changed()), this, SLOT(handleSliceChanged()));
117 connect(slice, SIGNAL(clicked()), l.m_data, SIGNAL(clicked()));
134 connect(slice, SIGNAL(clicked()), l.m_data, SIGNAL(clicked()));
118 connect(slice, SIGNAL(hoverEnter()), l.m_data, SIGNAL(hoverEnter()));
135 connect(slice, SIGNAL(hoverEnter()), l.m_data, SIGNAL(hoverEnter()));
119 connect(slice, SIGNAL(hoverLeave()), l.m_data, SIGNAL(hoverLeave()));
136 connect(slice, SIGNAL(hoverLeave()), l.m_data, SIGNAL(hoverLeave()));
120 }
137 }
121
138
122 // update
139 // update
123 slice->setLayout(l);
140 slice->setLayout(l);
124 slice->updateGeometry();
141 slice->updateGeometry();
125 slice->update();
142 slice->update();
126 }
143 }
127
144
128 // delete slices
145 // delete slices
129 foreach (QPieSlice *s, m_slices.keys()) {
146 foreach (QPieSlice *s, m_slices.keys()) {
130
147
131 bool found = false;
148 bool found = false;
132 foreach (PieSliceLayout l, layout) {
149 foreach (PieSliceLayout l, layout) {
133 if (l.m_data == s)
150 if (l.m_data == s)
134 found = true;
151 found = true;
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"
143
184
144 QTCOMMERCIALCHART_END_NAMESPACE
185 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,48 +1,51
1 #ifndef PIECHARTITEM_H
1 #ifndef PIECHARTITEM_H
2 #define PIECHARTITEM_H
2 #define PIECHARTITEM_H
3
3
4 #include "qpieseries.h"
4 #include "qpieseries.h"
5 #include "chartitem_p.h"
5 #include "chartitem_p.h"
6 #include "pieslice_p.h"
6 #include "pieslice_p.h"
7
7
8 class QGraphicsItem;
8 class QGraphicsItem;
9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 class QPieSlice;
10 class QPieSlice;
11
11
12 class PieChartItem : public QObject, public ChartItem
12 class PieChartItem : public QObject, public ChartItem
13 {
13 {
14 Q_OBJECT
14 Q_OBJECT
15
15
16 public:
16 public:
17 // TODO: use a generic data class instead of x and y
17 // TODO: use a generic data class instead of x and y
18 PieChartItem(QGraphicsItem *parent, QPieSeries *series);
18 PieChartItem(QGraphicsItem *parent, QPieSeries *series);
19 ~PieChartItem();
19 ~PieChartItem();
20
20
21 public: // from QGraphicsItem
21 public: // from QGraphicsItem
22 QRectF boundingRect() const { return m_rect; }
22 QRectF boundingRect() const { return m_rect; }
23 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
23 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
24
24
25 public Q_SLOTS:
25 public Q_SLOTS:
26 void handleSeriesChanged();
26 void handleSeriesChanged();
27 void handleSliceChanged();
27 void handleSliceChanged();
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;
38 QHash<QPieSlice*, PieSlice*> m_slices;
41 QHash<QPieSlice*, PieSlice*> m_slices;
39 QPieSeries *m_series;
42 QPieSeries *m_series;
40 QRectF m_rect;
43 QRectF m_rect;
41 QPointF m_pieCenter;
44 QPointF m_pieCenter;
42 qreal m_pieRadius;
45 qreal m_pieRadius;
43 QRectF m_debugRect;
46 QRectF m_debugRect;
44 };
47 };
45
48
46 QTCOMMERCIALCHART_END_NAMESPACE
49 QTCOMMERCIALCHART_END_NAMESPACE
47
50
48 #endif // PIECHARTITEM_H
51 #endif // PIECHARTITEM_H
@@ -1,208 +1,203
1 #include "pieslice_p.h"
1 #include "pieslice_p.h"
2 #include "piechartitem_p.h"
2 #include "piechartitem_p.h"
3 #include "qpieseries.h"
3 #include "qpieseries.h"
4 #include "qpieslice.h"
4 #include "qpieslice.h"
5 #include "chartpresenter_p.h"
5 #include "chartpresenter_p.h"
6 #include <QPainter>
6 #include <QPainter>
7 #include <QDebug>
7 #include <QDebug>
8 #include <qmath.h>
8 #include <qmath.h>
9 #include <QGraphicsSceneEvent>
9 #include <QGraphicsSceneEvent>
10 #include <QTime>
10 #include <QTime>
11
11
12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
13
13
14 #define PI 3.14159265 // TODO: is this defined in some header?
14 #define PI 3.14159265 // TODO: is this defined in some header?
15
15
16 QPointF offset(qreal angle, qreal length)
16 QPointF offset(qreal angle, qreal length)
17 {
17 {
18 qreal dx = qSin(angle*(PI/180)) * length;
18 qreal dx = qSin(angle*(PI/180)) * length;
19 qreal dy = qCos(angle*(PI/180)) * length;
19 qreal dy = qCos(angle*(PI/180)) * length;
20 return QPointF(dx, -dy);
20 return QPointF(dx, -dy);
21 }
21 }
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),
30 m_labelArmLengthFactor(0)
28 m_labelArmLengthFactor(0)
31 {
29 {
32 setAcceptHoverEvents(true);
30 setAcceptHoverEvents(true);
33 setAcceptedMouseButtons(Qt::LeftButton);
31 setAcceptedMouseButtons(Qt::LeftButton);
34 setZValue(ChartPresenter::PieSeriesZValue);
32 setZValue(ChartPresenter::PieSeriesZValue);
35 }
33 }
36
34
37 PieSlice::~PieSlice()
35 PieSlice::~PieSlice()
38 {
36 {
39
37
40 }
38 }
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
48 {
46 {
49 // Don't include the label and label arm.
47 // Don't include the label and label arm.
50 // This is used to detect a mouse clicks. We do not want clicks from label.
48 // This is used to detect a mouse clicks. We do not want clicks from label.
51 return m_slicePath;
49 return m_slicePath;
52 }
50 }
53
51
54 void PieSlice::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
52 void PieSlice::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
55 {
53 {
56 painter->setClipRect(parentItem()->boundingRect());
54 painter->setClipRect(parentItem()->boundingRect());
57
55
58 painter->save();
56 painter->save();
59 painter->setPen(m_slicePen);
57 painter->setPen(m_slicePen);
60 painter->setBrush(m_sliceBrush);
58 painter->setBrush(m_sliceBrush);
61 painter->drawPath(m_slicePath);
59 painter->drawPath(m_slicePath);
62 painter->restore();
60 painter->restore();
63
61
64 if (m_labelVisible) {
62 if (m_labelVisible) {
65 painter->save();
63 painter->save();
66 painter->setPen(m_labelArmPen);
64 painter->setPen(m_labelArmPen);
67 painter->drawPath(m_labelArmPath);
65 painter->drawPath(m_labelArmPath);
68 painter->restore();
66 painter->restore();
69
67
70 painter->setFont(m_labelFont);
68 painter->setFont(m_labelFont);
71 painter->drawText(m_labelTextRect.bottomLeft(), m_labelText);
69 painter->drawText(m_labelTextRect.bottomLeft(), m_labelText);
72 }
70 }
73 }
71 }
74
72
75 void PieSlice::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
73 void PieSlice::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
76 {
74 {
77 emit hoverEnter();
75 emit hoverEnter();
78 }
76 }
79
77
80 void PieSlice::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
78 void PieSlice::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
81 {
79 {
82 emit hoverLeave();
80 emit hoverLeave();
83 }
81 }
84
82
85 void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/)
83 void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/)
86 {
84 {
87 emit clicked();
85 emit clicked();
88 }
86 }
89
87
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()
97 {
94 {
98 if (m_layout.m_radius <= 0)
95 if (m_layout.m_radius <= 0)
99 return;
96 return;
100
97
101 prepareGeometryChange();
98 prepareGeometryChange();
102
99
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);
110
107
111 // update label arm path
108 // update label arm path
112 QPointF labelTextStart;
109 QPointF labelTextStart;
113 m_labelArmPath = labelArmPath(armStart, centerAngle, m_layout.m_radius * m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
110 m_labelArmPath = labelArmPath(armStart, centerAngle, m_layout.m_radius * m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
114
111
115 // update text position
112 // update text position
116 m_labelTextRect.moveBottomLeft(labelTextStart);
113 m_labelTextRect.moveBottomLeft(labelTextStart);
117
114
118 //qDebug() << "PieSlice::updateGeometry" << m_labelText << boundingRect() << m_startAngle << m_startAngle + m_angleSpan;
115 //qDebug() << "PieSlice::updateGeometry" << m_labelText << boundingRect() << m_startAngle << m_startAngle + m_angleSpan;
119 }
116 }
120
117
121 void PieSlice::updateData(const QPieSlice* sliceData)
118 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();
130 m_sliceBrush = sliceData->sliceBrush();
125 m_sliceBrush = sliceData->sliceBrush();
131
126
132 m_labelVisible = sliceData->isLabelVisible();
127 m_labelVisible = sliceData->isLabelVisible();
133 m_labelText = sliceData->label();
128 m_labelText = sliceData->label();
134 m_labelFont = sliceData->labelFont();
129 m_labelFont = sliceData->labelFont();
135 m_labelArmLengthFactor = sliceData->labelArmLengthFactor();
130 m_labelArmLengthFactor = sliceData->labelArmLengthFactor();
136 m_labelArmPen = sliceData->labelArmPen();
131 m_labelArmPen = sliceData->labelArmPen();
137 }
132 }
138
133
139 QPointF PieSlice::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
134 QPointF PieSlice::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
140 {
135 {
141 if (slice->isExploded()) {
136 if (slice->isExploded()) {
142 qreal centerAngle = slice->startAngle() + (slice->m_angleSpan/2);
137 qreal centerAngle = slice->startAngle() + (slice->m_angleSpan/2);
143 qreal len = radius * slice->explodeDistanceFactor();
138 qreal len = radius * slice->explodeDistanceFactor();
144 qreal dx = qSin(centerAngle*(PI/180)) * len;
139 qreal dx = qSin(centerAngle*(PI/180)) * len;
145 qreal dy = -qCos(centerAngle*(PI/180)) * len;
140 qreal dy = -qCos(centerAngle*(PI/180)) * len;
146 point += QPointF(dx, dy);
141 point += QPointF(dx, dy);
147 }
142 }
148 return point;
143 return point;
149 }
144 }
150
145
151 QPainterPath PieSlice::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal* centerAngle, QPointF* armStart)
146 QPainterPath PieSlice::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal* centerAngle, QPointF* armStart)
152 {
147 {
153 // calculate center angle
148 // calculate center angle
154 *centerAngle = startAngle + (angleSpan/2);
149 *centerAngle = startAngle + (angleSpan/2);
155
150
156 // calculate slice rectangle
151 // calculate slice rectangle
157 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
152 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
158
153
159 // slice path
154 // slice path
160 // TODO: draw the shape so that it might have a hole in the center
155 // TODO: draw the shape so that it might have a hole in the center
161 QPainterPath path;
156 QPainterPath path;
162 path.moveTo(rect.center());
157 path.moveTo(rect.center());
163 path.arcTo(rect, -startAngle + 90, -angleSpan);
158 path.arcTo(rect, -startAngle + 90, -angleSpan);
164 path.closeSubpath();
159 path.closeSubpath();
165
160
166 // calculate label arm start point
161 // calculate label arm start point
167 *armStart = center;
162 *armStart = center;
168 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
163 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
169
164
170 return path;
165 return path;
171 }
166 }
172
167
173 QPainterPath PieSlice::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart)
168 QPainterPath PieSlice::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart)
174 {
169 {
175 qreal dx = qSin(angle*(PI/180)) * length;
170 qreal dx = qSin(angle*(PI/180)) * length;
176 qreal dy = -qCos(angle*(PI/180)) * length;
171 qreal dy = -qCos(angle*(PI/180)) * length;
177 QPointF parm1 = start + QPointF(dx, dy);
172 QPointF parm1 = start + QPointF(dx, dy);
178
173
179 QPointF parm2 = parm1;
174 QPointF parm2 = parm1;
180 if (angle < 180) { // arm swings the other way on the left side
175 if (angle < 180) { // arm swings the other way on the left side
181 parm2 += QPointF(textWidth, 0);
176 parm2 += QPointF(textWidth, 0);
182 *textStart = parm1;
177 *textStart = parm1;
183 }
178 }
184 else {
179 else {
185 parm2 += QPointF(-textWidth,0);
180 parm2 += QPointF(-textWidth,0);
186 *textStart = parm2;
181 *textStart = parm2;
187 }
182 }
188
183
189 // elevate the text position a bit so that it does not hit the line
184 // elevate the text position a bit so that it does not hit the line
190 *textStart += QPointF(0, -5);
185 *textStart += QPointF(0, -5);
191
186
192 QPainterPath path;
187 QPainterPath path;
193 path.moveTo(start);
188 path.moveTo(start);
194 path.lineTo(parm1);
189 path.lineTo(parm1);
195 path.lineTo(parm2);
190 path.lineTo(parm2);
196
191
197 return path;
192 return path;
198 }
193 }
199
194
200 QRectF PieSlice::labelTextRect(QFont font, QString text)
195 QRectF PieSlice::labelTextRect(QFont font, QString text)
201 {
196 {
202 QFontMetricsF fm(font);
197 QFontMetricsF fm(font);
203 return fm.boundingRect(text);
198 return fm.boundingRect(text);
204 }
199 }
205
200
206 #include "moc_pieslice_p.cpp"
201 #include "moc_pieslice_p.cpp"
207
202
208 QTCOMMERCIALCHART_END_NAMESPACE
203 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,82 +1,80
1 #ifndef PIESLICE_H
1 #ifndef PIESLICE_H
2 #define PIESLICE_H
2 #define PIESLICE_H
3
3
4 #include "qchartglobal.h"
4 #include "qchartglobal.h"
5 #include "charttheme_p.h"
5 #include "charttheme_p.h"
6 #include "qpieseries.h"
6 #include "qpieseries.h"
7 #include <QGraphicsItem>
7 #include <QGraphicsItem>
8 #include <QRectF>
8 #include <QRectF>
9 #include <QColor>
9 #include <QColor>
10 #include <QPen>
10 #include <QPen>
11
11
12 #define PIESLICE_LABEL_GAP 5
12 #define PIESLICE_LABEL_GAP 5
13
13
14 QTCOMMERCIALCHART_BEGIN_NAMESPACE
14 QTCOMMERCIALCHART_BEGIN_NAMESPACE
15 class PieChartItem;
15 class PieChartItem;
16 class PieSliceLabel;
16 class PieSliceLabel;
17 class QPieSlice;
17 class QPieSlice;
18
18
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;
26 qreal m_angleSpan;
26 qreal m_angleSpan;
27 };
27 };
28
28
29 class PieSlice : public QGraphicsObject
29 class PieSlice : public QGraphicsObject
30 {
30 {
31 Q_OBJECT
31 Q_OBJECT
32
32
33 public:
33 public:
34 PieSlice(QGraphicsItem* parent = 0);
34 PieSlice(QGraphicsItem* parent = 0);
35 ~PieSlice();
35 ~PieSlice();
36
36
37 public: // from QGraphicsItem
37 public: // from QGraphicsItem
38 QRectF boundingRect() const;
38 QRectF boundingRect() const;
39 QPainterPath shape() const;
39 QPainterPath shape() const;
40 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
40 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
41 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
41 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
42 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
42 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
43 void mousePressEvent(QGraphicsSceneMouseEvent *event);
43 void mousePressEvent(QGraphicsSceneMouseEvent *event);
44
44
45 Q_SIGNALS:
45 Q_SIGNALS:
46 void clicked();
46 void clicked();
47 void hoverEnter();
47 void hoverEnter();
48 void hoverLeave();
48 void hoverLeave();
49
49
50 public:
50 public:
51 void setLayout(PieSliceLayout layout);
51 void setLayout(PieSliceLayout layout);
52 void updateGeometry();
52 void updateGeometry();
53 void updateData(const QPieSlice *sliceData);
53 void updateData(const QPieSlice *sliceData);
54 static QPointF sliceCenter(QPointF point, qreal radius, QPieSlice *slice);
54 static QPointF sliceCenter(QPointF point, qreal radius, QPieSlice *slice);
55 static QPainterPath slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal* centerAngle, QPointF* armStart);
55 static QPainterPath slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal* centerAngle, QPointF* armStart);
56 static QPainterPath labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart);
56 static QPainterPath labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart);
57 static QRectF labelTextRect(QFont font, QString text);
57 static QRectF labelTextRect(QFont font, QString text);
58
58
59 private:
59 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;
68 QPen m_slicePen;
66 QPen m_slicePen;
69 QBrush m_sliceBrush;
67 QBrush m_sliceBrush;
70
68
71 QPainterPath m_labelArmPath;
69 QPainterPath m_labelArmPath;
72 qreal m_labelArmLengthFactor;
70 qreal m_labelArmLengthFactor;
73 QPen m_labelArmPen;
71 QPen m_labelArmPen;
74
72
75 QRectF m_labelTextRect;
73 QRectF m_labelTextRect;
76 QFont m_labelFont;
74 QFont m_labelFont;
77 QString m_labelText;
75 QString m_labelText;
78 };
76 };
79
77
80 QTCOMMERCIALCHART_END_NAMESPACE
78 QTCOMMERCIALCHART_END_NAMESPACE
81
79
82 #endif // PIESLICE_H
80 #endif // PIESLICE_H
@@ -1,643 +1,649
1 #include "qpieseries.h"
1 #include "qpieseries.h"
2 #include "qpieslice.h"
2 #include "qpieslice.h"
3 #include <QDebug>
3 #include <QDebug>
4
4
5 QTCOMMERCIALCHART_BEGIN_NAMESPACE
5 QTCOMMERCIALCHART_BEGIN_NAMESPACE
6
6
7
7
8 /*!
8 /*!
9 \class QPieSeries::ChangeSet
9 \class QPieSeries::ChangeSet
10 \brief Defines the changes in the series.
10 \brief Defines the changes in the series.
11
11
12 Contains the changes that have occurred in the series. Lists of added, changed and removed slices.
12 Contains the changes that have occurred in the series. Lists of added, changed and removed slices.
13
13
14 \sa QPieSeries::changed()
14 \sa QPieSeries::changed()
15 */
15 */
16
16
17 /*!
17 /*!
18 \internal
18 \internal
19 */
19 */
20 void QPieSeries::ChangeSet::appendAdded(QPieSlice* slice)
20 void QPieSeries::ChangeSet::appendAdded(QPieSlice* slice)
21 {
21 {
22 if (!m_added.contains(slice))
22 if (!m_added.contains(slice))
23 m_added << slice;
23 m_added << slice;
24 }
24 }
25
25
26 /*!
26 /*!
27 \internal
27 \internal
28 */
28 */
29 void QPieSeries::ChangeSet::appendAdded(QList<QPieSlice*> slices)
29 void QPieSeries::ChangeSet::appendAdded(QList<QPieSlice*> slices)
30 {
30 {
31 foreach (QPieSlice* s, slices)
31 foreach (QPieSlice* s, slices)
32 appendAdded(s);
32 appendAdded(s);
33 }
33 }
34
34
35 /*!
35 /*!
36 \internal
36 \internal
37 */
37 */
38 void QPieSeries::ChangeSet::appendChanged(QPieSlice* slice)
38 void QPieSeries::ChangeSet::appendChanged(QPieSlice* slice)
39 {
39 {
40 if (!m_changed.contains(slice))
40 if (!m_changed.contains(slice))
41 m_changed << slice;
41 m_changed << slice;
42 }
42 }
43
43
44 /*!
44 /*!
45 \internal
45 \internal
46 */
46 */
47 void QPieSeries::ChangeSet::appendRemoved(QPieSlice* slice)
47 void QPieSeries::ChangeSet::appendRemoved(QPieSlice* slice)
48 {
48 {
49 if (!m_removed.contains(slice))
49 if (!m_removed.contains(slice))
50 m_removed << slice;
50 m_removed << slice;
51 }
51 }
52
52
53 /*!
53 /*!
54 Returns a list of slices that have been added to the series.
54 Returns a list of slices that have been added to the series.
55 \sa QPieSeries::changed()
55 \sa QPieSeries::changed()
56 */
56 */
57 QList<QPieSlice*> QPieSeries::ChangeSet::added() const
57 QList<QPieSlice*> QPieSeries::ChangeSet::added() const
58 {
58 {
59 return m_added;
59 return m_added;
60 }
60 }
61
61
62 /*!
62 /*!
63 Returns a list of slices that have been changed in the series.
63 Returns a list of slices that have been changed in the series.
64 \sa QPieSeries::changed()
64 \sa QPieSeries::changed()
65 */
65 */
66 QList<QPieSlice*> QPieSeries::ChangeSet::changed() const
66 QList<QPieSlice*> QPieSeries::ChangeSet::changed() const
67 {
67 {
68 return m_changed;
68 return m_changed;
69 }
69 }
70
70
71 /*!
71 /*!
72 Returns a list of slices that have been removed from the series.
72 Returns a list of slices that have been removed from the series.
73 \sa QPieSeries::changed()
73 \sa QPieSeries::changed()
74 */
74 */
75 QList<QPieSlice*> QPieSeries::ChangeSet::removed() const
75 QList<QPieSlice*> QPieSeries::ChangeSet::removed() const
76 {
76 {
77 return m_removed;
77 return m_removed;
78 }
78 }
79
79
80
80
81 /*!
81 /*!
82 Returns true if there are no added/changed or removed slices in the change set.
82 Returns true if there are no added/changed or removed slices in the change set.
83 */
83 */
84 bool QPieSeries::ChangeSet::isEmpty() const
84 bool QPieSeries::ChangeSet::isEmpty() const
85 {
85 {
86 if (m_added.count() || m_changed.count() || m_removed.count())
86 if (m_added.count() || m_changed.count() || m_removed.count())
87 return false;
87 return false;
88 return true;
88 return true;
89 }
89 }
90
90
91 /*!
91 /*!
92 \class QPieSeries
92 \class QPieSeries
93 \brief Pie series API for QtCommercial Charts
93 \brief Pie series API for QtCommercial Charts
94
94
95 The pie series defines a pie chart which consists of pie slices which are QPieSlice objects.
95 The pie series defines a pie chart which consists of pie slices which are QPieSlice objects.
96 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
96 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
97 The actual slice size is determined by that relative value.
97 The actual slice size is determined by that relative value.
98
98
99 By default the pie is defined as a full pie but it can be a partial pie.
99 By default the pie is defined as a full pie but it can be a partial pie.
100 This can be done by setting a starting angle and angle span to the series.
100 This can be done by setting a starting angle and angle span to the series.
101 */
101 */
102
102
103 /*!
103 /*!
104 Constructs a series object which is a child of \a parent.
104 Constructs a series object which is a child of \a parent.
105 */
105 */
106 QPieSeries::QPieSeries(QObject *parent) :
106 QPieSeries::QPieSeries(QObject *parent) :
107 QSeries(parent),
107 QSeries(parent),
108 m_pieRelativeHorPos(0.5),
108 m_pieRelativeHorPos(0.5),
109 m_pieRelativeVerPos(0.5),
109 m_pieRelativeVerPos(0.5),
110 m_pieRelativeSize(0.7),
110 m_pieRelativeSize(0.7),
111 m_pieStartAngle(0),
111 m_pieStartAngle(0),
112 m_pieEndAngle(360),
112 m_pieEndAngle(360),
113 m_total(0)
113 m_total(0)
114 {
114 {
115
115
116 }
116 }
117
117
118 /*!
118 /*!
119 Destroys the object. Note that adding series to QChart transfers the ownership to the chart.
119 Destroys the object. Note that adding series to QChart transfers the ownership to the chart.
120 */
120 */
121 QPieSeries::~QPieSeries()
121 QPieSeries::~QPieSeries()
122 {
122 {
123
123
124 }
124 }
125
125
126 /*!
126 /*!
127 Returns QChartSeries::SeriesTypePie.
127 Returns QChartSeries::SeriesTypePie.
128 */
128 */
129 QSeries::QSeriesType QPieSeries::type() const
129 QSeries::QSeriesType QPieSeries::type() const
130 {
130 {
131 return QSeries::SeriesTypePie;
131 return QSeries::SeriesTypePie;
132 }
132 }
133
133
134 /*!
134 /*!
135 Sets an array of \a slices to the series replacing the existing slices.
135 Sets an array of \a slices to the series replacing the existing slices.
136 Slice ownership is passed to the series.
136 Slice ownership is passed to the series.
137 */
137 */
138 void QPieSeries::replace(QList<QPieSlice*> slices)
138 void QPieSeries::replace(QList<QPieSlice*> slices)
139 {
139 {
140 clear();
140 clear();
141 add(slices);
141 add(slices);
142 }
142 }
143
143
144 /*!
144 /*!
145 Adds an array of \a slices to the series.
145 Adds an array of \a slices to the series.
146 Slice ownership is passed to the series.
146 Slice ownership is passed to the series.
147 */
147 */
148 void QPieSeries::add(QList<QPieSlice*> slices)
148 void QPieSeries::add(QList<QPieSlice*> slices)
149 {
149 {
150 foreach (QPieSlice* s, slices) {
150 foreach (QPieSlice* s, slices) {
151 s->setParent(this);
151 s->setParent(this);
152 m_slices << s;
152 m_slices << s;
153 }
153 }
154
154
155 updateDerivativeData();
155 updateDerivativeData();
156
156
157 foreach (QPieSlice* s, slices) {
157 foreach (QPieSlice* s, slices) {
158 connect(s, SIGNAL(changed()), this, SLOT(sliceChanged()));
158 connect(s, SIGNAL(changed()), this, SLOT(sliceChanged()));
159 connect(s, SIGNAL(clicked()), this, SLOT(sliceClicked()));
159 connect(s, SIGNAL(clicked()), this, SLOT(sliceClicked()));
160 connect(s, SIGNAL(hoverEnter()), this, SLOT(sliceHoverEnter()));
160 connect(s, SIGNAL(hoverEnter()), this, SLOT(sliceHoverEnter()));
161 connect(s, SIGNAL(hoverLeave()), this, SLOT(sliceHoverLeave()));
161 connect(s, SIGNAL(hoverLeave()), this, SLOT(sliceHoverLeave()));
162 }
162 }
163
163
164 emit changed();
164 emit changed();
165 }
165 }
166
166
167 /*!
167 /*!
168 Adds a single \a slice to the series.
168 Adds a single \a slice to the series.
169 Slice ownership is passed to the series.
169 Slice ownership is passed to the series.
170 */
170 */
171 void QPieSeries::add(QPieSlice* slice)
171 void QPieSeries::add(QPieSlice* slice)
172 {
172 {
173 add(QList<QPieSlice*>() << slice);
173 add(QList<QPieSlice*>() << slice);
174 }
174 }
175
175
176 /*!
176 /*!
177 Adds a single \a slice to the series and returns a reference to the series.
177 Adds a single \a slice to the series and returns a reference to the series.
178 Slice ownership is passed to the series.
178 Slice ownership is passed to the series.
179 */
179 */
180 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
180 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
181 {
181 {
182 add(slice);
182 add(slice);
183 return *this;
183 return *this;
184 }
184 }
185
185
186
186
187 /*!
187 /*!
188 Adds a single slice to the series with give \a value and \a name.
188 Adds a single slice to the series with give \a value and \a name.
189 Slice ownership is passed to the series.
189 Slice ownership is passed to the series.
190 */
190 */
191 QPieSlice* QPieSeries::add(qreal value, QString name)
191 QPieSlice* QPieSeries::add(qreal value, QString name)
192 {
192 {
193 QPieSlice* slice = new QPieSlice(value, name);
193 QPieSlice* slice = new QPieSlice(value, name);
194 add(slice);
194 add(slice);
195 return slice;
195 return slice;
196 }
196 }
197
197
198 void QPieSeries::insert(int i, QPieSlice* slice)
198 void QPieSeries::insert(int i, QPieSlice* slice)
199 {
199 {
200 Q_ASSERT(i <= m_slices.count());
200 Q_ASSERT(i <= m_slices.count());
201 slice->setParent(this);
201 slice->setParent(this);
202 m_slices.insert(i, slice);
202 m_slices.insert(i, slice);
203
203
204 updateDerivativeData();
204 updateDerivativeData();
205
205
206 connect(slice, SIGNAL(changed()), this, SLOT(sliceChanged()));
206 connect(slice, SIGNAL(changed()), this, SLOT(sliceChanged()));
207 connect(slice, SIGNAL(clicked()), this, SLOT(sliceClicked()));
207 connect(slice, SIGNAL(clicked()), this, SLOT(sliceClicked()));
208 connect(slice, SIGNAL(hoverEnter()), this, SLOT(sliceHoverEnter()));
208 connect(slice, SIGNAL(hoverEnter()), this, SLOT(sliceHoverEnter()));
209 connect(slice, SIGNAL(hoverLeave()), this, SLOT(sliceHoverLeave()));
209 connect(slice, SIGNAL(hoverLeave()), this, SLOT(sliceHoverLeave()));
210
210
211 emit changed();
211 emit changed();
212 }
212 }
213
213
214 /*!
214 /*!
215 Removes a single \a slice from the series and deletes the slice.
215 Removes a single \a slice from the series and deletes the slice.
216
216
217 Do not reference this pointer after this call.
217 Do not reference this pointer after this call.
218 */
218 */
219 void QPieSeries::remove(QPieSlice* slice)
219 void QPieSeries::remove(QPieSlice* slice)
220 {
220 {
221 if (!m_slices.removeOne(slice)) {
221 if (!m_slices.removeOne(slice)) {
222 Q_ASSERT(0); // TODO: how should this be reported?
222 Q_ASSERT(0); // TODO: how should this be reported?
223 return;
223 return;
224 }
224 }
225 emit changed();
225 emit changed();
226
226
227 updateDerivativeData();
227 updateDerivativeData();
228
228
229 delete slice;
229 delete slice;
230 slice = NULL;
230 slice = NULL;
231 }
231 }
232
232
233 /*!
233 /*!
234 Clears all slices from the series.
234 Clears all slices from the series.
235 */
235 */
236 void QPieSeries::clear()
236 void QPieSeries::clear()
237 {
237 {
238 if (m_slices.count() == 0)
238 if (m_slices.count() == 0)
239 return;
239 return;
240
240
241 foreach (QPieSlice* s, m_slices) {
241 foreach (QPieSlice* s, m_slices) {
242 m_slices.removeOne(s);
242 m_slices.removeOne(s);
243 delete s;
243 delete s;
244 }
244 }
245
245
246 emit changed();
246 emit changed();
247
247
248 updateDerivativeData();
248 updateDerivativeData();
249 }
249 }
250
250
251 /*!
251 /*!
252 Counts the number of the slices in this series.
252 Counts the number of the slices in this series.
253 */
253 */
254 int QPieSeries::count() const
254 int QPieSeries::count() const
255 {
255 {
256 return m_slices.count();
256 return m_slices.count();
257 }
257 }
258
258
259 /*!
259 /*!
260 Returns a list of slices that belong to this series.
260 Returns a list of slices that belong to this series.
261 */
261 */
262 QList<QPieSlice*> QPieSeries::slices() const
262 QList<QPieSlice*> QPieSeries::slices() const
263 {
263 {
264 return m_slices;
264 return m_slices;
265 }
265 }
266
266
267 /*!
267 /*!
268 Sets the center position of the pie by \a relativeHorizontalPosition and \a relativeVerticalPosition.
268 Sets the center position of the pie by \a relativeHorizontalPosition and \a relativeVerticalPosition.
269
269
270 The factors are relative to the chart rectangle where:
270 The factors are relative to the chart rectangle where:
271
271
272 \a relativeHorizontalPosition 0.0 means the absolute left.
272 \a relativeHorizontalPosition 0.0 means the absolute left.
273 \a relativeHorizontalPosition 1.0 means the absolute right.
273 \a relativeHorizontalPosition 1.0 means the absolute right.
274 \a relativeVerticalPosition 0.0 means the absolute top.
274 \a relativeVerticalPosition 0.0 means the absolute top.
275 \a relativeVerticalPosition 1.0 means the absolute bottom.
275 \a relativeVerticalPosition 1.0 means the absolute bottom.
276
276
277 By default both values are 0.5 which puts the pie in the middle of the chart rectangle.
277 By default both values are 0.5 which puts the pie in the middle of the chart rectangle.
278
278
279 \sa pieHorizontalPosition(), pieVerticalPosition(), setPieSize()
279 \sa pieHorizontalPosition(), pieVerticalPosition(), setPieSize()
280 */
280 */
281 void QPieSeries::setPiePosition(qreal relativeHorizontalPosition, qreal relativeVerticalPosition)
281 void QPieSeries::setPiePosition(qreal relativeHorizontalPosition, qreal relativeVerticalPosition)
282 {
282 {
283 if (relativeHorizontalPosition < 0.0 || relativeHorizontalPosition > 1.0 ||
283 if (relativeHorizontalPosition < 0.0 || relativeHorizontalPosition > 1.0 ||
284 relativeVerticalPosition < 0.0 || relativeVerticalPosition > 1.0)
284 relativeVerticalPosition < 0.0 || relativeVerticalPosition > 1.0)
285 return;
285 return;
286
286
287 if (m_pieRelativeHorPos != relativeHorizontalPosition || m_pieRelativeVerPos != relativeVerticalPosition) {
287 if (m_pieRelativeHorPos != relativeHorizontalPosition || m_pieRelativeVerPos != relativeVerticalPosition) {
288 m_pieRelativeHorPos = relativeHorizontalPosition;
288 m_pieRelativeHorPos = relativeHorizontalPosition;
289 m_pieRelativeVerPos = relativeVerticalPosition;
289 m_pieRelativeVerPos = relativeVerticalPosition;
290 emit changed();
290 emit changed();
291 }
291 }
292 }
292 }
293
293
294 /*!
294 /*!
295 Gets the horizontal position of the pie.
295 Gets the horizontal position of the pie.
296
296
297 The returned value is relative to the chart rectangle where:
297 The returned value is relative to the chart rectangle where:
298
298
299 0.0 means the absolute left.
299 0.0 means the absolute left.
300 1.0 means the absolute right.
300 1.0 means the absolute right.
301
301
302 By default it is 0.5 which puts the pie in the horizontal middle of the chart rectangle.
302 By default it is 0.5 which puts the pie in the horizontal middle of the chart rectangle.
303
303
304 \sa setPiePosition(), pieVerticalPosition(), setPieSize()
304 \sa setPiePosition(), pieVerticalPosition(), setPieSize()
305 */
305 */
306 qreal QPieSeries::pieHorizontalPosition() const
306 qreal QPieSeries::pieHorizontalPosition() const
307 {
307 {
308 return m_pieRelativeHorPos;
308 return m_pieRelativeHorPos;
309 }
309 }
310
310
311 /*!
311 /*!
312 Gets the vertical position position of the pie.
312 Gets the vertical position position of the pie.
313
313
314 The returned value is relative to the chart rectangle where:
314 The returned value is relative to the chart rectangle where:
315
315
316 0.0 means the absolute top.
316 0.0 means the absolute top.
317 1.0 means the absolute bottom.
317 1.0 means the absolute bottom.
318
318
319 By default it is 0.5 which puts the pie in the vertical middle of the chart rectangle.
319 By default it is 0.5 which puts the pie in the vertical middle of the chart rectangle.
320
320
321 \sa setPiePosition(), pieHorizontalPosition(), setPieSize()
321 \sa setPiePosition(), pieHorizontalPosition(), setPieSize()
322 */
322 */
323 qreal QPieSeries::pieVerticalPosition() const
323 qreal QPieSeries::pieVerticalPosition() const
324 {
324 {
325 return m_pieRelativeVerPos;
325 return m_pieRelativeVerPos;
326 }
326 }
327
327
328 /*!
328 /*!
329 Sets the relative size of the pie.
329 Sets the relative size of the pie.
330
330
331 The \a relativeSize is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
331 The \a relativeSize is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
332
332
333 Default value is 0.7.
333 Default value is 0.7.
334
334
335 \sa pieSize(), setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
335 \sa pieSize(), setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
336 */
336 */
337 void QPieSeries::setPieSize(qreal relativeSize)
337 void QPieSeries::setPieSize(qreal relativeSize)
338 {
338 {
339 if (relativeSize < 0.0 || relativeSize > 1.0)
339 if (relativeSize < 0.0 || relativeSize > 1.0)
340 return;
340 return;
341
341
342 if (m_pieRelativeSize != relativeSize) {
342 if (m_pieRelativeSize != relativeSize) {
343 m_pieRelativeSize = relativeSize;
343 m_pieRelativeSize = relativeSize;
344 emit changed();
344 emit changed();
345 }
345 }
346 }
346 }
347
347
348 /*!
348 /*!
349 Gets the relative size of the pie.
349 Gets the relative size of the pie.
350
350
351 The size is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
351 The size is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
352
352
353 Default value is 0.7.
353 Default value is 0.7.
354
354
355 \sa setPieSize(), setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
355 \sa setPieSize(), setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
356 */
356 */
357 qreal QPieSeries::pieSize() const
357 qreal QPieSeries::pieSize() const
358 {
358 {
359 return m_pieRelativeSize;
359 return m_pieRelativeSize;
360 }
360 }
361
361
362
362
363 /*!
363 /*!
364 Sets the end angle of the pie.
364 Sets the end angle of the pie.
365
365
366 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
366 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
367
367
368 \a angle must be less than pie end angle. Default value is 0.
368 \a angle must be less than pie end angle. Default value is 0.
369
369
370 \sa pieStartAngle(), pieEndAngle(), setPieEndAngle()
370 \sa pieStartAngle(), pieEndAngle(), setPieEndAngle()
371 */
371 */
372 void QPieSeries::setPieStartAngle(qreal angle)
372 void QPieSeries::setPieStartAngle(qreal angle)
373 {
373 {
374 if (angle >= 0 && angle <= 360 && angle != m_pieStartAngle && angle <= m_pieEndAngle) {
374 if (angle >= 0 && angle <= 360 && angle != m_pieStartAngle && angle <= m_pieEndAngle) {
375 m_pieStartAngle = angle;
375 m_pieStartAngle = angle;
376 updateDerivativeData();
376 updateDerivativeData();
377 }
377 }
378 }
378 }
379
379
380 /*!
380 /*!
381 Gets the start angle of the pie.
381 Gets the start angle of the pie.
382
382
383 Full pie is 360 degrees where 0 degrees is at 12 a'clock. Default value is 360.
383 Full pie is 360 degrees where 0 degrees is at 12 a'clock. Default value is 360.
384
384
385 \sa setPieStartAngle(), pieEndAngle(), setPieEndAngle()
385 \sa setPieStartAngle(), pieEndAngle(), setPieEndAngle()
386 */
386 */
387 qreal QPieSeries::pieStartAngle() const
387 qreal QPieSeries::pieStartAngle() const
388 {
388 {
389 return m_pieStartAngle;
389 return m_pieStartAngle;
390 }
390 }
391
391
392 /*!
392 /*!
393 Sets the end angle of the pie.
393 Sets the end angle of the pie.
394
394
395 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
395 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
396
396
397 \a angle must be greater than start angle.
397 \a angle must be greater than start angle.
398
398
399 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
399 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
400 */
400 */
401 void QPieSeries::setPieEndAngle(qreal angle)
401 void QPieSeries::setPieEndAngle(qreal angle)
402 {
402 {
403 if (angle >= 0 && angle <= 360 && angle != m_pieEndAngle && angle >= m_pieStartAngle) {
403 if (angle >= 0 && angle <= 360 && angle != m_pieEndAngle && angle >= m_pieStartAngle) {
404 m_pieEndAngle = angle;
404 m_pieEndAngle = angle;
405 updateDerivativeData();
405 updateDerivativeData();
406 }
406 }
407 }
407 }
408
408
409 /*!
409 /*!
410 Returns the end angle of the pie.
410 Returns the end angle of the pie.
411
411
412 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
412 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
413
413
414 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
414 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
415 */
415 */
416 qreal QPieSeries::pieEndAngle() const
416 qreal QPieSeries::pieEndAngle() const
417 {
417 {
418 return m_pieEndAngle;
418 return m_pieEndAngle;
419 }
419 }
420
420
421 /*!
421 /*!
422 Sets the all the slice labels \a visible or invisible.
422 Sets the all the slice labels \a visible or invisible.
423
423
424 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
424 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
425 */
425 */
426 void QPieSeries::setLabelsVisible(bool visible)
426 void QPieSeries::setLabelsVisible(bool visible)
427 {
427 {
428 foreach (QPieSlice* s, m_slices)
428 foreach (QPieSlice* s, m_slices)
429 s->setLabelVisible(visible);
429 s->setLabelVisible(visible);
430 }
430 }
431
431
432 /*!
432 /*!
433 Returns the sum of all slice values in this series.
433 Returns the sum of all slice values in this series.
434
434
435 \sa QPieSlice::value(), QPieSlice::setValue()
435 \sa QPieSlice::value(), QPieSlice::setValue()
436 */
436 */
437 qreal QPieSeries::total() const
437 qreal QPieSeries::total() const
438 {
438 {
439 return m_total;
439 return m_total;
440 }
440 }
441
441
442 /*!
442 /*!
443 \fn void QPieSeries::changed()
443 \fn void QPieSeries::changed()
444
444
445 This signal emitted when something has changed in the series.
445 This signal emitted when something has changed in the series.
446
446
447 \sa QPieSeries::ChangeSet, QPieSlice::changed()
447 \sa QPieSeries::ChangeSet, QPieSlice::changed()
448 */
448 */
449
449
450 /*!
450 /*!
451 \fn void QPieSeries::clicked(QPieSlice* slice)
451 \fn void QPieSeries::clicked(QPieSlice* slice)
452
452
453 This signal is emitted when a \a slice has been clicked.
453 This signal is emitted when a \a slice has been clicked.
454
454
455 \sa QPieSlice::clicked()
455 \sa QPieSlice::clicked()
456 */
456 */
457
457
458 /*!
458 /*!
459 \fn void QPieSeries::hoverEnter(QPieSlice* slice)
459 \fn void QPieSeries::hoverEnter(QPieSlice* slice)
460
460
461 This signal is emitted when user has hovered over a \a slice.
461 This signal is emitted when user has hovered over a \a slice.
462
462
463 \sa QPieSlice::hoverEnter()
463 \sa QPieSlice::hoverEnter()
464 */
464 */
465
465
466 /*!
466 /*!
467 \fn void QPieSeries::hoverLeave(QPieSlice* slice)
467 \fn void QPieSeries::hoverLeave(QPieSlice* slice)
468
468
469 This signal is emitted when user has hovered away from a \a slice.
469 This signal is emitted when user has hovered away from a \a slice.
470
470
471 \sa QPieSlice::hoverLeave()
471 \sa QPieSlice::hoverLeave()
472 */
472 */
473
473
474 void QPieSeries::sliceChanged()
474 void QPieSeries::sliceChanged()
475 {
475 {
476 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
476 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
477 Q_ASSERT(m_slices.contains(slice));
477 Q_ASSERT(m_slices.contains(slice));
478 updateDerivativeData();
478 updateDerivativeData();
479 }
479 }
480
480
481 void QPieSeries::sliceClicked()
481 void QPieSeries::sliceClicked()
482 {
482 {
483 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
483 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
484 Q_ASSERT(m_slices.contains(slice));
484 Q_ASSERT(m_slices.contains(slice));
485 emit clicked(slice);
485 emit clicked(slice);
486 }
486 }
487
487
488 void QPieSeries::sliceHoverEnter()
488 void QPieSeries::sliceHoverEnter()
489 {
489 {
490 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
490 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
491 Q_ASSERT(m_slices.contains(slice));
491 Q_ASSERT(m_slices.contains(slice));
492 emit hoverEnter(slice);
492 emit hoverEnter(slice);
493 }
493 }
494
494
495 void QPieSeries::sliceHoverLeave()
495 void QPieSeries::sliceHoverLeave()
496 {
496 {
497 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
497 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
498 Q_ASSERT(m_slices.contains(slice));
498 Q_ASSERT(m_slices.contains(slice));
499 emit hoverLeave(slice);
499 emit hoverLeave(slice);
500 }
500 }
501
501
502 void QPieSeries::updateDerivativeData()
502 void QPieSeries::updateDerivativeData()
503 {
503 {
504 m_total = 0;
504 m_total = 0;
505
505
506 // nothing to do?
506 // nothing to do?
507 if (m_slices.count() == 0)
507 if (m_slices.count() == 0)
508 return;
508 return;
509
509
510 // calculate total
510 // calculate total
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";
517 Q_ASSERT(m_total > 0); // TODO: is this the correct way to handle this?
519 Q_ASSERT(m_total > 0); // TODO: is this the correct way to handle this?
518 }
520 }
519
521
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)
551 {
557 {
552 // disconnect signals from old model
558 // disconnect signals from old model
553 if(m_model)
559 if(m_model)
554 {
560 {
555 disconnect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), 0, 0);
561 disconnect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), 0, 0);
556 disconnect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), 0, 0);
562 disconnect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), 0, 0);
557 disconnect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), 0, 0);
563 disconnect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), 0, 0);
558 }
564 }
559
565
560 // set new model if not NULL and connect necessary signals from it
566 // set new model if not NULL and connect necessary signals from it
561 if(model)
567 if(model)
562 {
568 {
563 m_model = model;
569 m_model = model;
564 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex, QModelIndex)));
570 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex, QModelIndex)));
565 connect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
571 connect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
566 connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
572 connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
567 }
573 }
568
574
569 return true;
575 return true;
570 }
576 }
571
577
572 void QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
578 void QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
573 {
579 {
574 m_mapValues = modelValuesLine;
580 m_mapValues = modelValuesLine;
575 m_mapLabels = modelLabelsLine;
581 m_mapLabels = modelLabelsLine;
576 m_mapOrientation = orientation;
582 m_mapOrientation = orientation;
577
583
578 if (m_model == NULL)
584 if (m_model == NULL)
579 return;
585 return;
580
586
581 if (m_mapOrientation == Qt::Vertical)
587 if (m_mapOrientation == Qt::Vertical)
582 for (int i = 0; i < m_model->rowCount(); i++)
588 for (int i = 0; i < m_model->rowCount(); i++)
583 add(m_model->data(m_model->index(i, m_mapValues), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(i, m_mapLabels), Qt::DisplayRole).toString());
589 add(m_model->data(m_model->index(i, m_mapValues), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(i, m_mapLabels), Qt::DisplayRole).toString());
584 else
590 else
585 for (int i = 0; i < m_model->columnCount(); i++)
591 for (int i = 0; i < m_model->columnCount(); i++)
586 add(m_model->data(m_model->index(m_mapValues, i), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(m_mapLabels, i), Qt::DisplayRole).toString());
592 add(m_model->data(m_model->index(m_mapValues, i), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(m_mapLabels, i), Qt::DisplayRole).toString());
587
593
588
594
589 }
595 }
590
596
591 void QPieSeries::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
597 void QPieSeries::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
592 {
598 {
593 Q_UNUSED(bottomRight)
599 Q_UNUSED(bottomRight)
594
600
595 if (m_mapOrientation == Qt::Vertical)
601 if (m_mapOrientation == Qt::Vertical)
596 {
602 {
597 // slices().at(topLeft.row())->setValue(m_model->data(m_model->index(topLeft.row(), topLeft.column()), Qt::DisplayRole).toDouble());
603 // slices().at(topLeft.row())->setValue(m_model->data(m_model->index(topLeft.row(), topLeft.column()), Qt::DisplayRole).toDouble());
598 if (topLeft.column() == m_mapValues)
604 if (topLeft.column() == m_mapValues)
599 slices().at(topLeft.row())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
605 slices().at(topLeft.row())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
600 else if (topLeft.column() == m_mapLabels)
606 else if (topLeft.column() == m_mapLabels)
601 slices().at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
607 slices().at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
602 }
608 }
603 else
609 else
604 {
610 {
605 // slices().at(topLeft.column())->setValue(m_model->data(m_model->index(topLeft.row(), topLeft.column()), Qt::DisplayRole).toDouble());
611 // slices().at(topLeft.column())->setValue(m_model->data(m_model->index(topLeft.row(), topLeft.column()), Qt::DisplayRole).toDouble());
606 if (topLeft.column() == m_mapValues)
612 if (topLeft.column() == m_mapValues)
607 slices().at(topLeft.column())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
613 slices().at(topLeft.column())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
608 else if (topLeft.column() == m_mapLabels)
614 else if (topLeft.column() == m_mapLabels)
609 slices().at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
615 slices().at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
610 }
616 }
611 }
617 }
612
618
613 void QPieSeries::modelDataAdded(QModelIndex parent, int start, int end)
619 void QPieSeries::modelDataAdded(QModelIndex parent, int start, int end)
614 {
620 {
615 Q_UNUSED(parent)
621 Q_UNUSED(parent)
616 Q_UNUSED(end)
622 Q_UNUSED(end)
617
623
618 QPieSlice* newSlice = new QPieSlice;
624 QPieSlice* newSlice = new QPieSlice;
619 newSlice->setLabelVisible(true);
625 newSlice->setLabelVisible(true);
620 if (m_mapOrientation == Qt::Vertical)
626 if (m_mapOrientation == Qt::Vertical)
621 {
627 {
622 newSlice->setValue(m_model->data(m_model->index(start, m_mapValues), Qt::DisplayRole).toDouble());
628 newSlice->setValue(m_model->data(m_model->index(start, m_mapValues), Qt::DisplayRole).toDouble());
623 newSlice->setLabel(m_model->data(m_model->index(start, m_mapLabels), Qt::DisplayRole).toString());
629 newSlice->setLabel(m_model->data(m_model->index(start, m_mapLabels), Qt::DisplayRole).toString());
624 }
630 }
625 else
631 else
626 {
632 {
627 newSlice->setValue(m_model->data(m_model->index(m_mapValues, start), Qt::DisplayRole).toDouble());
633 newSlice->setValue(m_model->data(m_model->index(m_mapValues, start), Qt::DisplayRole).toDouble());
628 newSlice->setLabel(m_model->data(m_model->index(m_mapLabels, start), Qt::DisplayRole).toString());
634 newSlice->setLabel(m_model->data(m_model->index(m_mapLabels, start), Qt::DisplayRole).toString());
629 }
635 }
630
636
631 insert(start, newSlice);
637 insert(start, newSlice);
632 }
638 }
633
639
634 void QPieSeries::modelDataRemoved(QModelIndex parent, int start, int end)
640 void QPieSeries::modelDataRemoved(QModelIndex parent, int start, int end)
635 {
641 {
636 Q_UNUSED(parent)
642 Q_UNUSED(parent)
637 Q_UNUSED(end)
643 Q_UNUSED(end)
638 remove(slices().at(start));
644 remove(slices().at(start));
639 }
645 }
640
646
641 #include "moc_qpieseries.cpp"
647 #include "moc_qpieseries.cpp"
642
648
643 QTCOMMERCIALCHART_END_NAMESPACE
649 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,144 +1,145
1 #ifndef PIESERIES_H
1 #ifndef PIESERIES_H
2 #define PIESERIES_H
2 #define PIESERIES_H
3
3
4 #include "qseries.h"
4 #include "qseries.h"
5 #include <QObject>
5 #include <QObject>
6 #include <QRectF>
6 #include <QRectF>
7 #include <QColor>
7 #include <QColor>
8 #include <QPen>
8 #include <QPen>
9 #include <QBrush>
9 #include <QBrush>
10 #include <QSignalMapper>
10 #include <QSignalMapper>
11
11
12 class QGraphicsObject;
12 class QGraphicsObject;
13 QTCOMMERCIALCHART_BEGIN_NAMESPACE
13 QTCOMMERCIALCHART_BEGIN_NAMESPACE
14 class PieChartItem;
14 class PieChartItem;
15 class PieSlice;
15 class PieSlice;
16 class QPieSlice;
16 class QPieSlice;
17
17
18 class QTCOMMERCIALCHART_EXPORT QPieSeries : public QSeries
18 class QTCOMMERCIALCHART_EXPORT QPieSeries : public QSeries
19 {
19 {
20 Q_OBJECT
20 Q_OBJECT
21
21
22 public:
22 public:
23
23
24 class ChangeSet
24 class ChangeSet
25 {
25 {
26 public:
26 public:
27
27
28 // TODO: these should not really be exposed to the public API
28 // TODO: these should not really be exposed to the public API
29 void appendAdded(QPieSlice* slice);
29 void appendAdded(QPieSlice* slice);
30 void appendAdded(QList<QPieSlice*> slices);
30 void appendAdded(QList<QPieSlice*> slices);
31 void appendChanged(QPieSlice* slice);
31 void appendChanged(QPieSlice* slice);
32 void appendRemoved(QPieSlice* slice);
32 void appendRemoved(QPieSlice* slice);
33
33
34 QList<QPieSlice*> added() const;
34 QList<QPieSlice*> added() const;
35 QList<QPieSlice*> changed() const;
35 QList<QPieSlice*> changed() const;
36 QList<QPieSlice*> removed() const;
36 QList<QPieSlice*> removed() const;
37
37
38 bool isEmpty() const;
38 bool isEmpty() const;
39
39
40 private:
40 private:
41 QList<QPieSlice*> m_added;
41 QList<QPieSlice*> m_added;
42 QList<QPieSlice*> m_changed;
42 QList<QPieSlice*> m_changed;
43 QList<QPieSlice*> m_removed;
43 QList<QPieSlice*> m_removed;
44 };
44 };
45
45
46 public:
46 public:
47 QPieSeries(QObject *parent = 0);
47 QPieSeries(QObject *parent = 0);
48 virtual ~QPieSeries();
48 virtual ~QPieSeries();
49
49
50 public: // from QChartSeries
50 public: // from QChartSeries
51 QSeriesType type() const;
51 QSeriesType type() const;
52
52
53 public:
53 public:
54
54
55 // slice setters
55 // slice setters
56 void add(QPieSlice* slice);
56 void add(QPieSlice* slice);
57 void add(QList<QPieSlice*> slices);
57 void add(QList<QPieSlice*> slices);
58 void insert(int i, QPieSlice* slice);
58 void insert(int i, QPieSlice* slice);
59 void replace(QList<QPieSlice*> slices);
59 void replace(QList<QPieSlice*> slices);
60 void remove(QPieSlice* slice);
60 void remove(QPieSlice* slice);
61 void clear();
61 void clear();
62
62
63 // sluce getters
63 // sluce getters
64 QList<QPieSlice*> slices() const;
64 QList<QPieSlice*> slices() const;
65
65
66 // calculated data
66 // calculated data
67 int count() const;
67 int count() const;
68 qreal total() const;
68 qreal total() const;
69
69
70 // pie customization
70 // pie customization
71 void setPiePosition(qreal relativeHorizontalPosition, qreal relativeVerticalPosition);
71 void setPiePosition(qreal relativeHorizontalPosition, qreal relativeVerticalPosition);
72 qreal pieHorizontalPosition() const;
72 qreal pieHorizontalPosition() const;
73 qreal pieVerticalPosition() const;
73 qreal pieVerticalPosition() const;
74 void setPieSize(qreal relativeSize);
74 void setPieSize(qreal relativeSize);
75 qreal pieSize() const;
75 qreal pieSize() const;
76 void setPieStartAngle(qreal startAngle);
76 void setPieStartAngle(qreal startAngle);
77 qreal pieStartAngle() const;
77 qreal pieStartAngle() const;
78 void setPieEndAngle(qreal endAngle);
78 void setPieEndAngle(qreal endAngle);
79 qreal pieEndAngle() const;
79 qreal pieEndAngle() const;
80
80
81 // convenience function
81 // convenience function
82 QPieSeries& operator << (QPieSlice* slice);
82 QPieSeries& operator << (QPieSlice* slice);
83 QPieSlice* add(qreal value, QString name);
83 QPieSlice* add(qreal value, QString name);
84 void setLabelsVisible(bool visible = true);
84 void setLabelsVisible(bool visible = true);
85
85
86 // data from model
86 // data from model
87 bool setModel(QAbstractItemModel* model);
87 bool setModel(QAbstractItemModel* model);
88 void setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation = Qt::Vertical);
88 void setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation = Qt::Vertical);
89
89
90 // TODO: find slices?
90 // TODO: find slices?
91 // QList<QPieSlice*> findByValue(qreal value);
91 // QList<QPieSlice*> findByValue(qreal value);
92 // ...
92 // ...
93
93
94 // TODO: sorting slices?
94 // TODO: sorting slices?
95 // void sort(QPieSeries::SortByValue|label|??)
95 // void sort(QPieSeries::SortByValue|label|??)
96
96
97 // TODO: general graphics customization
97 // TODO: general graphics customization
98 // setDrawStyle(2d|3d)
98 // setDrawStyle(2d|3d)
99 // setDropShadows
99 // setDropShadows
100
100
101 Q_SIGNALS:
101 Q_SIGNALS:
102 void clicked(QPieSlice* slice);
102 void clicked(QPieSlice* slice);
103 void hoverEnter(QPieSlice* slice);
103 void hoverEnter(QPieSlice* slice);
104 void hoverLeave(QPieSlice* slice);
104 void hoverLeave(QPieSlice* slice);
105 void changed(); // TODO: hide this in PIMPL
105 void changed(); // TODO: hide this in PIMPL
106
106
107 private Q_SLOTS: // TODO: should be private and not visible in the interface at all
107 private Q_SLOTS: // TODO: should be private and not visible in the interface at all
108 void sliceChanged();
108 void sliceChanged();
109 void sliceClicked();
109 void sliceClicked();
110 void sliceHoverEnter();
110 void sliceHoverEnter();
111 void sliceHoverLeave();
111 void sliceHoverLeave();
112
112
113 // slots for updating pie when data in model changes
113 // slots for updating pie when data in model changes
114 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
114 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
115 void modelDataAdded(QModelIndex parent, int start, int end);
115 void modelDataAdded(QModelIndex parent, int start, int end);
116 void modelDataRemoved(QModelIndex parent, int start, int end);
116 void modelDataRemoved(QModelIndex parent, int start, int end);
117
117
118 private:
118 private:
119 void updateDerivativeData();
119 void updateDerivativeData();
120
120
121 private:
121 private:
122 Q_DISABLE_COPY(QPieSeries)
122 Q_DISABLE_COPY(QPieSeries)
123
123
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;
130 qreal m_pieRelativeVerPos;
131 qreal m_pieRelativeVerPos;
131 qreal m_pieRelativeSize;
132 qreal m_pieRelativeSize;
132 qreal m_pieStartAngle;
133 qreal m_pieStartAngle;
133 qreal m_pieEndAngle;
134 qreal m_pieEndAngle;
134 qreal m_total;
135 qreal m_total;
135
136
136 // model map
137 // model map
137 int m_mapValues;
138 int m_mapValues;
138 int m_mapLabels;
139 int m_mapLabels;
139 Qt::Orientation m_mapOrientation;
140 Qt::Orientation m_mapOrientation;
140 };
141 };
141
142
142 QTCOMMERCIALCHART_END_NAMESPACE
143 QTCOMMERCIALCHART_END_NAMESPACE
143
144
144 #endif // PIESERIES_H
145 #endif // PIESERIES_H
@@ -1,401 +1,407
1 #include "qpieslice.h"
1 #include "qpieslice.h"
2 #include "qpieseries.h"
2
3
3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4
5
5 #define DEFAULT_PEN_COLOR Qt::black
6 #define DEFAULT_PEN_COLOR Qt::black
6 #define DEFAULT_BRUSH_COLOR Qt::white
7 #define DEFAULT_BRUSH_COLOR Qt::white
7 #define DEFAULT_LABEL_ARM_LENGTH_FACTOR 0.15
8 #define DEFAULT_LABEL_ARM_LENGTH_FACTOR 0.15
8 #define DEFAULT_EXPOLODE_DISTANCE_FACTOR 0.15
9 #define DEFAULT_EXPOLODE_DISTANCE_FACTOR 0.15
9
10
10 /*!
11 /*!
11 \class QPieSlice
12 \class QPieSlice
12 \brief Defines a slice in pie series.
13 \brief Defines a slice in pie series.
13
14
14 Holds all the data of a single slice in a QPieSeries and provides the means
15 Holds all the data of a single slice in a QPieSeries and provides the means
15 to modify slice data and customize the visual appearance of the slice.
16 to modify slice data and customize the visual appearance of the slice.
16
17
17 It also provides the means to customize user interaction with the slice by
18 It also provides the means to customize user interaction with the slice by
18 providing signals for clicking and hover events.
19 providing signals for clicking and hover events.
19 */
20 */
20
21
21 /*!
22 /*!
22 \property QPieSlice::label
23 \property QPieSlice::label
23
24
24 Label of the slice.
25 Label of the slice.
25 */
26 */
26
27
27 /*!
28 /*!
28 \property QPieSlice::value
29 \property QPieSlice::value
29
30
30 Value of the slice.
31 Value of the slice.
31 */
32 */
32
33
33 /*!
34 /*!
34 Constructs an empty slice with a \a parent.
35 Constructs an empty slice with a \a parent.
35
36
36 Note that QPieSeries takes ownership of the slice when it is set/added.
37 Note that QPieSeries takes ownership of the slice when it is set/added.
37
38
38 \sa QPieSeries::replace(), QPieSeries::add()
39 \sa QPieSeries::replace(), QPieSeries::add()
39 */
40 */
40 QPieSlice::QPieSlice(QObject *parent)
41 QPieSlice::QPieSlice(QObject *parent)
41 :QObject(parent),
42 :QObject(parent),
42 m_value(0),
43 m_value(0),
43 m_isLabelVisible(false),
44 m_isLabelVisible(false),
44 m_isExploded(false),
45 m_isExploded(false),
45 m_explodeDistanceFactor(DEFAULT_EXPOLODE_DISTANCE_FACTOR),
46 m_explodeDistanceFactor(DEFAULT_EXPOLODE_DISTANCE_FACTOR),
46 m_percentage(0),
47 m_percentage(0),
47 m_startAngle(0),
48 m_startAngle(0),
48 m_angleSpan(0),
49 m_angleSpan(0),
49 m_slicePen(DEFAULT_PEN_COLOR),
50 m_slicePen(DEFAULT_PEN_COLOR),
50 m_sliceBrush(DEFAULT_BRUSH_COLOR),
51 m_sliceBrush(DEFAULT_BRUSH_COLOR),
51 m_labelArmPen(DEFAULT_PEN_COLOR),
52 m_labelArmPen(DEFAULT_PEN_COLOR),
52 m_labelArmLengthFactor(DEFAULT_LABEL_ARM_LENGTH_FACTOR)
53 m_labelArmLengthFactor(DEFAULT_LABEL_ARM_LENGTH_FACTOR)
53 {
54 {
54
55
55 }
56 }
56
57
57 /*!
58 /*!
58 Constructs an empty slice with given \a value, \a label and a \a parent.
59 Constructs an empty slice with given \a value, \a label and a \a parent.
59 Note that QPieSeries takes ownership of the slice when it is set/added.
60 Note that QPieSeries takes ownership of the slice when it is set/added.
60 \sa QPieSeries::replace(), QPieSeries::add()
61 \sa QPieSeries::replace(), QPieSeries::add()
61 */
62 */
62 QPieSlice::QPieSlice(qreal value, QString label, QObject *parent)
63 QPieSlice::QPieSlice(qreal value, QString label, QObject *parent)
63 :QObject(parent),
64 :QObject(parent),
64 m_value(value),
65 m_value(value),
65 m_label(label),
66 m_label(label),
66 m_isLabelVisible(false),
67 m_isLabelVisible(false),
67 m_isExploded(false),
68 m_isExploded(false),
68 m_explodeDistanceFactor(DEFAULT_EXPOLODE_DISTANCE_FACTOR),
69 m_explodeDistanceFactor(DEFAULT_EXPOLODE_DISTANCE_FACTOR),
69 m_percentage(0),
70 m_percentage(0),
70 m_startAngle(0),
71 m_startAngle(0),
71 m_angleSpan(0),
72 m_angleSpan(0),
72 m_slicePen(DEFAULT_PEN_COLOR),
73 m_slicePen(DEFAULT_PEN_COLOR),
73 m_sliceBrush(DEFAULT_BRUSH_COLOR),
74 m_sliceBrush(DEFAULT_BRUSH_COLOR),
74 m_labelArmPen(DEFAULT_PEN_COLOR),
75 m_labelArmPen(DEFAULT_PEN_COLOR),
75 m_labelArmLengthFactor(DEFAULT_LABEL_ARM_LENGTH_FACTOR)
76 m_labelArmLengthFactor(DEFAULT_LABEL_ARM_LENGTH_FACTOR)
76 {
77 {
77
78
78 }
79 }
79
80
80 /*!
81 /*!
81 Destroys the slice.
82 Destroys the slice.
82 User should not delete the slice if it has been added to the series.
83 User should not delete the slice if it has been added to the series.
83 */
84 */
84 QPieSlice::~QPieSlice()
85 QPieSlice::~QPieSlice()
85 {
86 {
86
87
87 }
88 }
88
89
89 /*!
90 /*!
90 Gets the value of the slice.
91 Gets the value of the slice.
91 Note that all values in the series
92 Note that all values in the series
92 \sa setValue()
93 \sa setValue()
93 */
94 */
94 qreal QPieSlice::value() const
95 qreal QPieSlice::value() const
95 {
96 {
96 return m_value;
97 return m_value;
97 }
98 }
98
99
99 /*!
100 /*!
100 Gets the label of the slice.
101 Gets the label of the slice.
101 \sa setLabel()
102 \sa setLabel()
102 */
103 */
103 QString QPieSlice::label() const
104 QString QPieSlice::label() const
104 {
105 {
105 return m_label;
106 return m_label;
106 }
107 }
107
108
108 /*!
109 /*!
109 Returns true if label is set as visible.
110 Returns true if label is set as visible.
110 \sa setLabelVisible()
111 \sa setLabelVisible()
111 */
112 */
112 bool QPieSlice::isLabelVisible() const
113 bool QPieSlice::isLabelVisible() const
113 {
114 {
114 return m_isLabelVisible;
115 return m_isLabelVisible;
115 }
116 }
116
117
117 /*!
118 /*!
118 Returns true if slice is exloded from the pie.
119 Returns true if slice is exloded from the pie.
119 \sa setExploded(), setExplodeDistanceFactor()
120 \sa setExploded(), setExplodeDistanceFactor()
120 */
121 */
121 bool QPieSlice::isExploded() const
122 bool QPieSlice::isExploded() const
122 {
123 {
123 return m_isExploded;
124 return m_isExploded;
124 }
125 }
125
126
126 /*!
127 /*!
127 Returns the explode distance factor.
128 Returns the explode distance factor.
128
129
129 The factor is relative to pie radius. For example:
130 The factor is relative to pie radius. For example:
130 1.0 means the distance is the same as the radius.
131 1.0 means the distance is the same as the radius.
131 0.5 means the distance is half of the radius.
132 0.5 means the distance is half of the radius.
132
133
133 Default value is 0.15.
134 Default value is 0.15.
134
135
135 \sa setExplodeDistanceFactor()
136 \sa setExplodeDistanceFactor()
136 */
137 */
137 qreal QPieSlice::explodeDistanceFactor() const
138 qreal QPieSlice::explodeDistanceFactor() const
138 {
139 {
139 return m_explodeDistanceFactor;
140 return m_explodeDistanceFactor;
140 }
141 }
141
142
142 /*!
143 /*!
143 Returns the percentage of this slice compared to all slices in the same series.
144 Returns the percentage of this slice compared to all slices in the same series.
144 The returned value ranges from 0 to 1.0.
145 The returned value ranges from 0 to 1.0.
145
146
146 Updated internally after the slice is added to the series.
147 Updated internally after the slice is added to the series.
147 */
148 */
148 qreal QPieSlice::percentage() const
149 qreal QPieSlice::percentage() const
149 {
150 {
150 return m_percentage;
151 return m_percentage;
151 }
152 }
152
153
153 /*!
154 /*!
154 Returns the starting angle of this slice in the series it belongs to.
155 Returns the starting angle of this slice in the series it belongs to.
155
156
156 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
157 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
157
158
158 Updated internally after the slice is added to the series.
159 Updated internally after the slice is added to the series.
159 */
160 */
160 qreal QPieSlice::startAngle() const
161 qreal QPieSlice::startAngle() const
161 {
162 {
162 return m_startAngle;
163 return m_startAngle;
163 }
164 }
164
165
165 /*!
166 /*!
166 Returns the end angle of this slice in the series it belongs to.
167 Returns the end angle of this slice in the series it belongs to.
167
168
168 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
169 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
169
170
170 Updated internally after the slice is added to the series.
171 Updated internally after the slice is added to the series.
171 */
172 */
172 qreal QPieSlice::endAngle() const
173 qreal QPieSlice::endAngle() const
173 {
174 {
174 return m_startAngle + m_angleSpan;
175 return m_startAngle + m_angleSpan;
175 }
176 }
176
177
177 /*!
178 /*!
178 Returns the pen used to draw this slice.
179 Returns the pen used to draw this slice.
179 \sa setSlicePen()
180 \sa setSlicePen()
180 */
181 */
181 QPen QPieSlice::slicePen() const
182 QPen QPieSlice::slicePen() const
182 {
183 {
183 return m_slicePen;
184 return m_slicePen;
184 }
185 }
185
186
186 /*!
187 /*!
187 Returns the brush used to draw this slice.
188 Returns the brush used to draw this slice.
188 \sa setSliceBrush()
189 \sa setSliceBrush()
189 */
190 */
190 QBrush QPieSlice::sliceBrush() const
191 QBrush QPieSlice::sliceBrush() const
191 {
192 {
192 return m_sliceBrush;
193 return m_sliceBrush;
193 }
194 }
194
195
195 /*!
196 /*!
196 Returns the pen used to draw label arm in this slice.
197 Returns the pen used to draw label arm in this slice.
197 \sa setLabelArmPen()
198 \sa setLabelArmPen()
198 */
199 */
199 QPen QPieSlice::labelArmPen() const
200 QPen QPieSlice::labelArmPen() const
200 {
201 {
201 return m_labelArmPen;
202 return m_labelArmPen;
202 }
203 }
203
204
204 /*!
205 /*!
205 Returns the font used to draw label in this slice.
206 Returns the font used to draw label in this slice.
206 \sa setLabelFont()
207 \sa setLabelFont()
207 */
208 */
208 QFont QPieSlice::labelFont() const
209 QFont QPieSlice::labelFont() const
209 {
210 {
210 return m_labelFont;
211 return m_labelFont;
211 }
212 }
212
213
213 /*!
214 /*!
214 Gets the label arm lenght factor.
215 Gets the label arm lenght factor.
215
216
216 The factor is relative to pie radius. For example:
217 The factor is relative to pie radius. For example:
217 1.0 means the length is the same as the radius.
218 1.0 means the length is the same as the radius.
218 0.5 means the length is half of the radius.
219 0.5 means the length is half of the radius.
219
220
220 Default value is 0.15
221 Default value is 0.15
221
222
222 \sa setLabelArmLengthFactor()
223 \sa setLabelArmLengthFactor()
223 */
224 */
224 qreal QPieSlice::labelArmLengthFactor() const
225 qreal QPieSlice::labelArmLengthFactor() const
225 {
226 {
226 return m_labelArmLengthFactor;
227 return m_labelArmLengthFactor;
227 }
228 }
228
229
229 /*!
230 /*!
230 \fn void QPieSlice::clicked()
231 \fn void QPieSlice::clicked()
231
232
232 This signal is emitted when user has clicked the slice.
233 This signal is emitted when user has clicked the slice.
233
234
234 \sa QPieSeries::clicked()
235 \sa QPieSeries::clicked()
235 */
236 */
236
237
237 /*!
238 /*!
238 \fn void QPieSlice::hoverEnter()
239 \fn void QPieSlice::hoverEnter()
239
240
240 This signal is emitted when user has hovered over the slice.
241 This signal is emitted when user has hovered over the slice.
241
242
242 \sa QPieSeries::hoverEnter()
243 \sa QPieSeries::hoverEnter()
243 */
244 */
244
245
245 /*!
246 /*!
246 \fn void QPieSlice::hoverLeave()
247 \fn void QPieSlice::hoverLeave()
247
248
248 This signal is emitted when user has hovered away from the slice.
249 This signal is emitted when user has hovered away from the slice.
249
250
250 \sa QPieSeries::hoverLeave()
251 \sa QPieSeries::hoverLeave()
251 */
252 */
252
253
253 /*!
254 /*!
254 \fn void QPieSlice::changed()
255 \fn void QPieSlice::changed()
255
256
256 This signal emitted when something has changed in the slice.
257 This signal emitted when something has changed in the slice.
257
258
258 \sa QPieSeries::changed()
259 \sa QPieSeries::changed()
259 */
260 */
260
261
261 /*!
262 /*!
262 Sets the \a value of this slice.
263 Sets the \a value of this slice.
263 \sa value()
264 \sa value()
264 */
265 */
265 void QPieSlice::setValue(qreal value)
266 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
273 /*!
279 /*!
274 Sets the \a label of the slice.
280 Sets the \a label of the slice.
275 \sa label()
281 \sa label()
276 */
282 */
277 void QPieSlice::setLabel(QString label)
283 void QPieSlice::setLabel(QString label)
278 {
284 {
279 if (m_label != label) {
285 if (m_label != label) {
280 m_label = label;
286 m_label = label;
281 emit changed();
287 emit changed();
282 }
288 }
283 }
289 }
284
290
285 /*!
291 /*!
286 Sets the label \a visible in this slice.
292 Sets the label \a visible in this slice.
287 \sa isLabelVisible(), QPieSeries::setLabelsVisible()
293 \sa isLabelVisible(), QPieSeries::setLabelsVisible()
288 */
294 */
289 void QPieSlice::setLabelVisible(bool visible)
295 void QPieSlice::setLabelVisible(bool visible)
290 {
296 {
291 if (m_isLabelVisible != visible) {
297 if (m_isLabelVisible != visible) {
292 m_isLabelVisible = visible;
298 m_isLabelVisible = visible;
293 emit changed();
299 emit changed();
294 }
300 }
295 }
301 }
296
302
297 /*!
303 /*!
298 Sets this slice \a exploded.
304 Sets this slice \a exploded.
299 \sa isExploded(), explodeDistanceFactor()
305 \sa isExploded(), explodeDistanceFactor()
300 */
306 */
301 void QPieSlice::setExploded(bool exploded)
307 void QPieSlice::setExploded(bool exploded)
302 {
308 {
303 if (m_isExploded != exploded) {
309 if (m_isExploded != exploded) {
304 m_isExploded = exploded;
310 m_isExploded = exploded;
305 emit changed();
311 emit changed();
306 }
312 }
307 }
313 }
308
314
309 /*!
315 /*!
310 Sets the explode distance \a factor.
316 Sets the explode distance \a factor.
311
317
312 The factor is relative to pie radius. For example:
318 The factor is relative to pie radius. For example:
313 1.0 means the distance is the same as the radius.
319 1.0 means the distance is the same as the radius.
314 0.5 means the distance is half of the radius.
320 0.5 means the distance is half of the radius.
315
321
316 Default value is 0.15
322 Default value is 0.15
317
323
318 \sa explodeDistanceFactor()
324 \sa explodeDistanceFactor()
319 */
325 */
320 void QPieSlice::setExplodeDistanceFactor(qreal factor)
326 void QPieSlice::setExplodeDistanceFactor(qreal factor)
321 {
327 {
322 if (m_explodeDistanceFactor != factor) {
328 if (m_explodeDistanceFactor != factor) {
323 m_explodeDistanceFactor = factor;
329 m_explodeDistanceFactor = factor;
324 emit changed();
330 emit changed();
325 }
331 }
326 }
332 }
327
333
328 /*!
334 /*!
329 Sets the \a pen used to draw this slice.
335 Sets the \a pen used to draw this slice.
330 Note that applying a theme will override this.
336 Note that applying a theme will override this.
331 \sa slicePen()
337 \sa slicePen()
332 */
338 */
333 void QPieSlice::setSlicePen(const QPen &pen)
339 void QPieSlice::setSlicePen(const QPen &pen)
334 {
340 {
335 if (m_slicePen != pen) {
341 if (m_slicePen != pen) {
336 m_slicePen = pen;
342 m_slicePen = pen;
337 emit changed();
343 emit changed();
338 }
344 }
339 }
345 }
340
346
341 /*!
347 /*!
342 Sets the \a brush used to draw this slice.
348 Sets the \a brush used to draw this slice.
343 Note that applying a theme will override this.
349 Note that applying a theme will override this.
344 \sa sliceBrush()
350 \sa sliceBrush()
345 */
351 */
346 void QPieSlice::setSliceBrush(const QBrush &brush)
352 void QPieSlice::setSliceBrush(const QBrush &brush)
347 {
353 {
348 if (m_sliceBrush != brush) {
354 if (m_sliceBrush != brush) {
349 m_sliceBrush = brush;
355 m_sliceBrush = brush;
350 emit changed();
356 emit changed();
351 }
357 }
352 }
358 }
353
359
354 /*!
360 /*!
355 Sets the \a pen used to draw the label arm in this slice.
361 Sets the \a pen used to draw the label arm in this slice.
356 Note that applying a theme will override this.
362 Note that applying a theme will override this.
357 \sa labelArmPen()
363 \sa labelArmPen()
358 */
364 */
359 void QPieSlice::setLabelArmPen(const QPen &pen)
365 void QPieSlice::setLabelArmPen(const QPen &pen)
360 {
366 {
361 if (m_labelArmPen != pen) {
367 if (m_labelArmPen != pen) {
362 m_labelArmPen = pen;
368 m_labelArmPen = pen;
363 emit changed();
369 emit changed();
364 }
370 }
365 }
371 }
366
372
367 /*!
373 /*!
368 Sets the \a font used to draw the label in this slice.
374 Sets the \a font used to draw the label in this slice.
369 Note that applying a theme will override this.
375 Note that applying a theme will override this.
370 \sa labelFont()
376 \sa labelFont()
371 */
377 */
372 void QPieSlice::setLabelFont(const QFont &font)
378 void QPieSlice::setLabelFont(const QFont &font)
373 {
379 {
374 if (m_labelFont != font) {
380 if (m_labelFont != font) {
375 m_labelFont = font;
381 m_labelFont = font;
376 emit changed();
382 emit changed();
377 }
383 }
378 }
384 }
379
385
380 /*!
386 /*!
381 Sets the label arm lenght \a factor.
387 Sets the label arm lenght \a factor.
382
388
383 The factor is relative to pie radius. For example:
389 The factor is relative to pie radius. For example:
384 1.0 means the length is the same as the radius.
390 1.0 means the length is the same as the radius.
385 0.5 means the length is half of the radius.
391 0.5 means the length is half of the radius.
386
392
387 Default value is 0.15
393 Default value is 0.15
388
394
389 \sa labelArmLengthFactor()
395 \sa labelArmLengthFactor()
390 */
396 */
391 void QPieSlice::setLabelArmLengthFactor(qreal factor)
397 void QPieSlice::setLabelArmLengthFactor(qreal factor)
392 {
398 {
393 if (m_labelArmLengthFactor != factor) {
399 if (m_labelArmLengthFactor != factor) {
394 m_labelArmLengthFactor = factor;
400 m_labelArmLengthFactor = factor;
395 emit changed();
401 emit changed();
396 }
402 }
397 }
403 }
398
404
399 #include "moc_qpieslice.cpp"
405 #include "moc_qpieslice.cpp"
400
406
401 QTCOMMERCIALCHART_END_NAMESPACE
407 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,91 +1,88
1 #ifndef QPIESLICE_H
1 #ifndef QPIESLICE_H
2 #define QPIESLICE_H
2 #define QPIESLICE_H
3
3
4 #include <qchartglobal.h>
4 #include <qchartglobal.h>
5 #include <QObject>
5 #include <QObject>
6 #include <QPen>
6 #include <QPen>
7 #include <QBrush>
7 #include <QBrush>
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 {
14 Q_OBJECT
15 Q_OBJECT
15 Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY changed)
16 Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY changed)
16 Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY changed)
17 Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY changed)
17
18
18 public:
19 public:
19 QPieSlice(QObject *parent = 0);
20 QPieSlice(QObject *parent = 0);
20 QPieSlice(qreal value, QString label, QObject *parent = 0);
21 QPieSlice(qreal value, QString label, QObject *parent = 0);
21 virtual ~QPieSlice();
22 virtual ~QPieSlice();
22
23
23 // data
24 // data
24 void setValue(qreal value);
25 void setValue(qreal value);
25 qreal value() const;
26 qreal value() const;
26 void setLabel(QString label);
27 void setLabel(QString label);
27 QString label() const;
28 QString label() const;
28 void setLabelVisible(bool visible);
29 void setLabelVisible(bool visible);
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;
37 qreal startAngle() const;
36 qreal startAngle() const;
38 qreal endAngle() const;
37 qreal endAngle() const;
39
38
40 // customization
39 // customization
41 void setSlicePen(const QPen &pen);
40 void setSlicePen(const QPen &pen);
42 QPen slicePen() const;
41 QPen slicePen() const;
43 void setSliceBrush(const QBrush &brush);
42 void setSliceBrush(const QBrush &brush);
44 QBrush sliceBrush() const;
43 QBrush sliceBrush() const;
45 void setLabelArmPen(const QPen &pen);
44 void setLabelArmPen(const QPen &pen);
46 QPen labelArmPen() const;
45 QPen labelArmPen() const;
47 void setLabelFont(const QFont &font);
46 void setLabelFont(const QFont &font);
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();
58 void hoverEnter();
55 void hoverEnter();
59 void hoverLeave();
56 void hoverLeave();
60 void changed();
57 void changed();
61
58
62 private:
59 private:
63
60
64 // TODO: use private class
61 // TODO: use private class
65 friend class QPieSeries;
62 friend class QPieSeries;
66 friend class PieChartItem;
63 friend class PieChartItem;
67 friend class PieSlice;
64 friend class PieSlice;
68
65
69 // data
66 // data
70 qreal m_value;
67 qreal m_value;
71 QString m_label;
68 QString m_label;
72 bool m_isLabelVisible;
69 bool m_isLabelVisible;
73 bool m_isExploded;
70 bool m_isExploded;
74 qreal m_explodeDistanceFactor;
71 qreal m_explodeDistanceFactor;
75
72
76 // generated data
73 // generated data
77 qreal m_percentage;
74 qreal m_percentage;
78 qreal m_startAngle;
75 qreal m_startAngle;
79 qreal m_angleSpan;
76 qreal m_angleSpan;
80
77
81 // customization
78 // customization
82 QPen m_slicePen;
79 QPen m_slicePen;
83 QBrush m_sliceBrush;
80 QBrush m_sliceBrush;
84 QFont m_labelFont;
81 QFont m_labelFont;
85 QPen m_labelArmPen;
82 QPen m_labelArmPen;
86 qreal m_labelArmLengthFactor;
83 qreal m_labelArmLengthFactor;
87 };
84 };
88
85
89 QTCOMMERCIALCHART_END_NAMESPACE
86 QTCOMMERCIALCHART_END_NAMESPACE
90
87
91 #endif // QPIESLICE_H
88 #endif // QPIESLICE_H
General Comments 0
You need to be logged in to leave comments. Login now