##// END OF EJS Templates
Refactoring pie series and animations.
Jani Honkonen -
r621:f4b980d7defa
parent child
Show More
@@ -1,582 +1,595
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 m_chartView->setAnimationOptions(QChart::AllAnimations);
291
291
292 // create series
292 // create series
293 m_series = new QPieSeries();
293 m_series = new QPieSeries();
294 *m_series << new CustomSlice(10.0, "Slice 1");
294 *m_series << new CustomSlice(10.0, "Slice 1");
295 *m_series << new CustomSlice(20.0, "Slice 2");
295 *m_series << new CustomSlice(20.0, "Slice 2");
296 *m_series << new CustomSlice(30.0, "Slice 3");
296 *m_series << new CustomSlice(30.0, "Slice 3");
297 *m_series << new CustomSlice(40.0, "Slice 4");
297 *m_series << new CustomSlice(40.0, "Slice 4");
298 *m_series << new CustomSlice(50.0, "Slice 5");
298 *m_series << new CustomSlice(50.0, "Slice 5");
299 m_chartView->addSeries(m_series);
299 m_chartView->addSeries(m_series);
300
300
301 connect(m_series, SIGNAL(clicked(QPieSlice*)), this, SLOT(handleSliceClicked(QPieSlice*)));
301 connect(m_series, SIGNAL(clicked(QPieSlice*)), this, SLOT(handleSliceClicked(QPieSlice*)));
302
302
303 // chart settings
303 // chart settings
304 m_themeComboBox = new QComboBox();
304 m_themeComboBox = new QComboBox();
305 m_themeComboBox->addItem("Default", QChart::ChartThemeDefault);
305 m_themeComboBox->addItem("Default", QChart::ChartThemeDefault);
306 m_themeComboBox->addItem("Vanilla", QChart::ChartThemeVanilla);
306 m_themeComboBox->addItem("Vanilla", QChart::ChartThemeVanilla);
307 m_themeComboBox->addItem("Icy", QChart::ChartThemeIcy);
307 m_themeComboBox->addItem("Icy", QChart::ChartThemeIcy);
308 m_themeComboBox->addItem("Grayscale", QChart::ChartThemeGrayscale);
308 m_themeComboBox->addItem("Grayscale", QChart::ChartThemeGrayscale);
309 m_themeComboBox->addItem("Scientific", QChart::ChartThemeScientific);
309 m_themeComboBox->addItem("Scientific", QChart::ChartThemeScientific);
310
310
311 m_aaCheckBox = new QCheckBox();
311 m_aaCheckBox = new QCheckBox();
312
312
313 QFormLayout* chartSettingsLayout = new QFormLayout();
313 QFormLayout* chartSettingsLayout = new QFormLayout();
314 chartSettingsLayout->addRow("Theme", m_themeComboBox);
314 chartSettingsLayout->addRow("Theme", m_themeComboBox);
315 chartSettingsLayout->addRow("Antialiasing", m_aaCheckBox);
315 chartSettingsLayout->addRow("Antialiasing", m_aaCheckBox);
316 QGroupBox* chartSettings = new QGroupBox("Chart");
316 QGroupBox* chartSettings = new QGroupBox("Chart");
317 chartSettings->setLayout(chartSettingsLayout);
317 chartSettings->setLayout(chartSettingsLayout);
318
318
319 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this ,SLOT(updateChartSettings()));
319 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this ,SLOT(updateChartSettings()));
320 connect(m_aaCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
320 connect(m_aaCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
321
321
322 // series settings
322 // series settings
323 m_hPosition = new QDoubleSpinBox();
323 m_hPosition = new QDoubleSpinBox();
324 m_hPosition->setMinimum(0.0);
324 m_hPosition->setMinimum(0.0);
325 m_hPosition->setMaximum(1.0);
325 m_hPosition->setMaximum(1.0);
326 m_hPosition->setSingleStep(0.1);
326 m_hPosition->setSingleStep(0.1);
327 m_hPosition->setValue(m_series->pieHorizontalPosition());
327 m_hPosition->setValue(m_series->pieHorizontalPosition());
328
328
329 m_vPosition = new QDoubleSpinBox();
329 m_vPosition = new QDoubleSpinBox();
330 m_vPosition->setMinimum(0.0);
330 m_vPosition->setMinimum(0.0);
331 m_vPosition->setMaximum(1.0);
331 m_vPosition->setMaximum(1.0);
332 m_vPosition->setSingleStep(0.1);
332 m_vPosition->setSingleStep(0.1);
333 m_vPosition->setValue(m_series->pieVerticalPosition());
333 m_vPosition->setValue(m_series->pieVerticalPosition());
334
334
335 m_sizeFactor = new QDoubleSpinBox();
335 m_sizeFactor = new QDoubleSpinBox();
336 m_sizeFactor->setMinimum(0.0);
336 m_sizeFactor->setMinimum(0.0);
337 m_sizeFactor->setMaximum(1.0);
337 m_sizeFactor->setMaximum(1.0);
338 m_sizeFactor->setSingleStep(0.1);
338 m_sizeFactor->setSingleStep(0.1);
339 m_sizeFactor->setValue(m_series->pieSize());
339 m_sizeFactor->setValue(m_series->pieSize());
340
340
341 m_startAngle = new QDoubleSpinBox();
341 m_startAngle = new QDoubleSpinBox();
342 m_startAngle->setMinimum(0.0);
342 m_startAngle->setMinimum(0.0);
343 m_startAngle->setMaximum(360);
343 m_startAngle->setMaximum(360);
344 m_startAngle->setValue(m_series->pieStartAngle());
344 m_startAngle->setValue(m_series->pieStartAngle());
345 m_startAngle->setSingleStep(1);
345 m_startAngle->setSingleStep(1);
346
346
347 m_endAngle = new QDoubleSpinBox();
347 m_endAngle = new QDoubleSpinBox();
348 m_endAngle->setMinimum(0.0);
348 m_endAngle->setMinimum(0.0);
349 m_endAngle->setMaximum(360);
349 m_endAngle->setMaximum(360);
350 m_endAngle->setValue(m_series->pieEndAngle());
350 m_endAngle->setValue(m_series->pieEndAngle());
351 m_endAngle->setSingleStep(1);
351 m_endAngle->setSingleStep(1);
352
352
353 QPushButton *addSlice = new QPushButton("Add slice");
353 QPushButton *addSlice = new QPushButton("Add slice");
354 QPushButton *insertSlice = new QPushButton("Insert slice");
354
355
355 QFormLayout* seriesSettingsLayout = new QFormLayout();
356 QFormLayout* seriesSettingsLayout = new QFormLayout();
356 seriesSettingsLayout->addRow("Horizontal position", m_hPosition);
357 seriesSettingsLayout->addRow("Horizontal position", m_hPosition);
357 seriesSettingsLayout->addRow("Vertical position", m_vPosition);
358 seriesSettingsLayout->addRow("Vertical position", m_vPosition);
358 seriesSettingsLayout->addRow("Size factor", m_sizeFactor);
359 seriesSettingsLayout->addRow("Size factor", m_sizeFactor);
359 seriesSettingsLayout->addRow("Start angle", m_startAngle);
360 seriesSettingsLayout->addRow("Start angle", m_startAngle);
360 seriesSettingsLayout->addRow("End angle", m_endAngle);
361 seriesSettingsLayout->addRow("End angle", m_endAngle);
361 seriesSettingsLayout->addRow(addSlice);
362 seriesSettingsLayout->addRow(addSlice);
363 seriesSettingsLayout->addRow(insertSlice);
362 QGroupBox* seriesSettings = new QGroupBox("Series");
364 QGroupBox* seriesSettings = new QGroupBox("Series");
363 seriesSettings->setLayout(seriesSettingsLayout);
365 seriesSettings->setLayout(seriesSettingsLayout);
364
366
365 connect(m_vPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
367 connect(m_vPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
366 connect(m_hPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
368 connect(m_hPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
367 connect(m_sizeFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
369 connect(m_sizeFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
368 connect(m_startAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
370 connect(m_startAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
369 connect(m_endAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
371 connect(m_endAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
370 connect(addSlice, SIGNAL(clicked()), this, SLOT(addSlice()));
372 connect(addSlice, SIGNAL(clicked()), this, SLOT(addSlice()));
373 connect(insertSlice, SIGNAL(clicked()), this, SLOT(insertSlice()));
371
374
372 // slice settings
375 // slice settings
373 m_sliceName = new QLabel("<click a slice>");
376 m_sliceName = new QLabel("<click a slice>");
374 m_sliceValue = new QDoubleSpinBox();
377 m_sliceValue = new QDoubleSpinBox();
375 m_sliceValue->setMaximum(1000);
378 m_sliceValue->setMaximum(1000);
376 m_sliceLabelVisible = new QCheckBox();
379 m_sliceLabelVisible = new QCheckBox();
377 m_sliceLabelArmFactor = new QDoubleSpinBox();
380 m_sliceLabelArmFactor = new QDoubleSpinBox();
378 m_sliceLabelArmFactor->setSingleStep(0.01);
381 m_sliceLabelArmFactor->setSingleStep(0.01);
379 m_sliceExploded = new QCheckBox();
382 m_sliceExploded = new QCheckBox();
380 m_sliceExplodedFactor = new QDoubleSpinBox();
383 m_sliceExplodedFactor = new QDoubleSpinBox();
381 m_sliceExplodedFactor->setSingleStep(0.01);
384 m_sliceExplodedFactor->setSingleStep(0.01);
382 m_pen = new QPushButton();
385 m_pen = new QPushButton();
383 m_penTool = new PenTool("Slice pen", this);
386 m_penTool = new PenTool("Slice pen", this);
384 m_brush = new QPushButton();
387 m_brush = new QPushButton();
385 m_brushTool = new BrushTool("Slice brush", this);
388 m_brushTool = new BrushTool("Slice brush", this);
386 m_font = new QPushButton();
389 m_font = new QPushButton();
387 m_labelArmPen = new QPushButton();
390 m_labelArmPen = new QPushButton();
388 m_labelArmPenTool = new PenTool("Label arm pen", this);
391 m_labelArmPenTool = new PenTool("Label arm pen", this);
389 QPushButton *removeSlice = new QPushButton("Remove slice");
392 QPushButton *removeSlice = new QPushButton("Remove slice");
390
393
391 QFormLayout* sliceSettingsLayout = new QFormLayout();
394 QFormLayout* sliceSettingsLayout = new QFormLayout();
392 sliceSettingsLayout->addRow("Selected", m_sliceName);
395 sliceSettingsLayout->addRow("Selected", m_sliceName);
393 sliceSettingsLayout->addRow("Value", m_sliceValue);
396 sliceSettingsLayout->addRow("Value", m_sliceValue);
394 sliceSettingsLayout->addRow("Pen", m_pen);
397 sliceSettingsLayout->addRow("Pen", m_pen);
395 sliceSettingsLayout->addRow("Brush", m_brush);
398 sliceSettingsLayout->addRow("Brush", m_brush);
396 sliceSettingsLayout->addRow("Label visible", m_sliceLabelVisible);
399 sliceSettingsLayout->addRow("Label visible", m_sliceLabelVisible);
397 sliceSettingsLayout->addRow("Label font", m_font);
400 sliceSettingsLayout->addRow("Label font", m_font);
398 sliceSettingsLayout->addRow("Label arm pen", m_labelArmPen);
401 sliceSettingsLayout->addRow("Label arm pen", m_labelArmPen);
399 sliceSettingsLayout->addRow("Label arm length", m_sliceLabelArmFactor);
402 sliceSettingsLayout->addRow("Label arm length", m_sliceLabelArmFactor);
400 sliceSettingsLayout->addRow("Exploded", m_sliceExploded);
403 sliceSettingsLayout->addRow("Exploded", m_sliceExploded);
401 sliceSettingsLayout->addRow("Explode distance", m_sliceExplodedFactor);
404 sliceSettingsLayout->addRow("Explode distance", m_sliceExplodedFactor);
402 sliceSettingsLayout->addRow(removeSlice);
405 sliceSettingsLayout->addRow(removeSlice);
403 QGroupBox* sliceSettings = new QGroupBox("Slice");
406 QGroupBox* sliceSettings = new QGroupBox("Slice");
404 sliceSettings->setLayout(sliceSettingsLayout);
407 sliceSettings->setLayout(sliceSettingsLayout);
405
408
406 connect(m_sliceValue, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
409 connect(m_sliceValue, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
407 connect(m_pen, SIGNAL(clicked()), m_penTool, SLOT(show()));
410 connect(m_pen, SIGNAL(clicked()), m_penTool, SLOT(show()));
408 connect(m_penTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
411 connect(m_penTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
409 connect(m_brush, SIGNAL(clicked()), m_brushTool, SLOT(show()));
412 connect(m_brush, SIGNAL(clicked()), m_brushTool, SLOT(show()));
410 connect(m_brushTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
413 connect(m_brushTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
411 connect(m_font, SIGNAL(clicked()), this, SLOT(showFontDialog()));
414 connect(m_font, SIGNAL(clicked()), this, SLOT(showFontDialog()));
412 connect(m_labelArmPen, SIGNAL(clicked()), m_labelArmPenTool, SLOT(show()));
415 connect(m_labelArmPen, SIGNAL(clicked()), m_labelArmPenTool, SLOT(show()));
413 connect(m_labelArmPenTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
416 connect(m_labelArmPenTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
414 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
417 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
415 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
418 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
416 connect(m_sliceLabelArmFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
419 connect(m_sliceLabelArmFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
417 connect(m_sliceExploded, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
420 connect(m_sliceExploded, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
418 connect(m_sliceExplodedFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
421 connect(m_sliceExplodedFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
419 connect(removeSlice, SIGNAL(clicked()), this, SLOT(removeSlice()));
422 connect(removeSlice, SIGNAL(clicked()), this, SLOT(removeSlice()));
420
423
421 // create main layout
424 // create main layout
422 QVBoxLayout *settingsLayout = new QVBoxLayout();
425 QVBoxLayout *settingsLayout = new QVBoxLayout();
423 settingsLayout->addWidget(chartSettings);
426 settingsLayout->addWidget(chartSettings);
424 settingsLayout->addWidget(seriesSettings);
427 settingsLayout->addWidget(seriesSettings);
425 settingsLayout->addWidget(sliceSettings);
428 settingsLayout->addWidget(sliceSettings);
426 settingsLayout->addStretch();
429 settingsLayout->addStretch();
427
430
428 QGridLayout* baseLayout = new QGridLayout();
431 QGridLayout* baseLayout = new QGridLayout();
429 baseLayout->addLayout(settingsLayout, 0, 0);
432 baseLayout->addLayout(settingsLayout, 0, 0);
430 baseLayout->addWidget(m_chartView, 0, 1);
433 baseLayout->addWidget(m_chartView, 0, 1);
431 setLayout(baseLayout);
434 setLayout(baseLayout);
432
435
433 updateSerieSettings();
436 updateSerieSettings();
434 }
437 }
435
438
436 public Q_SLOTS:
439 public Q_SLOTS:
437
440
438 void updateChartSettings()
441 void updateChartSettings()
439 {
442 {
440 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
443 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
441 m_chartView->setChartTheme(theme);
444 m_chartView->setChartTheme(theme);
442 m_chartView->setRenderHint(QPainter::Antialiasing, m_aaCheckBox->isChecked());
445 m_chartView->setRenderHint(QPainter::Antialiasing, m_aaCheckBox->isChecked());
443 }
446 }
444
447
445 void updateSerieSettings()
448 void updateSerieSettings()
446 {
449 {
447 m_series->setPiePosition(m_vPosition->value(), m_hPosition->value());
450 m_series->setPiePosition(m_vPosition->value(), m_hPosition->value());
448 m_series->setPieSize(m_sizeFactor->value());
451 m_series->setPieSize(m_sizeFactor->value());
449 m_series->setPieStartAngle(m_startAngle->value());
452 m_series->setPieStartAngle(m_startAngle->value());
450 m_series->setPieEndAngle(m_endAngle->value());
453 m_series->setPieEndAngle(m_endAngle->value());
451 }
454 }
452
455
453 void updateSliceSettings()
456 void updateSliceSettings()
454 {
457 {
455 if (!m_slice)
458 if (!m_slice)
456 return;
459 return;
457
460
458 m_slice->setValue(m_sliceValue->value());
461 m_slice->setValue(m_sliceValue->value());
459
462
460 m_slice->setSlicePen(m_penTool->pen());
463 m_slice->setSlicePen(m_penTool->pen());
461 m_slice->setSliceBrush(m_brushTool->brush());
464 m_slice->setSliceBrush(m_brushTool->brush());
462
465
463 m_slice->setLabelArmPen(m_labelArmPenTool->pen());
466 m_slice->setLabelArmPen(m_labelArmPenTool->pen());
464 m_slice->setLabelVisible(m_sliceLabelVisible->isChecked());
467 m_slice->setLabelVisible(m_sliceLabelVisible->isChecked());
465 m_slice->setLabelArmLengthFactor(m_sliceLabelArmFactor->value());
468 m_slice->setLabelArmLengthFactor(m_sliceLabelArmFactor->value());
466
469
467 m_slice->setExploded(m_sliceExploded->isChecked());
470 m_slice->setExploded(m_sliceExploded->isChecked());
468 m_slice->setExplodeDistanceFactor(m_sliceExplodedFactor->value());
471 m_slice->setExplodeDistanceFactor(m_sliceExplodedFactor->value());
469 }
472 }
470
473
471 void handleSliceClicked(QPieSlice* slice)
474 void handleSliceClicked(QPieSlice* slice)
472 {
475 {
473 m_slice = static_cast<CustomSlice*>(slice);
476 m_slice = static_cast<CustomSlice*>(slice);
474
477
475 // name
478 // name
476 m_sliceName->setText(slice->label());
479 m_sliceName->setText(slice->label());
477
480
478 // value
481 // value
479 m_sliceValue->blockSignals(true);
482 m_sliceValue->blockSignals(true);
480 m_sliceValue->setValue(slice->value());
483 m_sliceValue->setValue(slice->value());
481 m_sliceValue->blockSignals(false);
484 m_sliceValue->blockSignals(false);
482
485
483 // pen
486 // pen
484 m_pen->setText(PenTool::name(m_slice->slicePen()));
487 m_pen->setText(PenTool::name(m_slice->slicePen()));
485 m_penTool->setPen(m_slice->slicePen());
488 m_penTool->setPen(m_slice->slicePen());
486
489
487 // brush
490 // brush
488 m_brush->setText(m_slice->originalBrush().color().name());
491 m_brush->setText(m_slice->originalBrush().color().name());
489 m_brushTool->setBrush(m_slice->originalBrush());
492 m_brushTool->setBrush(m_slice->originalBrush());
490
493
491 // label
494 // label
492 m_labelArmPen->setText(PenTool::name(m_slice->labelArmPen()));
495 m_labelArmPen->setText(PenTool::name(m_slice->labelArmPen()));
493 m_labelArmPenTool->setPen(m_slice->labelArmPen());
496 m_labelArmPenTool->setPen(m_slice->labelArmPen());
494 m_font->setText(slice->labelFont().toString());
497 m_font->setText(slice->labelFont().toString());
495 m_sliceLabelVisible->blockSignals(true);
498 m_sliceLabelVisible->blockSignals(true);
496 m_sliceLabelVisible->setChecked(slice->isLabelVisible());
499 m_sliceLabelVisible->setChecked(slice->isLabelVisible());
497 m_sliceLabelVisible->blockSignals(false);
500 m_sliceLabelVisible->blockSignals(false);
498 m_sliceLabelArmFactor->blockSignals(true);
501 m_sliceLabelArmFactor->blockSignals(true);
499 m_sliceLabelArmFactor->setValue(slice->labelArmLengthFactor());
502 m_sliceLabelArmFactor->setValue(slice->labelArmLengthFactor());
500 m_sliceLabelArmFactor->blockSignals(false);
503 m_sliceLabelArmFactor->blockSignals(false);
501
504
502 // exploded
505 // exploded
503 m_sliceExploded->blockSignals(true);
506 m_sliceExploded->blockSignals(true);
504 m_sliceExploded->setChecked(slice->isExploded());
507 m_sliceExploded->setChecked(slice->isExploded());
505 m_sliceExploded->blockSignals(false);
508 m_sliceExploded->blockSignals(false);
506 m_sliceExplodedFactor->blockSignals(true);
509 m_sliceExplodedFactor->blockSignals(true);
507 m_sliceExplodedFactor->setValue(slice->explodeDistanceFactor());
510 m_sliceExplodedFactor->setValue(slice->explodeDistanceFactor());
508 m_sliceExplodedFactor->blockSignals(false);
511 m_sliceExplodedFactor->blockSignals(false);
509 }
512 }
510
513
511 void showFontDialog()
514 void showFontDialog()
512 {
515 {
513 if (!m_slice)
516 if (!m_slice)
514 return;
517 return;
515
518
516 QFontDialog dialog(m_slice->labelFont());
519 QFontDialog dialog(m_slice->labelFont());
517 dialog.show();
520 dialog.show();
518 dialog.exec();
521 dialog.exec();
519
522
520 m_slice->setLabelFont(dialog.currentFont());
523 m_slice->setLabelFont(dialog.currentFont());
521 m_font->setText(dialog.currentFont().toString());
524 m_font->setText(dialog.currentFont().toString());
522 }
525 }
523
526
524 void addSlice()
527 void addSlice()
525 {
528 {
526 *m_series << new CustomSlice(10.0, "Slice " + QString::number(m_series->count()));
529 *m_series << new CustomSlice(10.0, "Slice " + QString::number(m_series->count()));
527 }
530 }
528
531
532 void insertSlice()
533 {
534 if (!m_slice)
535 return;
536
537 int i = m_series->slices().indexOf(m_slice);
538
539 m_series->insert(i, new CustomSlice(10.0, "Slice " + QString::number(m_series->count())));
540 }
541
529 void removeSlice()
542 void removeSlice()
530 {
543 {
531 if (!m_slice)
544 if (!m_slice)
532 return;
545 return;
533
546
534 m_series->remove(m_slice);
547 m_series->remove(m_slice);
535 m_slice = 0;
548 m_slice = 0;
536 }
549 }
537
550
538 private:
551 private:
539 QComboBox *m_themeComboBox;
552 QComboBox *m_themeComboBox;
540 QCheckBox *m_aaCheckBox;
553 QCheckBox *m_aaCheckBox;
541
554
542 QChartView* m_chartView;
555 QChartView* m_chartView;
543 QPieSeries* m_series;
556 QPieSeries* m_series;
544 CustomSlice* m_slice;
557 CustomSlice* m_slice;
545
558
546 QDoubleSpinBox* m_hPosition;
559 QDoubleSpinBox* m_hPosition;
547 QDoubleSpinBox* m_vPosition;
560 QDoubleSpinBox* m_vPosition;
548 QDoubleSpinBox* m_sizeFactor;
561 QDoubleSpinBox* m_sizeFactor;
549 QDoubleSpinBox* m_startAngle;
562 QDoubleSpinBox* m_startAngle;
550 QDoubleSpinBox* m_endAngle;
563 QDoubleSpinBox* m_endAngle;
551
564
552 QLabel* m_sliceName;
565 QLabel* m_sliceName;
553 QDoubleSpinBox* m_sliceValue;
566 QDoubleSpinBox* m_sliceValue;
554 QCheckBox* m_sliceLabelVisible;
567 QCheckBox* m_sliceLabelVisible;
555 QDoubleSpinBox* m_sliceLabelArmFactor;
568 QDoubleSpinBox* m_sliceLabelArmFactor;
556 QCheckBox* m_sliceExploded;
569 QCheckBox* m_sliceExploded;
557 QDoubleSpinBox* m_sliceExplodedFactor;
570 QDoubleSpinBox* m_sliceExplodedFactor;
558 QPushButton *m_brush;
571 QPushButton *m_brush;
559 BrushTool *m_brushTool;
572 BrushTool *m_brushTool;
560 QPushButton *m_pen;
573 QPushButton *m_pen;
561 PenTool *m_penTool;
574 PenTool *m_penTool;
562 QPushButton *m_font;
575 QPushButton *m_font;
563 QPushButton *m_labelArmPen;
576 QPushButton *m_labelArmPen;
564 PenTool *m_labelArmPenTool;
577 PenTool *m_labelArmPenTool;
565 };
578 };
566
579
567 int main(int argc, char *argv[])
580 int main(int argc, char *argv[])
568 {
581 {
569 QApplication a(argc, argv);
582 QApplication a(argc, argv);
570
583
571 QMainWindow window;
584 QMainWindow window;
572
585
573 MainWidget* widget = new MainWidget();
586 MainWidget* widget = new MainWidget();
574
587
575 window.setCentralWidget(widget);
588 window.setCentralWidget(widget);
576 window.resize(900, 600);
589 window.resize(900, 600);
577 window.show();
590 window.show();
578
591
579 return a.exec();
592 return a.exec();
580 }
593 }
581
594
582 #include "main.moc"
595 #include "main.moc"
@@ -1,113 +1,114
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 <QTime>
7 #include <QTime>
8
8
9 QTCOMMERCIALCHART_USE_NAMESPACE
9 QTCOMMERCIALCHART_USE_NAMESPACE
10
10
11 class DrilldownSlice : public QPieSlice
11 class DrilldownSlice : public QPieSlice
12 {
12 {
13 Q_OBJECT
13 Q_OBJECT
14
14
15 public:
15 public:
16 DrilldownSlice(qreal value, QString prefix, QSeries* drilldownSeries)
16 DrilldownSlice(qreal value, QString prefix, QSeries* drilldownSeries)
17 :m_drilldownSeries(drilldownSeries),
17 :m_drilldownSeries(drilldownSeries),
18 m_prefix(prefix)
18 m_prefix(prefix)
19 {
19 {
20 setValue(value);
20 setValue(value);
21 setLabelVisible(true);
21 setLabelVisible(true);
22 updateLabel();
22 updateLabel();
23 connect(this, SIGNAL(changed()), this, SLOT(updateLabel()));
23 connect(this, SIGNAL(changed()), this, SLOT(updateLabel()));
24 }
24 }
25
25
26 QSeries* drilldownSeries() const { return m_drilldownSeries; }
26 QSeries* drilldownSeries() const { return m_drilldownSeries; }
27
27
28 public Q_SLOTS:
28 public Q_SLOTS:
29 void updateLabel()
29 void updateLabel()
30 {
30 {
31 QString label = m_prefix;
31 QString label = m_prefix;
32 label += " " + QString::number(this->value())+ "e (";
32 label += " " + QString::number(this->value())+ "e (";
33 label += QString::number(this->percentage()*100, 'f', 1) + "%)";
33 label += QString::number(this->percentage()*100, 'f', 1) + "%)";
34 setLabel(label);
34 setLabel(label);
35 }
35 }
36
36
37 private:
37 private:
38 QSeries* m_drilldownSeries;
38 QSeries* m_drilldownSeries;
39 QString m_prefix;
39 QString m_prefix;
40 };
40 };
41
41
42 class DrilldownChart : public QChartView
42 class DrilldownChart : public QChartView
43 {
43 {
44 Q_OBJECT
44 Q_OBJECT
45 public:
45 public:
46 explicit DrilldownChart(QWidget *parent = 0):QChartView(parent), m_currentSeries(0) {}
46 explicit DrilldownChart(QWidget *parent = 0):QChartView(parent), m_currentSeries(0) {}
47
47
48 void changeSeries(QSeries* series)
48 void changeSeries(QSeries* series)
49 {
49 {
50 // NOTE: if the series is owned by the chart it will be deleted
50 // NOTE: if the series is owned by the chart it will be deleted
51 // here the "window" owns the series...
51 // here the "window" owns the series...
52 if (m_currentSeries)
52 if (m_currentSeries)
53 removeSeries(m_currentSeries);
53 removeSeries(m_currentSeries);
54 m_currentSeries = series;
54 m_currentSeries = series;
55 addSeries(series);
55 addSeries(series);
56 setChartTitle(series->title());
56 setChartTitle(series->title());
57 }
57 }
58
58
59 public Q_SLOTS:
59 public Q_SLOTS:
60 void handleSliceClicked(QPieSlice* slice)
60 void handleSliceClicked(QPieSlice* slice)
61 {
61 {
62 DrilldownSlice* drilldownSlice = static_cast<DrilldownSlice*>(slice);
62 DrilldownSlice* drilldownSlice = static_cast<DrilldownSlice*>(slice);
63 changeSeries(drilldownSlice->drilldownSeries());
63 changeSeries(drilldownSlice->drilldownSeries());
64 }
64 }
65
65
66 private:
66 private:
67 QSeries* m_currentSeries;
67 QSeries* m_currentSeries;
68 };
68 };
69
69
70 int main(int argc, char *argv[])
70 int main(int argc, char *argv[])
71 {
71 {
72 QApplication a(argc, argv);
72 QApplication a(argc, argv);
73
73
74 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
74 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
75
75
76 QMainWindow window;
76 QMainWindow window;
77
77
78 DrilldownChart* drilldownChart = new DrilldownChart(&window);
78 DrilldownChart* drilldownChart = new DrilldownChart(&window);
79 drilldownChart->setRenderHint(QPainter::Antialiasing);
79 drilldownChart->setRenderHint(QPainter::Antialiasing);
80 drilldownChart->setChartTheme(QChart::ChartThemeVanilla);
80 drilldownChart->setChartTheme(QChart::ChartThemeVanilla);
81 drilldownChart->setAnimationOptions(QChart::AllAnimations);
81
82
82 QPieSeries* yearSeries = new QPieSeries(&window);
83 QPieSeries* yearSeries = new QPieSeries(&window);
83 yearSeries->setTitle("Sales by year - All");
84 yearSeries->setTitle("Sales by year - All");
84
85
85 QList<QString> months;
86 QList<QString> months;
86 months << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun" << "Jul" << "Aug" << "Sep" << "Oct" << "Nov" << "Dec";
87 months << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun" << "Jul" << "Aug" << "Sep" << "Oct" << "Nov" << "Dec";
87 QList<QString> names;
88 QList<QString> names;
88 names << "Jane" << "John" << "Axel" << "Mary" << "Samantha" << "Bob";
89 names << "Jane" << "John" << "Axel" << "Mary" << "Samantha" << "Bob";
89
90
90 foreach (QString name, names) {
91 foreach (QString name, names) {
91 QPieSeries* series = new QPieSeries(&window);
92 QPieSeries* series = new QPieSeries(&window);
92 series->setTitle("Sales by month - " + name);
93 series->setTitle("Sales by month - " + name);
93
94
94 foreach (QString month, months)
95 foreach (QString month, months)
95 *series << new DrilldownSlice(qrand() % 1000, month, yearSeries);
96 *series << new DrilldownSlice(qrand() % 1000, month, yearSeries);
96
97
97 QObject::connect(series, SIGNAL(clicked(QPieSlice*)), drilldownChart, SLOT(handleSliceClicked(QPieSlice*)));
98 QObject::connect(series, SIGNAL(clicked(QPieSlice*)), drilldownChart, SLOT(handleSliceClicked(QPieSlice*)));
98
99
99 *yearSeries << new DrilldownSlice(series->total(), name, series);
100 *yearSeries << new DrilldownSlice(series->total(), name, series);
100 }
101 }
101
102
102 QObject::connect(yearSeries, SIGNAL(clicked(QPieSlice*)), drilldownChart, SLOT(handleSliceClicked(QPieSlice*)));
103 QObject::connect(yearSeries, SIGNAL(clicked(QPieSlice*)), drilldownChart, SLOT(handleSliceClicked(QPieSlice*)));
103
104
104 drilldownChart->changeSeries(yearSeries);
105 drilldownChart->changeSeries(yearSeries);
105
106
106 window.setCentralWidget(drilldownChart);
107 window.setCentralWidget(drilldownChart);
107 window.resize(800, 600);
108 window.resize(800, 600);
108 window.show();
109 window.show();
109
110
110 return a.exec();
111 return a.exec();
111 }
112 }
112
113
113 #include "main.moc"
114 #include "main.moc"
@@ -1,207 +1,221
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 "pieanimation_p.h"
6 #include "areachartitem_p.h"
6 #include "areachartitem_p.h"
7 #include <QTimer>
7 #include <QTimer>
8
8
9 Q_DECLARE_METATYPE(QVector<QPointF>)
9 Q_DECLARE_METATYPE(QVector<QPointF>)
10 Q_DECLARE_METATYPE(QVector<qreal>)
10 Q_DECLARE_METATYPE(QVector<qreal>)
11
11
12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
13
13
14 const static int duration = 1000;
14 const static int duration = 1000;
15
15
16 ChartAnimator::ChartAnimator(QObject *parent):QObject(parent)
16 ChartAnimator::ChartAnimator(QObject *parent):QObject(parent)
17 {
17 {
18 }
18 }
19
19
20 ChartAnimator::~ChartAnimator()
20 ChartAnimator::~ChartAnimator()
21 {
21 {
22 }
22 }
23
23
24 void ChartAnimator::addAnimation(AxisItem* item)
24 void ChartAnimator::addAnimation(AxisItem* item)
25 {
25 {
26 ChartAnimation* animation = m_animations.value(item);
26 ChartAnimation* animation = m_animations.value(item);
27
27
28 if(!animation) {
28 if(!animation) {
29 animation = new AxisAnimation(item);
29 animation = new AxisAnimation(item);
30 m_animations.insert(item,animation);
30 m_animations.insert(item,animation);
31 }
31 }
32
32
33 item->setAnimator(this);
33 item->setAnimator(this);
34 }
34 }
35
35
36 void ChartAnimator::addAnimation(XYChartItem* item)
36 void ChartAnimator::addAnimation(XYChartItem* item)
37 {
37 {
38 ChartAnimation* animation = m_animations.value(item);
38 ChartAnimation* animation = m_animations.value(item);
39
39
40 if(!animation) {
40 if(!animation) {
41 animation = new XYAnimation(item);
41 animation = new XYAnimation(item);
42 m_animations.insert(item,animation);
42 m_animations.insert(item,animation);
43 }
43 }
44
44
45 item->setAnimator(this);
45 item->setAnimator(this);
46 }
46 }
47
47
48 void ChartAnimator::addAnimation(PieChartItem* item)
48 void ChartAnimator::addAnimation(PieChartItem* item)
49 {
49 {
50 ChartAnimation* animation = m_animations.value(item);
50 ChartAnimation* animation = m_animations.value(item);
51
51
52 if(!animation) {
52 if(!animation) {
53 animation = new PieAnimation(item);
53 animation = new PieAnimation(item);
54 m_animations.insert(item,animation);
54 m_animations.insert(item,animation);
55 }
55 }
56
56
57 item->setAnimator(this);
57 item->setAnimator(this);
58 }
58 }
59
59
60 void ChartAnimator::removeAnimation(ChartItem* item)
60 void ChartAnimator::removeAnimation(ChartItem* item)
61 {
61 {
62 item->setAnimator(0);
62 item->setAnimator(0);
63 m_animations.remove(item);
63 m_animations.remove(item);
64 }
64 }
65
65
66 void ChartAnimator::applyLayout(AxisItem* item , QVector<qreal>& newLayout)
66 void ChartAnimator::applyLayout(AxisItem* item , QVector<qreal>& newLayout)
67 {
67 {
68 AxisAnimation* animation = static_cast<AxisAnimation*>(m_animations.value(item));
68 AxisAnimation* animation = static_cast<AxisAnimation*>(m_animations.value(item));
69
69
70 Q_ASSERT(animation);
70 Q_ASSERT(animation);
71
71
72 QVector<qreal> oldLayout = item->layout();
72 QVector<qreal> oldLayout = item->layout();
73
73
74 if(newLayout.count()==0) return;
74 if(newLayout.count()==0) return;
75
75
76 switch(m_state)
76 switch(m_state)
77 {
77 {
78 case ZoomOutState: {
78 case ZoomOutState: {
79 QRectF rect = item->geometry();
79 QRectF rect = item->geometry();
80 oldLayout.resize(newLayout.count());
80 oldLayout.resize(newLayout.count());
81
81
82 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--)
83 {
83 {
84 oldLayout[i]= item->axisType()==AxisItem::X_AXIS?rect.left():rect.bottom();
84 oldLayout[i]= item->axisType()==AxisItem::X_AXIS?rect.left():rect.bottom();
85 oldLayout[j]= item->axisType()==AxisItem::X_AXIS?rect.right():rect.top();
85 oldLayout[j]= item->axisType()==AxisItem::X_AXIS?rect.right():rect.top();
86 }
86 }
87 }
87 }
88 break;
88 break;
89 case ZoomInState: {
89 case ZoomInState: {
90 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);
91 oldLayout.resize(newLayout.count());
91 oldLayout.resize(newLayout.count());
92
92
93 for(int i=0;i<oldLayout.count();i++)
93 for(int i=0;i<oldLayout.count();i++)
94 {
94 {
95 oldLayout[i]= oldLayout[index];
95 oldLayout[i]= oldLayout[index];
96 }
96 }
97 }
97 }
98 break;
98 break;
99 case ScrollDownState:
99 case ScrollDownState:
100 case ScrollRightState: {
100 case ScrollRightState: {
101 oldLayout.resize(newLayout.count());
101 oldLayout.resize(newLayout.count());
102
102
103 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++)
104 {
104 {
105 oldLayout[i]= oldLayout[j];
105 oldLayout[i]= oldLayout[j];
106 }
106 }
107 }
107 }
108 break;
108 break;
109 case ScrollUpState:
109 case ScrollUpState:
110 case ScrollLeftState: {
110 case ScrollLeftState: {
111 oldLayout.resize(newLayout.count());
111 oldLayout.resize(newLayout.count());
112
112
113 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--)
114 {
114 {
115 oldLayout[i]= oldLayout[j];
115 oldLayout[i]= oldLayout[j];
116 }
116 }
117 }
117 }
118 break;
118 break;
119 default: {
119 default: {
120 oldLayout.resize(newLayout.count());
120 oldLayout.resize(newLayout.count());
121 QRectF rect = item->geometry();
121 QRectF rect = item->geometry();
122 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--)
123 {
123 {
124 oldLayout[i]= item->axisType()==AxisItem::X_AXIS?rect.left():rect.top();
124 oldLayout[i]= item->axisType()==AxisItem::X_AXIS?rect.left():rect.top();
125 }
125 }
126 }
126 }
127 break;
127 break;
128 }
128 }
129
129
130
130
131 if(animation->state()!=QAbstractAnimation::Stopped) {
131 if(animation->state()!=QAbstractAnimation::Stopped) {
132 animation->stop();
132 animation->stop();
133 }
133 }
134
134
135 animation->setDuration(duration);
135 animation->setDuration(duration);
136 animation->setEasingCurve(QEasingCurve::OutQuart);
136 animation->setEasingCurve(QEasingCurve::OutQuart);
137 QVariantAnimation::KeyValues value;
137 QVariantAnimation::KeyValues value;
138 animation->setKeyValues(value); //workaround for wrong interpolation call
138 animation->setKeyValues(value); //workaround for wrong interpolation call
139 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
139 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
140 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
140 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
141
141
142 QTimer::singleShot(0,animation,SLOT(start()));
142 QTimer::singleShot(0,animation,SLOT(start()));
143 }
143 }
144
144
145 void ChartAnimator::applyLayout(XYChartItem* item, QVector<QPointF>& newPoints)
145 void ChartAnimator::applyLayout(XYChartItem* item, QVector<QPointF>& newPoints)
146 {
146 {
147
147
148 XYAnimation* animation = static_cast<XYAnimation*>(m_animations.value(item));
148 XYAnimation* animation = static_cast<XYAnimation*>(m_animations.value(item));
149
149
150 Q_ASSERT(animation);
150 Q_ASSERT(animation);
151
151
152 QVector<QPointF> oldPoints = item->points();
152 QVector<QPointF> oldPoints = item->points();
153
153
154 if(newPoints.count()==0) return;
154 if(newPoints.count()==0) return;
155
155
156 bool empty = oldPoints.count()==0;
156 bool empty = oldPoints.count()==0;
157 oldPoints.resize(newPoints.size());
157 oldPoints.resize(newPoints.size());
158
158
159 if(animation->state()!=QAbstractAnimation::Stopped) {
159 if(animation->state()!=QAbstractAnimation::Stopped) {
160 animation->stop();
160 animation->stop();
161 }
161 }
162
162
163 animation->setDuration(duration);
163 animation->setDuration(duration);
164 if(!empty)
164 if(!empty)
165 animation->setAnimationType(XYAnimation::MoveDownAnimation);
165 animation->setAnimationType(XYAnimation::MoveDownAnimation);
166 else
166 else
167 animation->setAnimationType(XYAnimation::LineDrawAnimation);
167 animation->setAnimationType(XYAnimation::LineDrawAnimation);
168 animation->setEasingCurve(QEasingCurve::OutQuart);
168 animation->setEasingCurve(QEasingCurve::OutQuart);
169 animation->setValues(oldPoints,newPoints);
169 animation->setValues(oldPoints,newPoints);
170 QTimer::singleShot(0,animation,SLOT(start()));
170 QTimer::singleShot(0,animation,SLOT(start()));
171 }
171 }
172
172
173 void ChartAnimator::updateLayout(XYChartItem* item, QVector<QPointF>& newPoints)
173 void ChartAnimator::updateLayout(XYChartItem* item, QVector<QPointF>& newPoints)
174 {
174 {
175 XYAnimation* animation = static_cast<XYAnimation*>(m_animations.value(item));
175 XYAnimation* animation = static_cast<XYAnimation*>(m_animations.value(item));
176
176
177 Q_ASSERT(animation);
177 Q_ASSERT(animation);
178
178
179 animation->setDuration(duration);
179 animation->setDuration(duration);
180 animation->setAnimationType(XYAnimation::MoveDownAnimation);
180 animation->setAnimationType(XYAnimation::MoveDownAnimation);
181 animation->setEasingCurve(QEasingCurve::OutQuart);
181 animation->setEasingCurve(QEasingCurve::OutQuart);
182 animation->updateValues(newPoints);
182 animation->updateValues(newPoints);
183
183
184 QTimer::singleShot(0,animation,SLOT(start()));
184 QTimer::singleShot(0,animation,SLOT(start()));
185 }
185 }
186
186
187 void ChartAnimator::applyLayout(PieChartItem* item, QVector<PieSliceLayout> &layout)
187 void ChartAnimator::addAnimation(PieChartItem* item, QPieSlice *slice, PieSliceLayout &layout)
188 {
188 {
189 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
189 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
190 Q_ASSERT(animation);
190 Q_ASSERT(animation);
191 animation->setValues(layout);
191 animation->addSlice(slice, layout);
192 }
193
194 void ChartAnimator::removeAnimation(PieChartItem* item, QPieSlice *slice)
195 {
196 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
197 Q_ASSERT(animation);
198 animation->removeSlice(slice);
199 }
200
201 void ChartAnimator::updateLayout(PieChartItem* item, QVector<PieSliceLayout> &layout)
202 {
203 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
204 Q_ASSERT(animation);
205 animation->updateValues(layout);
192 }
206 }
193
207
194 void ChartAnimator::updateLayout(PieChartItem* item, PieSliceLayout &layout)
208 void ChartAnimator::updateLayout(PieChartItem* item, PieSliceLayout &layout)
195 {
209 {
196 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
210 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
197 Q_ASSERT(animation);
211 Q_ASSERT(animation);
198 animation->updateValue(layout);
212 animation->updateValue(layout);
199 }
213 }
200
214
201 void ChartAnimator::setState(State state,const QPointF& point)
215 void ChartAnimator::setState(State state,const QPointF& point)
202 {
216 {
203 m_state=state;
217 m_state=state;
204 m_point=point;
218 m_point=point;
205 }
219 }
206
220
207 QTCOMMERCIALCHART_END_NAMESPACE
221 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,48 +1,50
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 "piechartitem_p.h"
6 #include <QPointF>
6 #include <QPointF>
7
7
8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9
9
10 class ChartItem;
10 class ChartItem;
11 class XYChartItem;
11 class XYChartItem;
12 class AxisItem;
12 class AxisItem;
13 class AreaChartItem;
13 class AreaChartItem;
14
14
15
15
16 class ChartAnimator : public QObject {
16 class ChartAnimator : public QObject {
17
17
18 public:
18 public:
19 //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
20 enum State{ShowState, ScrollUpState, ScrollDownState, ScrollLeftState,ScrollRightState,ZoomInState,ZoomOutState};
20 enum State{ShowState, ScrollUpState, ScrollDownState, ScrollLeftState,ScrollRightState,ZoomInState,ZoomOutState};
21 ChartAnimator(QObject *parent = 0);
21 ChartAnimator(QObject *parent = 0);
22 virtual ~ChartAnimator();
22 virtual ~ChartAnimator();
23
23
24 void addAnimation(AxisItem* item);
24 void addAnimation(AxisItem* item);
25 void addAnimation(XYChartItem* item);
25 void addAnimation(XYChartItem* item);
26 void addAnimation(PieChartItem* item);
26 void addAnimation(PieChartItem* item);
27
27
28 void removeAnimation(ChartItem* item);
28 void removeAnimation(ChartItem* item);
29
29
30 void animationStarted();
30 void animationStarted();
31 void applyLayout(XYChartItem* item, QVector<QPointF>& layout);
31 void applyLayout(XYChartItem* item, QVector<QPointF>& layout);
32 void updateLayout(XYChartItem* item, QVector<QPointF>& layout);
32 void updateLayout(XYChartItem* item, QVector<QPointF>& layout);
33 void applyLayout(AxisItem* item, QVector<qreal>& layout);
33 void applyLayout(AxisItem* item, QVector<qreal>& layout);
34
34
35 void applyLayout(PieChartItem* item, QVector<PieSliceLayout> &layout);
35 void addAnimation(PieChartItem* item, QPieSlice *slice, PieSliceLayout &layout);
36 void removeAnimation(PieChartItem* item, QPieSlice *slice);
37 void updateLayout(PieChartItem* item, QVector<PieSliceLayout> &layout);
36 void updateLayout(PieChartItem* item, PieSliceLayout &layout);
38 void updateLayout(PieChartItem* item, PieSliceLayout &layout);
37
39
38 void setState(State state,const QPointF& point = QPointF());
40 void setState(State state,const QPointF& point = QPointF());
39
41
40 private:
42 private:
41 QMap<ChartItem*,ChartAnimation*> m_animations;
43 QMap<ChartItem*,ChartAnimation*> m_animations;
42 State m_state;
44 State m_state;
43 QPointF m_point;
45 QPointF m_point;
44 };
46 };
45
47
46 QTCOMMERCIALCHART_END_NAMESPACE
48 QTCOMMERCIALCHART_END_NAMESPACE
47
49
48 #endif
50 #endif
@@ -1,94 +1,89
1 #include "PieAnimation_p.h"
1 #include "PieAnimation_p.h"
2 #include "piesliceanimation_p.h"
2 #include "piesliceanimation_p.h"
3 #include "piechartitem_p.h"
3 #include "piechartitem_p.h"
4 #include <QParallelAnimationGroup>
4 #include <QParallelAnimationGroup>
5 #include <QTimer>
5 #include <QTimer>
6
6
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8
8
9 PieAnimation::PieAnimation(PieChartItem *item)
9 PieAnimation::PieAnimation(PieChartItem *item)
10 :ChartAnimation(item),
10 :ChartAnimation(item),
11 m_item(item)
11 m_item(item)
12 {
12 {
13 }
13 }
14
14
15 PieAnimation::~PieAnimation()
15 PieAnimation::~PieAnimation()
16 {
16 {
17 }
17 }
18
18
19 void PieAnimation::setValues(QVector<PieSliceLayout>& newValues)
19 void PieAnimation::updateValues(QVector<PieSliceLayout>& newValues)
20 {
20 {
21 PieSliceAnimation *animation = 0;
21 foreach (PieSliceLayout endLayout, newValues)
22
22 updateValue(endLayout);
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 }
23 }
67
24
68 void PieAnimation::updateValue(PieSliceLayout& endLayout)
25 void PieAnimation::updateValue(PieSliceLayout& endLayout)
69 {
26 {
70 PieSliceAnimation *animation = m_animations.value(endLayout.m_data);
27 PieSliceAnimation *animation = m_animations.value(endLayout.m_data);
71 Q_ASSERT(animation);
28 Q_ASSERT(animation);
72 animation->stop();
29 animation->stop();
30
31 animation->updateValue(endLayout);
32 animation->setDuration(1000);
33 animation->setEasingCurve(QEasingCurve::OutQuart);
34
35 QTimer::singleShot(0, animation, SLOT(start()));
36 }
37
38 void PieAnimation::addSlice(QPieSlice *slice, PieSliceLayout endLayout)
39 {
40 PieSliceAnimation *animation = new PieSliceAnimation(m_item);
41 m_animations.insert(slice, animation);
42
43 PieSliceLayout startLayout = endLayout;
44 startLayout.m_radius = 0;
45 startLayout.m_startAngle = endLayout.m_startAngle + (endLayout.m_angleSpan/2);
46 startLayout.m_angleSpan = 0;
47 animation->setValue(startLayout, endLayout);
48
49 animation->setDuration(1000);
50 animation->setEasingCurve(QEasingCurve::OutQuart);
51 QTimer::singleShot(0, animation, SLOT(start()));
52 }
53
54 void PieAnimation::removeSlice(QPieSlice *slice)
55 {
56 PieSliceAnimation *animation = m_animations.value(slice);
57 Q_ASSERT(animation);
58 animation->stop();
59
60 PieSliceLayout endLayout = animation->currentSliceValue();
61 endLayout.m_radius = 0;
62 // TODO: find the actual angle where this slice disappears
63 endLayout.m_startAngle = endLayout.m_startAngle + endLayout.m_angleSpan;
64 endLayout.m_angleSpan = 0;
65
73 animation->updateValue(endLayout);
66 animation->updateValue(endLayout);
74 animation->setDuration(1000);
67 animation->setDuration(1000);
75 animation->setEasingCurve(QEasingCurve::OutQuart);
68 animation->setEasingCurve(QEasingCurve::OutQuart);
69
70 connect(animation, SIGNAL(finished()), this, SLOT(destroySliceAnimationComplete()));
76 QTimer::singleShot(0, animation, SLOT(start()));
71 QTimer::singleShot(0, animation, SLOT(start()));
77 }
72 }
78
73
79 void PieAnimation::updateCurrentValue(const QVariant &)
74 void PieAnimation::updateCurrentValue(const QVariant &)
80 {
75 {
81 // nothing to do...
76 // nothing to do...
82 }
77 }
83
78
84 void PieAnimation::destroySliceAnimationComplete()
79 void PieAnimation::destroySliceAnimationComplete()
85 {
80 {
86 PieSliceAnimation *animation = static_cast<PieSliceAnimation*>(sender());
81 PieSliceAnimation *animation = static_cast<PieSliceAnimation*>(sender());
87 QPieSlice *slice = m_animations.key(animation);
82 QPieSlice *slice = m_animations.key(animation);
88 m_item->destroySlice(slice);
83 m_item->destroySlice(slice);
89 delete m_animations.take(slice);
84 delete m_animations.take(slice);
90 }
85 }
91
86
92 #include "moc_pieanimation_p.cpp"
87 #include "moc_pieanimation_p.cpp"
93
88
94 QTCOMMERCIALCHART_END_NAMESPACE
89 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,35 +1,37
1 #ifndef PIEANIMATION_P_H_
1 #ifndef PIEANIMATION_P_H_
2 #define PIEANIMATION_P_H_
2 #define PIEANIMATION_P_H_
3
3
4 #include "chartanimation_p.h"
4 #include "chartanimation_p.h"
5 #include "piechartitem_p.h"
5 #include "piechartitem_p.h"
6 #include "piesliceanimation_p.h"
6 #include "piesliceanimation_p.h"
7
7
8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9
9
10 class PieChartItem;
10 class PieChartItem;
11
11
12 class PieAnimation : public ChartAnimation
12 class PieAnimation : public ChartAnimation
13 {
13 {
14 Q_OBJECT
14 Q_OBJECT
15
15
16 public:
16 public:
17 PieAnimation(PieChartItem *item);
17 PieAnimation(PieChartItem *item);
18 ~PieAnimation();
18 ~PieAnimation();
19 void setValues(QVector<PieSliceLayout>& newValues);
19 void updateValues(QVector<PieSliceLayout>& newValues);
20 void updateValue(PieSliceLayout& newValue);
20 void updateValue(PieSliceLayout& newValue);
21 void addSlice(QPieSlice *slice, PieSliceLayout endLayout);
22 void removeSlice(QPieSlice *slice);
21
23
22 public: // from QVariantAnimation
24 public: // from QVariantAnimation
23 void updateCurrentValue(const QVariant &value);
25 void updateCurrentValue(const QVariant &value);
24
26
25 public Q_SLOTS:
27 public Q_SLOTS:
26 void destroySliceAnimationComplete();
28 void destroySliceAnimationComplete();
27
29
28 private:
30 private:
29 PieChartItem *m_item;
31 PieChartItem *m_item;
30 QHash<QPieSlice*, PieSliceAnimation*> m_animations;
32 QHash<QPieSlice*, PieSliceAnimation*> m_animations;
31 };
33 };
32
34
33 QTCOMMERCIALCHART_END_NAMESPACE
35 QTCOMMERCIALCHART_END_NAMESPACE
34
36
35 #endif
37 #endif
@@ -1,185 +1,189
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 "chartanimator_p.h"
7 #include <QDebug>
7 #include <QDebug>
8 #include <QPainter>
8 #include <QPainter>
9
9 #include <QTimer>
10
10
11 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 QTCOMMERCIALCHART_BEGIN_NAMESPACE
12
12
13 PieChartItem::PieChartItem(QGraphicsItem *parent, QPieSeries *series)
13 PieChartItem::PieChartItem(QGraphicsItem *parent, QPieSeries *series)
14 :ChartItem(parent),
14 :ChartItem(parent),
15 m_series(series)
15 m_series(series)
16 {
16 {
17 Q_ASSERT(series);
17 Q_ASSERT(series);
18 connect(series, SIGNAL(changed()), this, SLOT(handleSeriesChanged()));
18 connect(series, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>)));
19 connect(series, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>)));
20 connect(series, SIGNAL(piePositionChanged()), this, SLOT(handlePieLayoutChanged()));
21 connect(series, SIGNAL(pieSizeChanged()), this, SLOT(handlePieLayoutChanged()));
22
23 QTimer::singleShot(0, this, SLOT(initialize()));
19
24
20 // Note: the following does not affect as long as the item does not have anything to paint
25 // Note: the following does not affect as long as the item does not have anything to paint
21 setZValue(ChartPresenter::PieSeriesZValue);
26 setZValue(ChartPresenter::PieSeriesZValue);
22 }
27 }
23
28
24 PieChartItem::~PieChartItem()
29 PieChartItem::~PieChartItem()
25 {
30 {
26 // slices deleted automatically through QGraphicsItem
31 // slices deleted automatically through QGraphicsItem
27 }
32 }
28
33
29 void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
34 void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
30 {
35 {
31 Q_UNUSED(painter)
36 Q_UNUSED(painter)
32 // TODO: paint shadows for all components
37 // TODO: paint shadows for all components
33 // - get paths from items & merge & offset and draw with shadow color?
38 // - get paths from items & merge & offset and draw with shadow color?
34 //painter->setBrush(QBrush(Qt::red));
39 //painter->setBrush(QBrush(Qt::red));
35 //painter->drawRect(m_debugRect);
40 //painter->drawRect(m_debugRect);
36 }
41 }
37
42
38 void PieChartItem::handleSeriesChanged()
43 void PieChartItem::initialize()
44 {
45 handleSlicesAdded(m_series->m_slices);
46 }
47
48 void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices)
49 {
50 foreach (QPieSlice *s, slices) {
51 PieSlice* slice = new PieSlice(this);
52 m_slices.insert(s, slice);
53 connect(s, SIGNAL(changed()), this, SLOT(handleSliceChanged()));
54 connect(slice, SIGNAL(clicked()), s, SIGNAL(clicked()));
55 connect(slice, SIGNAL(hoverEnter()), s, SIGNAL(hoverEnter()));
56 connect(slice, SIGNAL(hoverLeave()), s, SIGNAL(hoverLeave()));
57
58 PieSliceLayout layout = calculateSliceLayout(s);
59
60 if (m_animator)
61 m_animator->addAnimation(this, s, layout);
62 else
63 setLayout(layout);
64 }
65 }
66
67 void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices)
68 {
69 foreach (QPieSlice *s, slices) {
70 if (m_animator)
71 m_animator->removeAnimation(this, s);
72 else
73 destroySlice(s);
74 }
75 }
76
77 void PieChartItem::handlePieLayoutChanged()
39 {
78 {
40 QVector<PieSliceLayout> layout = calculateLayout();
79 QVector<PieSliceLayout> layout = calculateLayout();
41 applyLayout(layout);
80 applyLayout(layout);
42 update();
81 update();
43 }
82 }
44
83
45 void PieChartItem::handleSliceChanged()
84 void PieChartItem::handleSliceChanged()
46 {
85 {
47 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
86 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
48 Q_ASSERT(m_slices.contains(slice));
87 Q_ASSERT(m_slices.contains(slice));
49
88 PieSliceLayout layout = calculateSliceLayout(slice);
50 //qDebug() << "PieChartItem::handleSliceChanged" << slice->label();
89 updateLayout(layout);
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 }
58 update();
90 update();
59 }
91 }
60
92
61 void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal)
93 void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal)
62 {
94 {
63 // TODO
95 // TODO
64 }
96 }
65
97
66 void PieChartItem::handleGeometryChanged(const QRectF& rect)
98 void PieChartItem::handleGeometryChanged(const QRectF& rect)
67 {
99 {
68 prepareGeometryChange();
100 prepareGeometryChange();
69 m_rect = rect;
101 m_rect = rect;
70 QVector<PieSliceLayout> sliceLayout = calculateLayout();
102 handlePieLayoutChanged();
71 applyLayout(sliceLayout);
72 update();
73 }
103 }
74
104
75
105 void PieChartItem::calculatePieLayout()
76 QVector<PieSliceLayout> PieChartItem::calculateLayout()
77 {
106 {
78 // find pie center coordinates
107 // find pie center coordinates
79 QPointF center;
108 m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->pieHorizontalPosition()));
80 center.setX(m_rect.left() + (m_rect.width() * m_series->pieHorizontalPosition()));
109 m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->pieVerticalPosition()));
81 center.setY(m_rect.top() + (m_rect.height() * m_series->pieVerticalPosition()));
82
110
83 // find maximum radius for pie
111 // find maximum radius for pie
84 qreal radius = m_rect.height() / 2;
112 m_pieRadius = m_rect.height() / 2;
85 if (m_rect.width() < m_rect.height())
113 if (m_rect.width() < m_rect.height())
86 radius = m_rect.width() / 2;
114 m_pieRadius = m_rect.width() / 2;
87
115
88 // apply size factor
116 // apply size factor
89 radius *= m_series->pieSize();
117 m_pieRadius *= m_series->pieSize();
118 }
90
119
120 PieSliceLayout PieChartItem::calculateSliceLayout(QPieSlice *slice)
121 {
122 PieSliceLayout sliceLayout;
123 sliceLayout.m_data = slice;
124 sliceLayout.m_center = PieSlice::sliceCenter(m_pieCenter, m_pieRadius, slice);
125 sliceLayout.m_radius = m_pieRadius;
126 sliceLayout.m_startAngle = slice->startAngle();
127 sliceLayout.m_angleSpan = slice->m_angleSpan;
128 return sliceLayout;
129 }
130
131 QVector<PieSliceLayout> PieChartItem::calculateLayout()
132 {
133 calculatePieLayout();
91 QVector<PieSliceLayout> layout;
134 QVector<PieSliceLayout> layout;
92 foreach (QPieSlice* s, m_series->slices()) {
135 foreach (QPieSlice* s, m_series->slices()) {
93 PieSliceLayout sliceLayout;
136 if (m_slices.contains(s)) // calculate layout only for those slices that are already visible
94 sliceLayout.m_data = s;
137 layout << calculateSliceLayout(s);
95 sliceLayout.m_center = PieSlice::sliceCenter(center, radius, s);
96 sliceLayout.m_radius = radius;
97 sliceLayout.m_startAngle = s->startAngle();
98 sliceLayout.m_angleSpan = s->m_angleSpan;
99 layout << sliceLayout;
100 }
138 }
101
102 return layout;
139 return layout;
103 }
140 }
104
141
105 void PieChartItem::applyLayout(QVector<PieSliceLayout> &layout)
142 void PieChartItem::applyLayout(QVector<PieSliceLayout> &layout)
106 {
143 {
107 if (m_animator)
144 if (m_animator)
108 m_animator->applyLayout(this, layout);
145 m_animator->updateLayout(this, layout);
109 else
146 else
110 setLayout(layout);
147 setLayout(layout);
111 }
148 }
112
149
113 void PieChartItem::updateLayout(PieSliceLayout &layout)
150 void PieChartItem::updateLayout(PieSliceLayout &layout)
114 {
151 {
115 if (m_animator)
152 if (m_animator)
116 m_animator->updateLayout(this, layout);
153 m_animator->updateLayout(this, layout);
117 else
154 else
118 setLayout(layout);
155 setLayout(layout);
119 }
156 }
120
157
121 void PieChartItem::setLayout(QVector<PieSliceLayout> &layout)
158 void PieChartItem::setLayout(QVector<PieSliceLayout> &layout)
122 {
159 {
123 foreach (PieSliceLayout l, layout) {
160 foreach (PieSliceLayout l, layout) {
124
125 // find slice
126 PieSlice *slice = m_slices.value(l.m_data);
161 PieSlice *slice = m_slices.value(l.m_data);
127 if (!slice) {
162 Q_ASSERT(slice);
128 // add a new slice
129 slice = new PieSlice(this);
130 m_slices.insert(l.m_data, slice);
131
132 // connect signals
133 connect(l.m_data, SIGNAL(changed()), this, SLOT(handleSliceChanged()));
134 connect(slice, SIGNAL(clicked()), l.m_data, SIGNAL(clicked()));
135 connect(slice, SIGNAL(hoverEnter()), l.m_data, SIGNAL(hoverEnter()));
136 connect(slice, SIGNAL(hoverLeave()), l.m_data, SIGNAL(hoverLeave()));
137 }
138
139 // update
140 slice->setLayout(l);
163 slice->setLayout(l);
164 slice->updateData(l.m_data);
141 slice->updateGeometry();
165 slice->updateGeometry();
142 slice->update();
166 slice->update();
143 }
167 }
144
145 // delete slices
146 foreach (QPieSlice *s, m_slices.keys()) {
147
148 bool found = false;
149 foreach (PieSliceLayout l, layout) {
150 if (l.m_data == s)
151 found = true;
152 }
153
154 if (!found)
155 destroySlice(s);
156 }
157 }
168 }
158
169
159 void PieChartItem::setLayout(PieSliceLayout &layout)
170 void PieChartItem::setLayout(PieSliceLayout &layout)
160 {
171 {
161 // find slice
172 // find slice
162 PieSlice *slice = m_slices.value(layout.m_data);
173 PieSlice *slice = m_slices.value(layout.m_data);
163 if (!slice) {
174 Q_ASSERT(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()));
170 }
171 slice->setLayout(layout);
175 slice->setLayout(layout);
172 if (m_series->m_slices.contains(layout.m_data)) // Slice has been deleted if not found. Animations ongoing...
176 if (m_series->m_slices.contains(layout.m_data)) // Slice has been deleted if not found. Animations ongoing...
173 slice->updateData(layout.m_data);
177 slice->updateData(layout.m_data);
174 slice->updateGeometry();
178 slice->updateGeometry();
175 slice->update();
179 slice->update();
176 }
180 }
177
181
178 void PieChartItem::destroySlice(QPieSlice *slice)
182 void PieChartItem::destroySlice(QPieSlice *slice)
179 {
183 {
180 delete m_slices.take(slice);
184 delete m_slices.take(slice);
181 }
185 }
182
186
183 #include "moc_piechartitem_p.cpp"
187 #include "moc_piechartitem_p.cpp"
184
188
185 QTCOMMERCIALCHART_END_NAMESPACE
189 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,51 +1,56
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 initialize();
27 void handleSlicesAdded(QList<QPieSlice*> slices);
28 void handleSlicesRemoved(QList<QPieSlice*> slices);
29 void handlePieLayoutChanged();
27 void handleSliceChanged();
30 void handleSliceChanged();
28 void handleDomainChanged(qreal, qreal, qreal, qreal);
31 void handleDomainChanged(qreal, qreal, qreal, qreal);
29 void handleGeometryChanged(const QRectF& rect);
32 void handleGeometryChanged(const QRectF& rect);
30
33
31 public:
34 public:
35 void calculatePieLayout();
36 PieSliceLayout calculateSliceLayout(QPieSlice *slice);
32 QVector<PieSliceLayout> calculateLayout();
37 QVector<PieSliceLayout> calculateLayout();
33 void applyLayout(QVector<PieSliceLayout> &layout);
38 void applyLayout(QVector<PieSliceLayout> &layout);
34 void updateLayout(PieSliceLayout &layout);
39 void updateLayout(PieSliceLayout &layout);
35 void setLayout(QVector<PieSliceLayout> &layout);
40 void setLayout(QVector<PieSliceLayout> &layout);
36 void setLayout(PieSliceLayout &layout);
41 void setLayout(PieSliceLayout &layout);
37 void destroySlice(QPieSlice *slice);
42 void destroySlice(QPieSlice *slice);
38
43
39 private:
44 private:
40 friend class PieSlice;
45 friend class PieSlice;
41 QHash<QPieSlice*, PieSlice*> m_slices;
46 QHash<QPieSlice*, PieSlice*> m_slices;
42 QPieSeries *m_series;
47 QPieSeries *m_series;
43 QRectF m_rect;
48 QRectF m_rect;
44 QPointF m_pieCenter;
49 QPointF m_pieCenter;
45 qreal m_pieRadius;
50 qreal m_pieRadius;
46 QRectF m_debugRect;
51 QRectF m_debugRect;
47 };
52 };
48
53
49 QTCOMMERCIALCHART_END_NAMESPACE
54 QTCOMMERCIALCHART_END_NAMESPACE
50
55
51 #endif // PIECHARTITEM_H
56 #endif // PIECHARTITEM_H
@@ -1,203 +1,204
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_isExploded(false),
25 m_isExploded(false),
26 m_explodeDistanceFactor(0),
26 m_explodeDistanceFactor(0),
27 m_labelVisible(false),
27 m_labelVisible(false),
28 m_labelArmLengthFactor(0)
28 m_labelArmLengthFactor(0)
29 {
29 {
30 setAcceptHoverEvents(true);
30 setAcceptHoverEvents(true);
31 setAcceptedMouseButtons(Qt::LeftButton);
31 setAcceptedMouseButtons(Qt::LeftButton);
32 setZValue(ChartPresenter::PieSeriesZValue);
32 setZValue(ChartPresenter::PieSeriesZValue);
33 }
33 }
34
34
35 PieSlice::~PieSlice()
35 PieSlice::~PieSlice()
36 {
36 {
37
37
38 }
38 }
39
39
40 QRectF PieSlice::boundingRect() const
40 QRectF PieSlice::boundingRect() const
41 {
41 {
42 return m_slicePath.boundingRect().united(m_labelTextRect);
42 return m_boundingRect;
43 }
43 }
44
44
45 QPainterPath PieSlice::shape() const
45 QPainterPath PieSlice::shape() const
46 {
46 {
47 // Don't include the label and label arm.
47 // Don't include the label and label arm.
48 // 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.
49 return m_slicePath;
49 return m_slicePath;
50 }
50 }
51
51
52 void PieSlice::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
52 void PieSlice::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
53 {
53 {
54 painter->setClipRect(parentItem()->boundingRect());
54 painter->setClipRect(parentItem()->boundingRect());
55
55
56 painter->save();
56 painter->save();
57 painter->setPen(m_slicePen);
57 painter->setPen(m_slicePen);
58 painter->setBrush(m_sliceBrush);
58 painter->setBrush(m_sliceBrush);
59 painter->drawPath(m_slicePath);
59 painter->drawPath(m_slicePath);
60 painter->restore();
60 painter->restore();
61
61
62 if (m_labelVisible) {
62 if (m_labelVisible) {
63 painter->save();
63 painter->save();
64 painter->setPen(m_labelArmPen);
64 painter->setPen(m_labelArmPen);
65 painter->drawPath(m_labelArmPath);
65 painter->drawPath(m_labelArmPath);
66 painter->restore();
66 painter->restore();
67
67
68 painter->setFont(m_labelFont);
68 painter->setFont(m_labelFont);
69 painter->drawText(m_labelTextRect.bottomLeft(), m_labelText);
69 painter->drawText(m_labelTextRect.bottomLeft(), m_labelText);
70 }
70 }
71 }
71 }
72
72
73 void PieSlice::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
73 void PieSlice::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
74 {
74 {
75 emit hoverEnter();
75 emit hoverEnter();
76 }
76 }
77
77
78 void PieSlice::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
78 void PieSlice::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
79 {
79 {
80 emit hoverLeave();
80 emit hoverLeave();
81 }
81 }
82
82
83 void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/)
83 void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/)
84 {
84 {
85 emit clicked();
85 emit clicked();
86 }
86 }
87
87
88 void PieSlice::setLayout(PieSliceLayout layout)
88 void PieSlice::setLayout(PieSliceLayout layout)
89 {
89 {
90 m_layout = layout;
90 m_layout = layout;
91 }
91 }
92
92
93 void PieSlice::updateGeometry()
93 void PieSlice::updateGeometry()
94 {
94 {
95 if (m_layout.m_radius <= 0)
95 if (m_layout.m_radius <= 0)
96 return;
96 return;
97
97
98 prepareGeometryChange();
98 prepareGeometryChange();
99
99
100 // update slice path
100 // update slice path
101 qreal centerAngle;
101 qreal centerAngle;
102 QPointF armStart;
102 QPointF armStart;
103 m_slicePath = slicePath(m_layout.m_center, m_layout.m_radius, m_layout.m_startAngle, m_layout.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);
104
104
105 // update text rect
105 // update text rect
106 m_labelTextRect = labelTextRect(m_labelFont, m_labelText);
106 m_labelTextRect = labelTextRect(m_labelFont, m_labelText);
107
107
108 // update label arm path
108 // update label arm path
109 QPointF labelTextStart;
109 QPointF labelTextStart;
110 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);
111
111
112 // update text position
112 // update text position
113 m_labelTextRect.moveBottomLeft(labelTextStart);
113 m_labelTextRect.moveBottomLeft(labelTextStart);
114
114
115 //qDebug() << "PieSlice::updateGeometry" << m_labelText << boundingRect() << m_startAngle << m_startAngle + m_angleSpan;
115 // update bounding rect
116 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
116 }
117 }
117
118
118 void PieSlice::updateData(const QPieSlice* sliceData)
119 void PieSlice::updateData(const QPieSlice* sliceData)
119 {
120 {
120 // TODO: compare what has changes to avoid unneccesary geometry updates
121 // TODO: compare what has changes to avoid unneccesary geometry updates
121
122
122 m_isExploded = sliceData->isExploded();
123 m_isExploded = sliceData->isExploded();
123 m_explodeDistanceFactor = sliceData->explodeDistanceFactor();
124 m_explodeDistanceFactor = sliceData->explodeDistanceFactor();
124 m_slicePen = sliceData->slicePen();
125 m_slicePen = sliceData->slicePen();
125 m_sliceBrush = sliceData->sliceBrush();
126 m_sliceBrush = sliceData->sliceBrush();
126
127
127 m_labelVisible = sliceData->isLabelVisible();
128 m_labelVisible = sliceData->isLabelVisible();
128 m_labelText = sliceData->label();
129 m_labelText = sliceData->label();
129 m_labelFont = sliceData->labelFont();
130 m_labelFont = sliceData->labelFont();
130 m_labelArmLengthFactor = sliceData->labelArmLengthFactor();
131 m_labelArmLengthFactor = sliceData->labelArmLengthFactor();
131 m_labelArmPen = sliceData->labelArmPen();
132 m_labelArmPen = sliceData->labelArmPen();
132 }
133 }
133
134
134 QPointF PieSlice::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
135 QPointF PieSlice::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
135 {
136 {
136 if (slice->isExploded()) {
137 if (slice->isExploded()) {
137 qreal centerAngle = slice->startAngle() + (slice->m_angleSpan/2);
138 qreal centerAngle = slice->startAngle() + (slice->m_angleSpan/2);
138 qreal len = radius * slice->explodeDistanceFactor();
139 qreal len = radius * slice->explodeDistanceFactor();
139 qreal dx = qSin(centerAngle*(PI/180)) * len;
140 qreal dx = qSin(centerAngle*(PI/180)) * len;
140 qreal dy = -qCos(centerAngle*(PI/180)) * len;
141 qreal dy = -qCos(centerAngle*(PI/180)) * len;
141 point += QPointF(dx, dy);
142 point += QPointF(dx, dy);
142 }
143 }
143 return point;
144 return point;
144 }
145 }
145
146
146 QPainterPath PieSlice::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal* centerAngle, QPointF* armStart)
147 QPainterPath PieSlice::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal* centerAngle, QPointF* armStart)
147 {
148 {
148 // calculate center angle
149 // calculate center angle
149 *centerAngle = startAngle + (angleSpan/2);
150 *centerAngle = startAngle + (angleSpan/2);
150
151
151 // calculate slice rectangle
152 // calculate slice rectangle
152 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
153 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
153
154
154 // slice path
155 // slice path
155 // TODO: draw the shape so that it might have a hole in the center
156 // TODO: draw the shape so that it might have a hole in the center
156 QPainterPath path;
157 QPainterPath path;
157 path.moveTo(rect.center());
158 path.moveTo(rect.center());
158 path.arcTo(rect, -startAngle + 90, -angleSpan);
159 path.arcTo(rect, -startAngle + 90, -angleSpan);
159 path.closeSubpath();
160 path.closeSubpath();
160
161
161 // calculate label arm start point
162 // calculate label arm start point
162 *armStart = center;
163 *armStart = center;
163 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
164 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
164
165
165 return path;
166 return path;
166 }
167 }
167
168
168 QPainterPath PieSlice::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart)
169 QPainterPath PieSlice::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart)
169 {
170 {
170 qreal dx = qSin(angle*(PI/180)) * length;
171 qreal dx = qSin(angle*(PI/180)) * length;
171 qreal dy = -qCos(angle*(PI/180)) * length;
172 qreal dy = -qCos(angle*(PI/180)) * length;
172 QPointF parm1 = start + QPointF(dx, dy);
173 QPointF parm1 = start + QPointF(dx, dy);
173
174
174 QPointF parm2 = parm1;
175 QPointF parm2 = parm1;
175 if (angle < 180) { // arm swings the other way on the left side
176 if (angle < 180) { // arm swings the other way on the left side
176 parm2 += QPointF(textWidth, 0);
177 parm2 += QPointF(textWidth, 0);
177 *textStart = parm1;
178 *textStart = parm1;
178 }
179 }
179 else {
180 else {
180 parm2 += QPointF(-textWidth,0);
181 parm2 += QPointF(-textWidth,0);
181 *textStart = parm2;
182 *textStart = parm2;
182 }
183 }
183
184
184 // elevate the text position a bit so that it does not hit the line
185 // elevate the text position a bit so that it does not hit the line
185 *textStart += QPointF(0, -5);
186 *textStart += QPointF(0, -5);
186
187
187 QPainterPath path;
188 QPainterPath path;
188 path.moveTo(start);
189 path.moveTo(start);
189 path.lineTo(parm1);
190 path.lineTo(parm1);
190 path.lineTo(parm2);
191 path.lineTo(parm2);
191
192
192 return path;
193 return path;
193 }
194 }
194
195
195 QRectF PieSlice::labelTextRect(QFont font, QString text)
196 QRectF PieSlice::labelTextRect(QFont font, QString text)
196 {
197 {
197 QFontMetricsF fm(font);
198 QFontMetricsF fm(font);
198 return fm.boundingRect(text);
199 return fm.boundingRect(text);
199 }
200 }
200
201
201 #include "moc_pieslice_p.cpp"
202 #include "moc_pieslice_p.cpp"
202
203
203 QTCOMMERCIALCHART_END_NAMESPACE
204 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,80 +1,81
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; // TODO: get rid of this
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 QRectF m_boundingRect;
61
62
62 QPainterPath m_slicePath;
63 QPainterPath m_slicePath;
63 bool m_isExploded;
64 bool m_isExploded;
64 qreal m_explodeDistanceFactor;
65 qreal m_explodeDistanceFactor;
65 bool m_labelVisible;
66 bool m_labelVisible;
66 QPen m_slicePen;
67 QPen m_slicePen;
67 QBrush m_sliceBrush;
68 QBrush m_sliceBrush;
68
69
69 QPainterPath m_labelArmPath;
70 QPainterPath m_labelArmPath;
70 qreal m_labelArmLengthFactor;
71 qreal m_labelArmLengthFactor;
71 QPen m_labelArmPen;
72 QPen m_labelArmPen;
72
73
73 QRectF m_labelTextRect;
74 QRectF m_labelTextRect;
74 QFont m_labelFont;
75 QFont m_labelFont;
75 QString m_labelText;
76 QString m_labelText;
76 };
77 };
77
78
78 QTCOMMERCIALCHART_END_NAMESPACE
79 QTCOMMERCIALCHART_END_NAMESPACE
79
80
80 #endif // PIESLICE_H
81 #endif // PIESLICE_H
@@ -1,565 +1,572
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 \class QPieSeries
8 \class QPieSeries
9 \brief Pie series API for QtCommercial Charts
9 \brief Pie series API for QtCommercial Charts
10
10
11 The pie series defines a pie chart which consists of pie slices which are QPieSlice objects.
11 The pie series defines a pie chart which consists of pie slices which are QPieSlice objects.
12 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
12 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
13 The actual slice size is determined by that relative value.
13 The actual slice size is determined by that relative value.
14
14
15 By default the pie is defined as a full pie but it can be a partial pie.
15 By default the pie is defined as a full pie but it can be a partial pie.
16 This can be done by setting a starting angle and angle span to the series.
16 This can be done by setting a starting angle and angle span to the series.
17 */
17 */
18
18
19 /*!
19 /*!
20 Constructs a series object which is a child of \a parent.
20 Constructs a series object which is a child of \a parent.
21 */
21 */
22 QPieSeries::QPieSeries(QObject *parent) :
22 QPieSeries::QPieSeries(QObject *parent) :
23 QSeries(parent),
23 QSeries(parent),
24 m_pieRelativeHorPos(0.5),
24 m_pieRelativeHorPos(0.5),
25 m_pieRelativeVerPos(0.5),
25 m_pieRelativeVerPos(0.5),
26 m_pieRelativeSize(0.7),
26 m_pieRelativeSize(0.7),
27 m_pieStartAngle(0),
27 m_pieStartAngle(0),
28 m_pieEndAngle(360),
28 m_pieEndAngle(360),
29 m_total(0)
29 m_total(0)
30 {
30 {
31
31
32 }
32 }
33
33
34 /*!
34 /*!
35 Destroys the object. Note that adding series to QChart transfers the ownership to the chart.
35 Destroys the object. Note that adding series to QChart transfers the ownership to the chart.
36 */
36 */
37 QPieSeries::~QPieSeries()
37 QPieSeries::~QPieSeries()
38 {
38 {
39
39
40 }
40 }
41
41
42 /*!
42 /*!
43 Returns QChartSeries::SeriesTypePie.
43 Returns QChartSeries::SeriesTypePie.
44 */
44 */
45 QSeries::QSeriesType QPieSeries::type() const
45 QSeries::QSeriesType QPieSeries::type() const
46 {
46 {
47 return QSeries::SeriesTypePie;
47 return QSeries::SeriesTypePie;
48 }
48 }
49
49
50 /*!
50 /*!
51 Sets an array of \a slices to the series replacing the existing slices.
51 Sets an array of \a slices to the series replacing the existing slices.
52 Slice ownership is passed to the series.
52 Slice ownership is passed to the series.
53 */
53 */
54 void QPieSeries::replace(QList<QPieSlice*> slices)
54 void QPieSeries::replace(QList<QPieSlice*> slices)
55 {
55 {
56 clear();
56 clear();
57 add(slices);
57 add(slices);
58 }
58 }
59
59
60 /*!
60 /*!
61 Adds an array of \a slices to the series.
61 Adds an array of \a slices to the series.
62 Slice ownership is passed to the series.
62 Slice ownership is passed to the series.
63 */
63 */
64 void QPieSeries::add(QList<QPieSlice*> slices)
64 void QPieSeries::add(QList<QPieSlice*> slices)
65 {
65 {
66 foreach (QPieSlice* s, slices) {
66 foreach (QPieSlice* s, slices) {
67 s->setParent(this);
67 s->setParent(this);
68 m_slices << s;
68 m_slices << s;
69 }
69 }
70
70
71 updateDerivativeData();
71 updateDerivativeData();
72
72
73 foreach (QPieSlice* s, slices) {
73 foreach (QPieSlice* s, slices) {
74 connect(s, SIGNAL(changed()), this, SLOT(sliceChanged()));
74 connect(s, SIGNAL(changed()), this, SLOT(sliceChanged()));
75 connect(s, SIGNAL(clicked()), this, SLOT(sliceClicked()));
75 connect(s, SIGNAL(clicked()), this, SLOT(sliceClicked()));
76 connect(s, SIGNAL(hoverEnter()), this, SLOT(sliceHoverEnter()));
76 connect(s, SIGNAL(hoverEnter()), this, SLOT(sliceHoverEnter()));
77 connect(s, SIGNAL(hoverLeave()), this, SLOT(sliceHoverLeave()));
77 connect(s, SIGNAL(hoverLeave()), this, SLOT(sliceHoverLeave()));
78 }
78 }
79
79
80 emit changed();
80 emit added(slices);
81 }
81 }
82
82
83 /*!
83 /*!
84 Adds a single \a slice to the series.
84 Adds a single \a slice to the series.
85 Slice ownership is passed to the series.
85 Slice ownership is passed to the series.
86 */
86 */
87 void QPieSeries::add(QPieSlice* slice)
87 void QPieSeries::add(QPieSlice* slice)
88 {
88 {
89 add(QList<QPieSlice*>() << slice);
89 add(QList<QPieSlice*>() << slice);
90 }
90 }
91
91
92 /*!
92 /*!
93 Adds a single \a slice to the series and returns a reference to the series.
93 Adds a single \a slice to the series and returns a reference to the series.
94 Slice ownership is passed to the series.
94 Slice ownership is passed to the series.
95 */
95 */
96 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
96 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
97 {
97 {
98 add(slice);
98 add(slice);
99 return *this;
99 return *this;
100 }
100 }
101
101
102
102
103 /*!
103 /*!
104 Adds a single slice to the series with give \a value and \a name.
104 Adds a single slice to the series with give \a value and \a name.
105 Slice ownership is passed to the series.
105 Slice ownership is passed to the series.
106 */
106 */
107 QPieSlice* QPieSeries::add(qreal value, QString name)
107 QPieSlice* QPieSeries::add(qreal value, QString name)
108 {
108 {
109 QPieSlice* slice = new QPieSlice(value, name);
109 QPieSlice* slice = new QPieSlice(value, name);
110 add(slice);
110 add(slice);
111 return slice;
111 return slice;
112 }
112 }
113
113
114 void QPieSeries::insert(int i, QPieSlice* slice)
114 void QPieSeries::insert(int i, QPieSlice* slice)
115 {
115 {
116 Q_ASSERT(i <= m_slices.count());
116 Q_ASSERT(i <= m_slices.count());
117 slice->setParent(this);
117 slice->setParent(this);
118 m_slices.insert(i, slice);
118 m_slices.insert(i, slice);
119
119
120 updateDerivativeData();
120 updateDerivativeData();
121
121
122 connect(slice, SIGNAL(changed()), this, SLOT(sliceChanged()));
122 connect(slice, SIGNAL(changed()), this, SLOT(sliceChanged()));
123 connect(slice, SIGNAL(clicked()), this, SLOT(sliceClicked()));
123 connect(slice, SIGNAL(clicked()), this, SLOT(sliceClicked()));
124 connect(slice, SIGNAL(hoverEnter()), this, SLOT(sliceHoverEnter()));
124 connect(slice, SIGNAL(hoverEnter()), this, SLOT(sliceHoverEnter()));
125 connect(slice, SIGNAL(hoverLeave()), this, SLOT(sliceHoverLeave()));
125 connect(slice, SIGNAL(hoverLeave()), this, SLOT(sliceHoverLeave()));
126
126
127 emit changed();
127 emit added(QList<QPieSlice*>() << slice);
128 }
128 }
129
129
130 /*!
130 /*!
131 Removes a single \a slice from the series and deletes the slice.
131 Removes a single \a slice from the series and deletes the slice.
132
132
133 Do not reference this pointer after this call.
133 Do not reference this pointer after this call.
134 */
134 */
135 void QPieSeries::remove(QPieSlice* slice)
135 void QPieSeries::remove(QPieSlice* slice)
136 {
136 {
137 if (!m_slices.removeOne(slice)) {
137 if (!m_slices.removeOne(slice)) {
138 Q_ASSERT(0); // TODO: how should this be reported?
138 Q_ASSERT(0); // TODO: how should this be reported?
139 return;
139 return;
140 }
140 }
141 emit changed();
142
141
143 updateDerivativeData();
142 updateDerivativeData();
144
143
144 emit removed(QList<QPieSlice*>() << slice);
145
145 delete slice;
146 delete slice;
146 slice = NULL;
147 slice = NULL;
147 }
148 }
148
149
149 /*!
150 /*!
150 Clears all slices from the series.
151 Clears all slices from the series.
151 */
152 */
152 void QPieSeries::clear()
153 void QPieSeries::clear()
153 {
154 {
154 if (m_slices.count() == 0)
155 if (m_slices.count() == 0)
155 return;
156 return;
156
157
158 QList<QPieSlice*> slices = m_slices;
157 foreach (QPieSlice* s, m_slices) {
159 foreach (QPieSlice* s, m_slices) {
158 m_slices.removeOne(s);
160 m_slices.removeOne(s);
159 delete s;
161 delete s;
160 }
162 }
161
163
162 emit changed();
163
164 updateDerivativeData();
164 updateDerivativeData();
165
166 emit removed(slices);
165 }
167 }
166
168
167 /*!
169 /*!
168 Counts the number of the slices in this series.
170 Counts the number of the slices in this series.
169 */
171 */
170 int QPieSeries::count() const
172 int QPieSeries::count() const
171 {
173 {
172 return m_slices.count();
174 return m_slices.count();
173 }
175 }
174
176
175 /*!
177 /*!
178 Returns true is the series is empty.
179 */
180 bool QPieSeries::isEmpty() const
181 {
182 return m_slices.isEmpty();
183 }
184
185 /*!
176 Returns a list of slices that belong to this series.
186 Returns a list of slices that belong to this series.
177 */
187 */
178 QList<QPieSlice*> QPieSeries::slices() const
188 QList<QPieSlice*> QPieSeries::slices() const
179 {
189 {
180 return m_slices;
190 return m_slices;
181 }
191 }
182
192
183 /*!
193 /*!
184 Sets the center position of the pie by \a relativeHorizontalPosition and \a relativeVerticalPosition.
194 Sets the center position of the pie by \a relativeHorizontalPosition and \a relativeVerticalPosition.
185
195
186 The factors are relative to the chart rectangle where:
196 The factors are relative to the chart rectangle where:
187
197
188 \a relativeHorizontalPosition 0.0 means the absolute left.
198 \a relativeHorizontalPosition 0.0 means the absolute left.
189 \a relativeHorizontalPosition 1.0 means the absolute right.
199 \a relativeHorizontalPosition 1.0 means the absolute right.
190 \a relativeVerticalPosition 0.0 means the absolute top.
200 \a relativeVerticalPosition 0.0 means the absolute top.
191 \a relativeVerticalPosition 1.0 means the absolute bottom.
201 \a relativeVerticalPosition 1.0 means the absolute bottom.
192
202
193 By default both values are 0.5 which puts the pie in the middle of the chart rectangle.
203 By default both values are 0.5 which puts the pie in the middle of the chart rectangle.
194
204
195 \sa pieHorizontalPosition(), pieVerticalPosition(), setPieSize()
205 \sa pieHorizontalPosition(), pieVerticalPosition(), setPieSize()
196 */
206 */
197 void QPieSeries::setPiePosition(qreal relativeHorizontalPosition, qreal relativeVerticalPosition)
207 void QPieSeries::setPiePosition(qreal relativeHorizontalPosition, qreal relativeVerticalPosition)
198 {
208 {
199 if (relativeHorizontalPosition < 0.0 || relativeHorizontalPosition > 1.0 ||
209 if (relativeHorizontalPosition < 0.0 || relativeHorizontalPosition > 1.0 ||
200 relativeVerticalPosition < 0.0 || relativeVerticalPosition > 1.0)
210 relativeVerticalPosition < 0.0 || relativeVerticalPosition > 1.0)
201 return;
211 return;
202
212
203 if (m_pieRelativeHorPos != relativeHorizontalPosition || m_pieRelativeVerPos != relativeVerticalPosition) {
213 if (m_pieRelativeHorPos != relativeHorizontalPosition || m_pieRelativeVerPos != relativeVerticalPosition) {
204 m_pieRelativeHorPos = relativeHorizontalPosition;
214 m_pieRelativeHorPos = relativeHorizontalPosition;
205 m_pieRelativeVerPos = relativeVerticalPosition;
215 m_pieRelativeVerPos = relativeVerticalPosition;
206 emit changed();
216 emit piePositionChanged();
207 }
217 }
208 }
218 }
209
219
210 /*!
220 /*!
211 Gets the horizontal position of the pie.
221 Gets the horizontal position of the pie.
212
222
213 The returned value is relative to the chart rectangle where:
223 The returned value is relative to the chart rectangle where:
214
224
215 0.0 means the absolute left.
225 0.0 means the absolute left.
216 1.0 means the absolute right.
226 1.0 means the absolute right.
217
227
218 By default it is 0.5 which puts the pie in the horizontal middle of the chart rectangle.
228 By default it is 0.5 which puts the pie in the horizontal middle of the chart rectangle.
219
229
220 \sa setPiePosition(), pieVerticalPosition(), setPieSize()
230 \sa setPiePosition(), pieVerticalPosition(), setPieSize()
221 */
231 */
222 qreal QPieSeries::pieHorizontalPosition() const
232 qreal QPieSeries::pieHorizontalPosition() const
223 {
233 {
224 return m_pieRelativeHorPos;
234 return m_pieRelativeHorPos;
225 }
235 }
226
236
227 /*!
237 /*!
228 Gets the vertical position position of the pie.
238 Gets the vertical position position of the pie.
229
239
230 The returned value is relative to the chart rectangle where:
240 The returned value is relative to the chart rectangle where:
231
241
232 0.0 means the absolute top.
242 0.0 means the absolute top.
233 1.0 means the absolute bottom.
243 1.0 means the absolute bottom.
234
244
235 By default it is 0.5 which puts the pie in the vertical middle of the chart rectangle.
245 By default it is 0.5 which puts the pie in the vertical middle of the chart rectangle.
236
246
237 \sa setPiePosition(), pieHorizontalPosition(), setPieSize()
247 \sa setPiePosition(), pieHorizontalPosition(), setPieSize()
238 */
248 */
239 qreal QPieSeries::pieVerticalPosition() const
249 qreal QPieSeries::pieVerticalPosition() const
240 {
250 {
241 return m_pieRelativeVerPos;
251 return m_pieRelativeVerPos;
242 }
252 }
243
253
244 /*!
254 /*!
245 Sets the relative size of the pie.
255 Sets the relative size of the pie.
246
256
247 The \a relativeSize is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
257 The \a relativeSize is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
248
258
249 Default value is 0.7.
259 Default value is 0.7.
250
260
251 \sa pieSize(), setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
261 \sa pieSize(), setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
252 */
262 */
253 void QPieSeries::setPieSize(qreal relativeSize)
263 void QPieSeries::setPieSize(qreal relativeSize)
254 {
264 {
255 if (relativeSize < 0.0 || relativeSize > 1.0)
265 if (relativeSize < 0.0 || relativeSize > 1.0)
256 return;
266 return;
257
267
258 if (m_pieRelativeSize != relativeSize) {
268 if (m_pieRelativeSize != relativeSize) {
259 m_pieRelativeSize = relativeSize;
269 m_pieRelativeSize = relativeSize;
260 emit changed();
270 emit pieSizeChanged();
261 }
271 }
262 }
272 }
263
273
264 /*!
274 /*!
265 Gets the relative size of the pie.
275 Gets the relative size of the pie.
266
276
267 The size is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
277 The size is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
268
278
269 Default value is 0.7.
279 Default value is 0.7.
270
280
271 \sa setPieSize(), setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
281 \sa setPieSize(), setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
272 */
282 */
273 qreal QPieSeries::pieSize() const
283 qreal QPieSeries::pieSize() const
274 {
284 {
275 return m_pieRelativeSize;
285 return m_pieRelativeSize;
276 }
286 }
277
287
278
288
279 /*!
289 /*!
280 Sets the end angle of the pie.
290 Sets the end angle of the pie.
281
291
282 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
292 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
283
293
284 \a angle must be less than pie end angle. Default value is 0.
294 \a angle must be less than pie end angle. Default value is 0.
285
295
286 \sa pieStartAngle(), pieEndAngle(), setPieEndAngle()
296 \sa pieStartAngle(), pieEndAngle(), setPieEndAngle()
287 */
297 */
288 void QPieSeries::setPieStartAngle(qreal angle)
298 void QPieSeries::setPieStartAngle(qreal angle)
289 {
299 {
290 if (angle >= 0 && angle <= 360 && angle != m_pieStartAngle && angle <= m_pieEndAngle) {
300 if (angle >= 0 && angle <= 360 && angle != m_pieStartAngle && angle <= m_pieEndAngle) {
291 m_pieStartAngle = angle;
301 m_pieStartAngle = angle;
292 updateDerivativeData();
302 updateDerivativeData();
293 }
303 }
294 }
304 }
295
305
296 /*!
306 /*!
297 Gets the start angle of the pie.
307 Gets the start angle of the pie.
298
308
299 Full pie is 360 degrees where 0 degrees is at 12 a'clock. Default value is 360.
309 Full pie is 360 degrees where 0 degrees is at 12 a'clock. Default value is 360.
300
310
301 \sa setPieStartAngle(), pieEndAngle(), setPieEndAngle()
311 \sa setPieStartAngle(), pieEndAngle(), setPieEndAngle()
302 */
312 */
303 qreal QPieSeries::pieStartAngle() const
313 qreal QPieSeries::pieStartAngle() const
304 {
314 {
305 return m_pieStartAngle;
315 return m_pieStartAngle;
306 }
316 }
307
317
308 /*!
318 /*!
309 Sets the end angle of the pie.
319 Sets the end angle of the pie.
310
320
311 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
321 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
312
322
313 \a angle must be greater than start angle.
323 \a angle must be greater than start angle.
314
324
315 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
325 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
316 */
326 */
317 void QPieSeries::setPieEndAngle(qreal angle)
327 void QPieSeries::setPieEndAngle(qreal angle)
318 {
328 {
319 if (angle >= 0 && angle <= 360 && angle != m_pieEndAngle && angle >= m_pieStartAngle) {
329 if (angle >= 0 && angle <= 360 && angle != m_pieEndAngle && angle >= m_pieStartAngle) {
320 m_pieEndAngle = angle;
330 m_pieEndAngle = angle;
321 updateDerivativeData();
331 updateDerivativeData();
322 }
332 }
323 }
333 }
324
334
325 /*!
335 /*!
326 Returns the end angle of the pie.
336 Returns the end angle of the pie.
327
337
328 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
338 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
329
339
330 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
340 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
331 */
341 */
332 qreal QPieSeries::pieEndAngle() const
342 qreal QPieSeries::pieEndAngle() const
333 {
343 {
334 return m_pieEndAngle;
344 return m_pieEndAngle;
335 }
345 }
336
346
337 /*!
347 /*!
338 Sets the all the slice labels \a visible or invisible.
348 Sets the all the slice labels \a visible or invisible.
339
349
340 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
350 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
341 */
351 */
342 void QPieSeries::setLabelsVisible(bool visible)
352 void QPieSeries::setLabelsVisible(bool visible)
343 {
353 {
344 foreach (QPieSlice* s, m_slices)
354 foreach (QPieSlice* s, m_slices)
345 s->setLabelVisible(visible);
355 s->setLabelVisible(visible);
346 }
356 }
347
357
348 /*!
358 /*!
349 Returns the sum of all slice values in this series.
359 Returns the sum of all slice values in this series.
350
360
351 \sa QPieSlice::value(), QPieSlice::setValue()
361 \sa QPieSlice::value(), QPieSlice::setValue()
352 */
362 */
353 qreal QPieSeries::total() const
363 qreal QPieSeries::total() const
354 {
364 {
355 return m_total;
365 return m_total;
356 }
366 }
357
367
358 /*!
368 /*!
359 \fn void QPieSeries::changed()
369 \fn void QPieSeries::changed()
360
370
361 This signal emitted when something has changed in the series.
371 This signal emitted when something has changed in the series.
362
372
363 \sa QPieSeries::ChangeSet, QPieSlice::changed()
373 \sa QPieSeries::ChangeSet, QPieSlice::changed()
364 */
374 */
365
375
366 /*!
376 /*!
367 \fn void QPieSeries::clicked(QPieSlice* slice)
377 \fn void QPieSeries::clicked(QPieSlice* slice)
368
378
369 This signal is emitted when a \a slice has been clicked.
379 This signal is emitted when a \a slice has been clicked.
370
380
371 \sa QPieSlice::clicked()
381 \sa QPieSlice::clicked()
372 */
382 */
373
383
374 /*!
384 /*!
375 \fn void QPieSeries::hoverEnter(QPieSlice* slice)
385 \fn void QPieSeries::hoverEnter(QPieSlice* slice)
376
386
377 This signal is emitted when user has hovered over a \a slice.
387 This signal is emitted when user has hovered over a \a slice.
378
388
379 \sa QPieSlice::hoverEnter()
389 \sa QPieSlice::hoverEnter()
380 */
390 */
381
391
382 /*!
392 /*!
383 \fn void QPieSeries::hoverLeave(QPieSlice* slice)
393 \fn void QPieSeries::hoverLeave(QPieSlice* slice)
384
394
385 This signal is emitted when user has hovered away from a \a slice.
395 This signal is emitted when user has hovered away from a \a slice.
386
396
387 \sa QPieSlice::hoverLeave()
397 \sa QPieSlice::hoverLeave()
388 */
398 */
389
399
390 void QPieSeries::sliceChanged()
400 void QPieSeries::sliceChanged()
391 {
401 {
392 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
402 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
393 Q_ASSERT(m_slices.contains(slice));
403 Q_ASSERT(m_slices.contains(slice));
394 updateDerivativeData();
404 updateDerivativeData();
395 }
405 }
396
406
397 void QPieSeries::sliceClicked()
407 void QPieSeries::sliceClicked()
398 {
408 {
399 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
409 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
400 Q_ASSERT(m_slices.contains(slice));
410 Q_ASSERT(m_slices.contains(slice));
401 emit clicked(slice);
411 emit clicked(slice);
402 }
412 }
403
413
404 void QPieSeries::sliceHoverEnter()
414 void QPieSeries::sliceHoverEnter()
405 {
415 {
406 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
416 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
407 Q_ASSERT(m_slices.contains(slice));
417 Q_ASSERT(m_slices.contains(slice));
408 emit hoverEnter(slice);
418 emit hoverEnter(slice);
409 }
419 }
410
420
411 void QPieSeries::sliceHoverLeave()
421 void QPieSeries::sliceHoverLeave()
412 {
422 {
413 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
423 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
414 Q_ASSERT(m_slices.contains(slice));
424 Q_ASSERT(m_slices.contains(slice));
415 emit hoverLeave(slice);
425 emit hoverLeave(slice);
416 }
426 }
417
427
418 void QPieSeries::updateDerivativeData()
428 void QPieSeries::updateDerivativeData()
419 {
429 {
420 m_total = 0;
430 m_total = 0;
421
431
422 // nothing to do?
432 // nothing to do?
423 if (m_slices.count() == 0)
433 if (m_slices.count() == 0)
424 return;
434 return;
425
435
426 // calculate total
436 // calculate total
427 foreach (QPieSlice* s, m_slices)
437 foreach (QPieSlice* s, m_slices)
428 m_total += s->value();
438 m_total += s->value();
429
439
430 // TODO: emit totalChanged?
440 // nothing to show..
431
441 if (m_total == 0)
432 // we must have some values
442 return;
433 if (m_total == 0) {
434 qDebug() << "QPieSeries::updateDerivativeData() total == 0";
435 Q_ASSERT(m_total > 0); // TODO: is this the correct way to handle this?
436 }
437
443
438 // update slice attributes
444 // update slice attributes
439 qreal sliceAngle = m_pieStartAngle;
445 qreal sliceAngle = m_pieStartAngle;
440 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
446 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
441 QVector<QPieSlice*> changed;
447 QVector<QPieSlice*> changed;
442 foreach (QPieSlice* s, m_slices) {
448 foreach (QPieSlice* s, m_slices) {
443
449
444 bool isChanged = false;
450 bool isChanged = false;
445
451
446 qreal percentage = s->value() / m_total;
452 qreal percentage = s->value() / m_total;
447 if (s->m_percentage != percentage) {
453 if (s->m_percentage != percentage) {
448 s->m_percentage = percentage;
454 s->m_percentage = percentage;
449 isChanged = true;
455 isChanged = true;
450 }
456 }
451
457
452 qreal sliceSpan = pieSpan * percentage;
458 qreal sliceSpan = pieSpan * percentage;
453 if (s->m_angleSpan != sliceSpan) {
459 if (s->m_angleSpan != sliceSpan) {
454 s->m_angleSpan = sliceSpan;
460 s->m_angleSpan = sliceSpan;
455 isChanged = true;
461 isChanged = true;
456 }
462 }
457
463
458 if (s->m_startAngle != sliceAngle) {
464 if (s->m_startAngle != sliceAngle) {
459 s->m_startAngle = sliceAngle;
465 s->m_startAngle = sliceAngle;
460 isChanged = true;
466 isChanged = true;
461 }
467 }
462 sliceAngle += sliceSpan;
468 sliceAngle += sliceSpan;
463
469
464 if (isChanged)
470 if (isChanged)
465 changed << s;
471 changed << s;
466 }
472 }
467
473
474 // emit signals
468 foreach (QPieSlice* s, changed)
475 foreach (QPieSlice* s, changed)
469 emit s->changed();
476 emit s->changed();
470 }
477 }
471
478
472 bool QPieSeries::setModel(QAbstractItemModel* model)
479 bool QPieSeries::setModel(QAbstractItemModel* model)
473 {
480 {
474 // disconnect signals from old model
481 // disconnect signals from old model
475 if(m_model)
482 if(m_model)
476 {
483 {
477 disconnect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), 0, 0);
484 disconnect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), 0, 0);
478 disconnect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), 0, 0);
485 disconnect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), 0, 0);
479 disconnect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), 0, 0);
486 disconnect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), 0, 0);
480 }
487 }
481
488
482 // set new model if not NULL and connect necessary signals from it
489 // set new model if not NULL and connect necessary signals from it
483 if(model)
490 if(model)
484 {
491 {
485 m_model = model;
492 m_model = model;
486 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex, QModelIndex)));
493 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex, QModelIndex)));
487 connect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
494 connect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
488 connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
495 connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
489 }
496 }
490
497
491 return true;
498 return true;
492 }
499 }
493
500
494 void QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
501 void QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
495 {
502 {
496 m_mapValues = modelValuesLine;
503 m_mapValues = modelValuesLine;
497 m_mapLabels = modelLabelsLine;
504 m_mapLabels = modelLabelsLine;
498 m_mapOrientation = orientation;
505 m_mapOrientation = orientation;
499
506
500 if (m_model == NULL)
507 if (m_model == NULL)
501 return;
508 return;
502
509
503 if (m_mapOrientation == Qt::Vertical)
510 if (m_mapOrientation == Qt::Vertical)
504 for (int i = 0; i < m_model->rowCount(); i++)
511 for (int i = 0; i < m_model->rowCount(); i++)
505 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());
512 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());
506 else
513 else
507 for (int i = 0; i < m_model->columnCount(); i++)
514 for (int i = 0; i < m_model->columnCount(); i++)
508 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());
515 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());
509
516
510
517
511 }
518 }
512
519
513 void QPieSeries::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
520 void QPieSeries::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
514 {
521 {
515 Q_UNUSED(bottomRight)
522 Q_UNUSED(bottomRight)
516
523
517 if (m_mapOrientation == Qt::Vertical)
524 if (m_mapOrientation == Qt::Vertical)
518 {
525 {
519 // slices().at(topLeft.row())->setValue(m_model->data(m_model->index(topLeft.row(), topLeft.column()), Qt::DisplayRole).toDouble());
526 // slices().at(topLeft.row())->setValue(m_model->data(m_model->index(topLeft.row(), topLeft.column()), Qt::DisplayRole).toDouble());
520 if (topLeft.column() == m_mapValues)
527 if (topLeft.column() == m_mapValues)
521 slices().at(topLeft.row())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
528 slices().at(topLeft.row())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
522 else if (topLeft.column() == m_mapLabels)
529 else if (topLeft.column() == m_mapLabels)
523 slices().at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
530 slices().at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
524 }
531 }
525 else
532 else
526 {
533 {
527 // slices().at(topLeft.column())->setValue(m_model->data(m_model->index(topLeft.row(), topLeft.column()), Qt::DisplayRole).toDouble());
534 // slices().at(topLeft.column())->setValue(m_model->data(m_model->index(topLeft.row(), topLeft.column()), Qt::DisplayRole).toDouble());
528 if (topLeft.column() == m_mapValues)
535 if (topLeft.column() == m_mapValues)
529 slices().at(topLeft.column())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
536 slices().at(topLeft.column())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
530 else if (topLeft.column() == m_mapLabels)
537 else if (topLeft.column() == m_mapLabels)
531 slices().at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
538 slices().at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
532 }
539 }
533 }
540 }
534
541
535 void QPieSeries::modelDataAdded(QModelIndex parent, int start, int end)
542 void QPieSeries::modelDataAdded(QModelIndex parent, int start, int end)
536 {
543 {
537 Q_UNUSED(parent)
544 Q_UNUSED(parent)
538 Q_UNUSED(end)
545 Q_UNUSED(end)
539
546
540 QPieSlice* newSlice = new QPieSlice;
547 QPieSlice* newSlice = new QPieSlice;
541 newSlice->setLabelVisible(true);
548 newSlice->setLabelVisible(true);
542 if (m_mapOrientation == Qt::Vertical)
549 if (m_mapOrientation == Qt::Vertical)
543 {
550 {
544 newSlice->setValue(m_model->data(m_model->index(start, m_mapValues), Qt::DisplayRole).toDouble());
551 newSlice->setValue(m_model->data(m_model->index(start, m_mapValues), Qt::DisplayRole).toDouble());
545 newSlice->setLabel(m_model->data(m_model->index(start, m_mapLabels), Qt::DisplayRole).toString());
552 newSlice->setLabel(m_model->data(m_model->index(start, m_mapLabels), Qt::DisplayRole).toString());
546 }
553 }
547 else
554 else
548 {
555 {
549 newSlice->setValue(m_model->data(m_model->index(m_mapValues, start), Qt::DisplayRole).toDouble());
556 newSlice->setValue(m_model->data(m_model->index(m_mapValues, start), Qt::DisplayRole).toDouble());
550 newSlice->setLabel(m_model->data(m_model->index(m_mapLabels, start), Qt::DisplayRole).toString());
557 newSlice->setLabel(m_model->data(m_model->index(m_mapLabels, start), Qt::DisplayRole).toString());
551 }
558 }
552
559
553 insert(start, newSlice);
560 insert(start, newSlice);
554 }
561 }
555
562
556 void QPieSeries::modelDataRemoved(QModelIndex parent, int start, int end)
563 void QPieSeries::modelDataRemoved(QModelIndex parent, int start, int end)
557 {
564 {
558 Q_UNUSED(parent)
565 Q_UNUSED(parent)
559 Q_UNUSED(end)
566 Q_UNUSED(end)
560 remove(slices().at(start));
567 remove(slices().at(start));
561 }
568 }
562
569
563 #include "moc_qpieseries.cpp"
570 #include "moc_qpieseries.cpp"
564
571
565 QTCOMMERCIALCHART_END_NAMESPACE
572 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,113 +1,119
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
6
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 class QPieSlice;
8 class QPieSlice;
9
9
10 class QTCOMMERCIALCHART_EXPORT QPieSeries : public QSeries
10 class QTCOMMERCIALCHART_EXPORT QPieSeries : public QSeries
11 {
11 {
12 Q_OBJECT
12 Q_OBJECT
13
13
14 public:
14 public:
15 QPieSeries(QObject *parent = 0);
15 QPieSeries(QObject *parent = 0);
16 virtual ~QPieSeries();
16 virtual ~QPieSeries();
17
17
18 public: // from QChartSeries
18 public: // from QChartSeries
19 QSeriesType type() const;
19 QSeriesType type() const;
20
20
21 public:
21 public:
22
22
23 // slice setters
23 // slice setters
24 void add(QPieSlice* slice);
24 void add(QPieSlice* slice);
25 void add(QList<QPieSlice*> slices);
25 void add(QList<QPieSlice*> slices);
26 void insert(int i, QPieSlice* slice);
26 void insert(int i, QPieSlice* slice);
27 void replace(QList<QPieSlice*> slices);
27 void replace(QList<QPieSlice*> slices);
28 void remove(QPieSlice* slice);
28 void remove(QPieSlice* slice);
29 void clear();
29 void clear();
30
30
31 // sluce getters
31 // sluce getters
32 QList<QPieSlice*> slices() const;
32 QList<QPieSlice*> slices() const;
33
33
34 // calculated data
34 // calculated data
35 int count() const;
35 int count() const;
36 bool isEmpty() const;
36 qreal total() const;
37 qreal total() const;
37
38
38 // pie customization
39 // pie customization
39 void setPiePosition(qreal relativeHorizontalPosition, qreal relativeVerticalPosition);
40 void setPiePosition(qreal relativeHorizontalPosition, qreal relativeVerticalPosition);
40 qreal pieHorizontalPosition() const;
41 qreal pieHorizontalPosition() const;
41 qreal pieVerticalPosition() const;
42 qreal pieVerticalPosition() const;
42 void setPieSize(qreal relativeSize);
43 void setPieSize(qreal relativeSize);
43 qreal pieSize() const;
44 qreal pieSize() const;
44 void setPieStartAngle(qreal startAngle);
45 void setPieStartAngle(qreal startAngle);
45 qreal pieStartAngle() const;
46 qreal pieStartAngle() const;
46 void setPieEndAngle(qreal endAngle);
47 void setPieEndAngle(qreal endAngle);
47 qreal pieEndAngle() const;
48 qreal pieEndAngle() const;
48
49
49 // convenience function
50 // convenience function
50 QPieSeries& operator << (QPieSlice* slice);
51 QPieSeries& operator << (QPieSlice* slice);
51 QPieSlice* add(qreal value, QString name);
52 QPieSlice* add(qreal value, QString name);
52 void setLabelsVisible(bool visible = true);
53 void setLabelsVisible(bool visible = true);
53
54
54 // data from model
55 // data from model
55 bool setModel(QAbstractItemModel* model);
56 bool setModel(QAbstractItemModel* model);
56 void setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation = Qt::Vertical);
57 void setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation = Qt::Vertical);
57
58
58 // TODO: find slices?
59 // TODO: find slices?
59 // QList<QPieSlice*> findByValue(qreal value);
60 // QList<QPieSlice*> findByValue(qreal value);
60 // ...
61 // ...
61
62
62 // TODO: sorting slices?
63 // TODO: sorting slices?
63 // void sort(QPieSeries::SortByValue|label|??)
64 // void sort(QPieSeries::SortByValue|label|??)
64
65
65 // TODO: general graphics customization
66 // TODO: general graphics customization
66 // setDrawStyle(2d|3d)
67 // setDrawStyle(2d|3d)
67 // setDropShadows
68 // setDropShadows
68
69
69 Q_SIGNALS:
70 Q_SIGNALS:
70 void clicked(QPieSlice* slice);
71 void clicked(QPieSlice* slice);
71 void hoverEnter(QPieSlice* slice);
72 void hoverEnter(QPieSlice* slice);
72 void hoverLeave(QPieSlice* slice);
73 void hoverLeave(QPieSlice* slice);
73 void changed(); // TODO: hide this in PIMPL
74
75 // TODO: hide these in PIMPL
76 void added(QList<QPieSlice*> slices);
77 void removed(QList<QPieSlice*> slices);
78 void piePositionChanged();
79 void pieSizeChanged();
74
80
75 private Q_SLOTS: // TODO: should be private and not visible in the interface at all
81 private Q_SLOTS: // TODO: should be private and not visible in the interface at all
76 void sliceChanged();
82 void sliceChanged();
77 void sliceClicked();
83 void sliceClicked();
78 void sliceHoverEnter();
84 void sliceHoverEnter();
79 void sliceHoverLeave();
85 void sliceHoverLeave();
80
86
81 // slots for updating pie when data in model changes
87 // slots for updating pie when data in model changes
82 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
88 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
83 void modelDataAdded(QModelIndex parent, int start, int end);
89 void modelDataAdded(QModelIndex parent, int start, int end);
84 void modelDataRemoved(QModelIndex parent, int start, int end);
90 void modelDataRemoved(QModelIndex parent, int start, int end);
85
91
86 private:
92 private:
87 void updateDerivativeData();
93 void updateDerivativeData();
88
94
89 private:
95 private:
90 Q_DISABLE_COPY(QPieSeries)
96 Q_DISABLE_COPY(QPieSeries)
91
97
92 // TODO: use PIML
98 // TODO: use PIML
93 friend class PieChartItem;
99 friend class PieChartItem;
94 friend class PieSlice;
100 friend class PieSlice;
95 friend class QPieSlice;
101 friend class QPieSlice;
96
102
97 QList<QPieSlice*> m_slices;
103 QList<QPieSlice*> m_slices;
98 qreal m_pieRelativeHorPos;
104 qreal m_pieRelativeHorPos;
99 qreal m_pieRelativeVerPos;
105 qreal m_pieRelativeVerPos;
100 qreal m_pieRelativeSize;
106 qreal m_pieRelativeSize;
101 qreal m_pieStartAngle;
107 qreal m_pieStartAngle;
102 qreal m_pieEndAngle;
108 qreal m_pieEndAngle;
103 qreal m_total;
109 qreal m_total;
104
110
105 // model map
111 // model map
106 int m_mapValues;
112 int m_mapValues;
107 int m_mapLabels;
113 int m_mapLabels;
108 Qt::Orientation m_mapOrientation;
114 Qt::Orientation m_mapOrientation;
109 };
115 };
110
116
111 QTCOMMERCIALCHART_END_NAMESPACE
117 QTCOMMERCIALCHART_END_NAMESPACE
112
118
113 #endif // PIESERIES_H
119 #endif // PIESERIES_H
General Comments 0
You need to be logged in to leave comments. Login now