##// END OF EJS Templates
Add mousebuttons to pie clicked signals
Jani Honkonen -
r707:0529e02041c3
parent child
Show More
@@ -1,608 +1,610
1 1 #include <QtGui/QApplication>
2 2 #include <QMainWindow>
3 3 #include <qchartglobal.h>
4 4 #include <qchartview.h>
5 5 #include <qpieseries.h>
6 6 #include <qpieslice.h>
7 7 #include <QGridLayout>
8 8 #include <QFormLayout>
9 9 #include <QComboBox>
10 10 #include <QSpinBox>
11 11 #include <QCheckBox>
12 12 #include <QGroupBox>
13 13 #include <QLabel>
14 14 #include <QPushButton>
15 15 #include <QColorDialog>
16 16 #include <QFontDialog>
17 17
18 18 QTCOMMERCIALCHART_USE_NAMESPACE
19 19
20 20 class PenTool : public QWidget
21 21 {
22 22 Q_OBJECT
23 23
24 24 public:
25 25 explicit PenTool(QString title, QWidget *parent = 0)
26 26 :QWidget(parent)
27 27 {
28 28 setWindowTitle(title);
29 29 setWindowFlags(Qt::Tool);
30 30
31 31 m_colorButton = new QPushButton();
32 32
33 33 m_widthSpinBox = new QDoubleSpinBox();
34 34
35 35 m_styleCombo = new QComboBox();
36 36 m_styleCombo->addItem("NoPen");
37 37 m_styleCombo->addItem("SolidLine");
38 38 m_styleCombo->addItem("DashLine");
39 39 m_styleCombo->addItem("DotLine");
40 40 m_styleCombo->addItem("DashDotLine");
41 41 m_styleCombo->addItem("DashDotDotLine");
42 42
43 43 m_capStyleCombo = new QComboBox();
44 44 m_capStyleCombo->addItem("FlatCap", Qt::FlatCap);
45 45 m_capStyleCombo->addItem("SquareCap", Qt::SquareCap);
46 46 m_capStyleCombo->addItem("RoundCap", Qt::RoundCap);
47 47
48 48 m_joinStyleCombo = new QComboBox();
49 49 m_joinStyleCombo->addItem("MiterJoin", Qt::MiterJoin);
50 50 m_joinStyleCombo->addItem("BevelJoin", Qt::BevelJoin);
51 51 m_joinStyleCombo->addItem("RoundJoin", Qt::RoundJoin);
52 52 m_joinStyleCombo->addItem("SvgMiterJoin", Qt::SvgMiterJoin);
53 53
54 54 QFormLayout *layout = new QFormLayout();
55 55 layout->addRow("Color", m_colorButton);
56 56 layout->addRow("Width", m_widthSpinBox);
57 57 layout->addRow("Style", m_styleCombo);
58 58 layout->addRow("Cap style", m_capStyleCombo);
59 59 layout->addRow("Join style", m_joinStyleCombo);
60 60 setLayout(layout);
61 61
62 62 connect(m_colorButton, SIGNAL(clicked()), this, SLOT(showColorDialog()));
63 63 connect(m_widthSpinBox, SIGNAL(valueChanged(double)), this, SLOT(updateWidth(double)));
64 64 connect(m_styleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateStyle(int)));
65 65 connect(m_capStyleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateCapStyle(int)));
66 66 connect(m_joinStyleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateJoinStyle(int)));
67 67 }
68 68
69 69 void setPen(QPen pen)
70 70 {
71 71 m_pen = pen;
72 72 m_colorButton->setText(m_pen.color().name());
73 73 m_widthSpinBox->setValue(m_pen.widthF());
74 74 m_styleCombo->setCurrentIndex(m_pen.style()); // index matches the enum
75 75 m_capStyleCombo->setCurrentIndex(m_capStyleCombo->findData(m_pen.capStyle()));
76 76 m_joinStyleCombo->setCurrentIndex(m_joinStyleCombo->findData(m_pen.joinStyle()));
77 77 }
78 78
79 79 QPen pen() const
80 80 {
81 81 return m_pen;
82 82 }
83 83
84 84 QString name()
85 85 {
86 86 return name(m_pen);
87 87 }
88 88
89 89 static QString name(const QPen &pen)
90 90 {
91 91 return pen.color().name() + ":" + QString::number(pen.widthF());
92 92 }
93 93
94 94 Q_SIGNALS:
95 95 void changed();
96 96
97 97 public Q_SLOTS:
98 98
99 99 void showColorDialog()
100 100 {
101 101 QColorDialog dialog(m_pen.color());
102 102 dialog.show();
103 103 dialog.exec();
104 104 m_pen.setColor(dialog.selectedColor());
105 105 m_colorButton->setText(m_pen.color().name());
106 106 emit changed();
107 107 }
108 108
109 109 void updateWidth(double width)
110 110 {
111 111 if (width != m_pen.widthF()) {
112 112 m_pen.setWidthF(width);
113 113 emit changed();
114 114 }
115 115 }
116 116
117 117 void updateStyle(int style)
118 118 {
119 119 if (m_pen.style() != style) {
120 120 m_pen.setStyle((Qt::PenStyle) style);
121 121 emit changed();
122 122 }
123 123 }
124 124
125 125 void updateCapStyle(int index)
126 126 {
127 127 Qt::PenCapStyle capStyle = (Qt::PenCapStyle) m_capStyleCombo->itemData(index).toInt();
128 128 if (m_pen.capStyle() != capStyle) {
129 129 m_pen.setCapStyle(capStyle);
130 130 emit changed();
131 131 }
132 132 }
133 133
134 134 void updateJoinStyle(int index)
135 135 {
136 136 Qt::PenJoinStyle joinStyle = (Qt::PenJoinStyle) m_joinStyleCombo->itemData(index).toInt();
137 137 if (m_pen.joinStyle() != joinStyle) {
138 138 m_pen.setJoinStyle(joinStyle);
139 139 emit changed();
140 140 }
141 141 }
142 142
143 143 private:
144 144 QPen m_pen;
145 145 QPushButton *m_colorButton;
146 146 QDoubleSpinBox *m_widthSpinBox;
147 147 QComboBox *m_styleCombo;
148 148 QComboBox *m_capStyleCombo;
149 149 QComboBox *m_joinStyleCombo;
150 150 };
151 151
152 152 class BrushTool : public QWidget
153 153 {
154 154 Q_OBJECT
155 155
156 156 public:
157 157 explicit BrushTool(QString title, QWidget *parent = 0)
158 158 :QWidget(parent)
159 159 {
160 160 setWindowTitle(title);
161 161 setWindowFlags(Qt::Tool);
162 162
163 163 m_colorButton = new QPushButton();
164 164 m_styleCombo = new QComboBox();
165 165 m_styleCombo->addItem("Nobrush", Qt::NoBrush);
166 166 m_styleCombo->addItem("Solidpattern", Qt::SolidPattern);
167 167 m_styleCombo->addItem("Dense1pattern", Qt::Dense1Pattern);
168 168 m_styleCombo->addItem("Dense2attern", Qt::Dense2Pattern);
169 169 m_styleCombo->addItem("Dense3Pattern", Qt::Dense3Pattern);
170 170 m_styleCombo->addItem("Dense4Pattern", Qt::Dense4Pattern);
171 171 m_styleCombo->addItem("Dense5Pattern", Qt::Dense5Pattern);
172 172 m_styleCombo->addItem("Dense6Pattern", Qt::Dense6Pattern);
173 173 m_styleCombo->addItem("Dense7Pattern", Qt::Dense7Pattern);
174 174 m_styleCombo->addItem("HorPattern", Qt::HorPattern);
175 175 m_styleCombo->addItem("VerPattern", Qt::VerPattern);
176 176 m_styleCombo->addItem("CrossPattern", Qt::CrossPattern);
177 177 m_styleCombo->addItem("BDiagPattern", Qt::BDiagPattern);
178 178 m_styleCombo->addItem("FDiagPattern", Qt::FDiagPattern);
179 179 m_styleCombo->addItem("DiagCrossPattern", Qt::DiagCrossPattern);
180 180
181 181 QFormLayout *layout = new QFormLayout();
182 182 layout->addRow("Color", m_colorButton);
183 183 layout->addRow("Style", m_styleCombo);
184 184 setLayout(layout);
185 185
186 186 connect(m_colorButton, SIGNAL(clicked()), this, SLOT(showColorDialog()));
187 187 connect(m_styleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateStyle()));
188 188 }
189 189
190 190 void setBrush(QBrush brush)
191 191 {
192 192 m_brush = brush;
193 193 m_colorButton->setText(m_brush.color().name());
194 194 m_styleCombo->setCurrentIndex(m_brush.style()); // index matches the enum
195 195 }
196 196
197 197 QBrush brush() const
198 198 {
199 199 return m_brush;
200 200 }
201 201
202 202 QString name()
203 203 {
204 204 return name(m_brush);
205 205 }
206 206
207 207 static QString name(const QBrush &brush)
208 208 {
209 209 return brush.color().name();
210 210 }
211 211
212 212 Q_SIGNALS:
213 213 void changed();
214 214
215 215 public Q_SLOTS:
216 216
217 217 void showColorDialog()
218 218 {
219 219 QColorDialog dialog(m_brush.color());
220 220 dialog.show();
221 221 dialog.exec();
222 222 m_brush.setColor(dialog.selectedColor());
223 223 m_colorButton->setText(m_brush.color().name());
224 224 emit changed();
225 225 }
226 226
227 227 void updateStyle()
228 228 {
229 229 Qt::BrushStyle style = (Qt::BrushStyle) m_styleCombo->itemData(m_styleCombo->currentIndex()).toInt();
230 230 if (m_brush.style() != style) {
231 231 m_brush.setStyle(style);
232 232 emit changed();
233 233 }
234 234 }
235 235
236 236 private:
237 237 QBrush m_brush;
238 238 QPushButton *m_colorButton;
239 239 QComboBox *m_styleCombo;
240 240 };
241 241
242 242 class CustomSlice : public QPieSlice
243 243 {
244 244 Q_OBJECT
245 245 public:
246 246 CustomSlice(qreal value, QString label)
247 247 :QPieSlice(value, label)
248 248 {
249 249 connect(this, SIGNAL(hoverEnter()), this, SLOT(handleHoverEnter()));
250 250 connect(this, SIGNAL(hoverLeave()), this, SLOT(handleHoverLeave()));
251 251 }
252 252
253 253 public:
254 254 QBrush originalBrush()
255 255 {
256 256 return m_originalBrush;
257 257 }
258 258
259 259 public Q_SLOTS:
260 260
261 261 void handleHoverEnter()
262 262 {
263 263 QBrush brush = this->sliceBrush();
264 264 m_originalBrush = brush;
265 265 brush.setColor(brush.color().lighter());
266 266 setSliceBrush(brush);
267 267 }
268 268
269 269 void handleHoverLeave()
270 270 {
271 271 setSliceBrush(m_originalBrush);
272 272 }
273 273
274 274 private:
275 275 QBrush m_originalBrush;
276 276 };
277 277
278 278 class MainWidget : public QWidget
279 279 {
280 280 Q_OBJECT
281 281
282 282 public:
283 283 explicit MainWidget(QWidget* parent = 0)
284 284 :QWidget(parent),
285 285 m_slice(0)
286 286 {
287 287 // create chart
288 288 m_chartView = new QChartView();
289 289 m_chartView->setChartTitle("Piechart customization");
290 290 m_chartView->setAnimationOptions(QChart::AllAnimations);
291 291
292 292 // create series
293 293 m_series = new QPieSeries();
294 294 *m_series << new CustomSlice(10.0, "Slice 1");
295 295 *m_series << new CustomSlice(20.0, "Slice 2");
296 296 *m_series << new CustomSlice(30.0, "Slice 3");
297 297 *m_series << new CustomSlice(40.0, "Slice 4");
298 298 *m_series << new CustomSlice(50.0, "Slice 5");
299 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*, Qt::MouseButtons)), this, SLOT(handleSliceClicked(QPieSlice*, Qt::MouseButtons)));
302 302
303 303 // chart settings
304 304 m_themeComboBox = new QComboBox();
305 305 m_themeComboBox->addItem("Default", QChart::ChartThemeDefault);
306 306 m_themeComboBox->addItem("Light", QChart::ChartThemeLight);
307 307 m_themeComboBox->addItem("BlueCerulean", QChart::ChartThemeBlueCerulean);
308 308 m_themeComboBox->addItem("Dark", QChart::ChartThemeDark);
309 309 m_themeComboBox->addItem("BrownSand", QChart::ChartThemeBrownSand);
310 310 m_themeComboBox->addItem("BlueNcs", QChart::ChartThemeBlueNcs);
311 311 m_themeComboBox->addItem("Icy", QChart::ChartThemeIcy);
312 312 m_themeComboBox->addItem("Scientific", QChart::ChartThemeScientific);
313 313
314 314 m_aaCheckBox = new QCheckBox();
315 315 m_animationsCheckBox = new QCheckBox();
316 316 m_animationsCheckBox->setCheckState(Qt::Checked);
317 317
318 318 QFormLayout* chartSettingsLayout = new QFormLayout();
319 319 chartSettingsLayout->addRow("Theme", m_themeComboBox);
320 320 chartSettingsLayout->addRow("Antialiasing", m_aaCheckBox);
321 321 chartSettingsLayout->addRow("Animations", m_animationsCheckBox);
322 322 QGroupBox* chartSettings = new QGroupBox("Chart");
323 323 chartSettings->setLayout(chartSettingsLayout);
324 324
325 325 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this ,SLOT(updateChartSettings()));
326 326 connect(m_aaCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
327 327 connect(m_animationsCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
328 328
329 329 // series settings
330 330 m_hPosition = new QDoubleSpinBox();
331 331 m_hPosition->setMinimum(0.0);
332 332 m_hPosition->setMaximum(1.0);
333 333 m_hPosition->setSingleStep(0.1);
334 334 m_hPosition->setValue(m_series->pieHorizontalPosition());
335 335
336 336 m_vPosition = new QDoubleSpinBox();
337 337 m_vPosition->setMinimum(0.0);
338 338 m_vPosition->setMaximum(1.0);
339 339 m_vPosition->setSingleStep(0.1);
340 340 m_vPosition->setValue(m_series->pieVerticalPosition());
341 341
342 342 m_sizeFactor = new QDoubleSpinBox();
343 343 m_sizeFactor->setMinimum(0.0);
344 344 m_sizeFactor->setMaximum(1.0);
345 345 m_sizeFactor->setSingleStep(0.1);
346 346 m_sizeFactor->setValue(m_series->pieSize());
347 347
348 348 m_startAngle = new QDoubleSpinBox();
349 349 m_startAngle->setMinimum(0.0);
350 350 m_startAngle->setMaximum(360);
351 351 m_startAngle->setValue(m_series->pieStartAngle());
352 352 m_startAngle->setSingleStep(1);
353 353
354 354 m_endAngle = new QDoubleSpinBox();
355 355 m_endAngle->setMinimum(0.0);
356 356 m_endAngle->setMaximum(360);
357 357 m_endAngle->setValue(m_series->pieEndAngle());
358 358 m_endAngle->setSingleStep(1);
359 359
360 360 QPushButton *addSlice = new QPushButton("Add slice");
361 361 QPushButton *insertSlice = new QPushButton("Insert slice");
362 362
363 363 QFormLayout* seriesSettingsLayout = new QFormLayout();
364 364 seriesSettingsLayout->addRow("Horizontal position", m_hPosition);
365 365 seriesSettingsLayout->addRow("Vertical position", m_vPosition);
366 366 seriesSettingsLayout->addRow("Size factor", m_sizeFactor);
367 367 seriesSettingsLayout->addRow("Start angle", m_startAngle);
368 368 seriesSettingsLayout->addRow("End angle", m_endAngle);
369 369 seriesSettingsLayout->addRow(addSlice);
370 370 seriesSettingsLayout->addRow(insertSlice);
371 371 QGroupBox* seriesSettings = new QGroupBox("Series");
372 372 seriesSettings->setLayout(seriesSettingsLayout);
373 373
374 374 connect(m_vPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
375 375 connect(m_hPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
376 376 connect(m_sizeFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
377 377 connect(m_startAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
378 378 connect(m_endAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
379 379 connect(addSlice, SIGNAL(clicked()), this, SLOT(addSlice()));
380 380 connect(insertSlice, SIGNAL(clicked()), this, SLOT(insertSlice()));
381 381
382 382 // slice settings
383 383 m_sliceName = new QLabel("<click a slice>");
384 384 m_sliceValue = new QDoubleSpinBox();
385 385 m_sliceValue->setMaximum(1000);
386 386 m_sliceLabelVisible = new QCheckBox();
387 387 m_sliceLabelArmFactor = new QDoubleSpinBox();
388 388 m_sliceLabelArmFactor->setSingleStep(0.01);
389 389 m_sliceExploded = new QCheckBox();
390 390 m_sliceExplodedFactor = new QDoubleSpinBox();
391 391 m_sliceExplodedFactor->setSingleStep(0.01);
392 392 m_pen = new QPushButton();
393 393 m_penTool = new PenTool("Slice pen", this);
394 394 m_brush = new QPushButton();
395 395 m_brushTool = new BrushTool("Slice brush", this);
396 396 m_font = new QPushButton();
397 397 m_labelArmPen = new QPushButton();
398 398 m_labelArmPenTool = new PenTool("Label arm pen", this);
399 399 QPushButton *removeSlice = new QPushButton("Remove slice");
400 400
401 401 QFormLayout* sliceSettingsLayout = new QFormLayout();
402 402 sliceSettingsLayout->addRow("Selected", m_sliceName);
403 403 sliceSettingsLayout->addRow("Value", m_sliceValue);
404 404 sliceSettingsLayout->addRow("Pen", m_pen);
405 405 sliceSettingsLayout->addRow("Brush", m_brush);
406 406 sliceSettingsLayout->addRow("Label visible", m_sliceLabelVisible);
407 407 sliceSettingsLayout->addRow("Label font", m_font);
408 408 sliceSettingsLayout->addRow("Label arm pen", m_labelArmPen);
409 409 sliceSettingsLayout->addRow("Label arm length", m_sliceLabelArmFactor);
410 410 sliceSettingsLayout->addRow("Exploded", m_sliceExploded);
411 411 sliceSettingsLayout->addRow("Explode distance", m_sliceExplodedFactor);
412 412 sliceSettingsLayout->addRow(removeSlice);
413 413 QGroupBox* sliceSettings = new QGroupBox("Slice");
414 414 sliceSettings->setLayout(sliceSettingsLayout);
415 415
416 416 connect(m_sliceValue, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
417 417 connect(m_pen, SIGNAL(clicked()), m_penTool, SLOT(show()));
418 418 connect(m_penTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
419 419 connect(m_brush, SIGNAL(clicked()), m_brushTool, SLOT(show()));
420 420 connect(m_brushTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
421 421 connect(m_font, SIGNAL(clicked()), this, SLOT(showFontDialog()));
422 422 connect(m_labelArmPen, SIGNAL(clicked()), m_labelArmPenTool, SLOT(show()));
423 423 connect(m_labelArmPenTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
424 424 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
425 425 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
426 426 connect(m_sliceLabelArmFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
427 427 connect(m_sliceExploded, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
428 428 connect(m_sliceExplodedFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
429 429 connect(removeSlice, SIGNAL(clicked()), this, SLOT(removeSlice()));
430 430
431 431 // create main layout
432 432 QVBoxLayout *settingsLayout = new QVBoxLayout();
433 433 settingsLayout->addWidget(chartSettings);
434 434 settingsLayout->addWidget(seriesSettings);
435 435 settingsLayout->addWidget(sliceSettings);
436 436 settingsLayout->addStretch();
437 437
438 438 QGridLayout* baseLayout = new QGridLayout();
439 439 baseLayout->addLayout(settingsLayout, 0, 0);
440 440 baseLayout->addWidget(m_chartView, 0, 1);
441 441 setLayout(baseLayout);
442 442
443 443 updateSerieSettings();
444 444 }
445 445
446 446 public Q_SLOTS:
447 447
448 448 void updateChartSettings()
449 449 {
450 450 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
451 451 m_chartView->setChartTheme(theme);
452 452 m_chartView->setRenderHint(QPainter::Antialiasing, m_aaCheckBox->isChecked());
453 453
454 454 if (m_animationsCheckBox->checkState() == Qt::Checked)
455 455 m_chartView->setAnimationOptions(QChart::AllAnimations);
456 456 else
457 457 m_chartView->setAnimationOptions(QChart::NoAnimation);
458 458 }
459 459
460 460 void updateSerieSettings()
461 461 {
462 462 m_series->setPiePosition(m_hPosition->value(), m_vPosition->value());
463 463 m_series->setPieSize(m_sizeFactor->value());
464 464 m_series->setPieStartAngle(m_startAngle->value());
465 465 m_series->setPieEndAngle(m_endAngle->value());
466 466 }
467 467
468 468 void updateSliceSettings()
469 469 {
470 470 if (!m_slice)
471 471 return;
472 472
473 473 m_slice->setValue(m_sliceValue->value());
474 474
475 475 m_slice->setSlicePen(m_penTool->pen());
476 476 m_slice->setSliceBrush(m_brushTool->brush());
477 477
478 478 m_slice->setLabelArmPen(m_labelArmPenTool->pen());
479 479 m_slice->setLabelVisible(m_sliceLabelVisible->isChecked());
480 480 m_slice->setLabelArmLengthFactor(m_sliceLabelArmFactor->value());
481 481
482 482 m_slice->setExploded(m_sliceExploded->isChecked());
483 483 m_slice->setExplodeDistanceFactor(m_sliceExplodedFactor->value());
484 484 }
485 485
486 void handleSliceClicked(QPieSlice* slice)
486 void handleSliceClicked(QPieSlice* slice, Qt::MouseButtons buttons)
487 487 {
488 Q_UNUSED(buttons);
489
488 490 m_slice = static_cast<CustomSlice*>(slice);
489 491
490 492 // name
491 493 m_sliceName->setText(slice->label());
492 494
493 495 // value
494 496 m_sliceValue->blockSignals(true);
495 497 m_sliceValue->setValue(slice->value());
496 498 m_sliceValue->blockSignals(false);
497 499
498 500 // pen
499 501 m_pen->setText(PenTool::name(m_slice->slicePen()));
500 502 m_penTool->setPen(m_slice->slicePen());
501 503
502 504 // brush
503 505 m_brush->setText(m_slice->originalBrush().color().name());
504 506 m_brushTool->setBrush(m_slice->originalBrush());
505 507
506 508 // label
507 509 m_labelArmPen->setText(PenTool::name(m_slice->labelArmPen()));
508 510 m_labelArmPenTool->setPen(m_slice->labelArmPen());
509 511 m_font->setText(slice->labelFont().toString());
510 512 m_sliceLabelVisible->blockSignals(true);
511 513 m_sliceLabelVisible->setChecked(slice->isLabelVisible());
512 514 m_sliceLabelVisible->blockSignals(false);
513 515 m_sliceLabelArmFactor->blockSignals(true);
514 516 m_sliceLabelArmFactor->setValue(slice->labelArmLengthFactor());
515 517 m_sliceLabelArmFactor->blockSignals(false);
516 518
517 519 // exploded
518 520 m_sliceExploded->blockSignals(true);
519 521 m_sliceExploded->setChecked(slice->isExploded());
520 522 m_sliceExploded->blockSignals(false);
521 523 m_sliceExplodedFactor->blockSignals(true);
522 524 m_sliceExplodedFactor->setValue(slice->explodeDistanceFactor());
523 525 m_sliceExplodedFactor->blockSignals(false);
524 526 }
525 527
526 528 void showFontDialog()
527 529 {
528 530 if (!m_slice)
529 531 return;
530 532
531 533 QFontDialog dialog(m_slice->labelFont());
532 534 dialog.show();
533 535 dialog.exec();
534 536
535 537 m_slice->setLabelFont(dialog.currentFont());
536 538 m_font->setText(dialog.currentFont().toString());
537 539 }
538 540
539 541 void addSlice()
540 542 {
541 543 *m_series << new CustomSlice(10.0, "Slice " + QString::number(m_series->count()+1));
542 544 }
543 545
544 546 void insertSlice()
545 547 {
546 548 if (!m_slice)
547 549 return;
548 550
549 551 int i = m_series->slices().indexOf(m_slice);
550 552
551 553 m_series->insert(i, new CustomSlice(10.0, "Slice " + QString::number(m_series->count()+1)));
552 554 }
553 555
554 556 void removeSlice()
555 557 {
556 558 if (!m_slice)
557 559 return;
558 560
559 561 m_series->remove(m_slice);
560 562 m_slice = 0;
561 563 }
562 564
563 565 private:
564 566 QComboBox *m_themeComboBox;
565 567 QCheckBox *m_aaCheckBox;
566 568 QCheckBox *m_animationsCheckBox;
567 569
568 570 QChartView* m_chartView;
569 571 QPieSeries* m_series;
570 572 CustomSlice* m_slice;
571 573
572 574 QDoubleSpinBox* m_hPosition;
573 575 QDoubleSpinBox* m_vPosition;
574 576 QDoubleSpinBox* m_sizeFactor;
575 577 QDoubleSpinBox* m_startAngle;
576 578 QDoubleSpinBox* m_endAngle;
577 579
578 580 QLabel* m_sliceName;
579 581 QDoubleSpinBox* m_sliceValue;
580 582 QCheckBox* m_sliceLabelVisible;
581 583 QDoubleSpinBox* m_sliceLabelArmFactor;
582 584 QCheckBox* m_sliceExploded;
583 585 QDoubleSpinBox* m_sliceExplodedFactor;
584 586 QPushButton *m_brush;
585 587 BrushTool *m_brushTool;
586 588 QPushButton *m_pen;
587 589 PenTool *m_penTool;
588 590 QPushButton *m_font;
589 591 QPushButton *m_labelArmPen;
590 592 PenTool *m_labelArmPenTool;
591 593 };
592 594
593 595 int main(int argc, char *argv[])
594 596 {
595 597 QApplication a(argc, argv);
596 598
597 599 QMainWindow window;
598 600
599 601 MainWidget* widget = new MainWidget();
600 602
601 603 window.setCentralWidget(widget);
602 604 window.resize(900, 600);
603 605 window.show();
604 606
605 607 return a.exec();
606 608 }
607 609
608 610 #include "main.moc"
@@ -1,114 +1,114
1 1 #include <QtGui/QApplication>
2 2 #include <QMainWindow>
3 3 #include <qchartglobal.h>
4 4 #include <qchartview.h>
5 5 #include <qpieseries.h>
6 6 #include <qpieslice.h>
7 7 #include <QTime>
8 8
9 9 QTCOMMERCIALCHART_USE_NAMESPACE
10 10
11 11 class DrilldownSlice : public QPieSlice
12 12 {
13 13 Q_OBJECT
14 14
15 15 public:
16 16 DrilldownSlice(qreal value, QString prefix, QSeries* drilldownSeries)
17 17 :m_drilldownSeries(drilldownSeries),
18 18 m_prefix(prefix)
19 19 {
20 20 setValue(value);
21 21 setLabelVisible(true);
22 22 updateLabel();
23 23 connect(this, SIGNAL(changed()), this, SLOT(updateLabel()));
24 24 }
25 25
26 26 QSeries* drilldownSeries() const { return m_drilldownSeries; }
27 27
28 28 public Q_SLOTS:
29 29 void updateLabel()
30 30 {
31 31 QString label = m_prefix;
32 32 label += " " + QString::number(this->value())+ "e (";
33 33 label += QString::number(this->percentage()*100, 'f', 1) + "%)";
34 34 setLabel(label);
35 35 }
36 36
37 37 private:
38 38 QSeries* m_drilldownSeries;
39 39 QString m_prefix;
40 40 };
41 41
42 42 class DrilldownChart : public QChartView
43 43 {
44 44 Q_OBJECT
45 45 public:
46 46 explicit DrilldownChart(QWidget *parent = 0):QChartView(parent), m_currentSeries(0) {}
47 47
48 48 void changeSeries(QSeries* series)
49 49 {
50 50 // NOTE: if the series is owned by the chart it will be deleted
51 51 // here the "window" owns the series...
52 52 if (m_currentSeries)
53 53 removeSeries(m_currentSeries);
54 54 m_currentSeries = series;
55 55 addSeries(series);
56 56 setChartTitle(series->title());
57 57 }
58 58
59 59 public Q_SLOTS:
60 60 void handleSliceClicked(QPieSlice* slice)
61 61 {
62 62 DrilldownSlice* drilldownSlice = static_cast<DrilldownSlice*>(slice);
63 63 changeSeries(drilldownSlice->drilldownSeries());
64 64 }
65 65
66 66 private:
67 67 QSeries* m_currentSeries;
68 68 };
69 69
70 70 int main(int argc, char *argv[])
71 71 {
72 72 QApplication a(argc, argv);
73 73
74 74 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
75 75
76 76 QMainWindow window;
77 77
78 78 DrilldownChart* drilldownChart = new DrilldownChart(&window);
79 79 drilldownChart->setRenderHint(QPainter::Antialiasing);
80 80 drilldownChart->setChartTheme(QChart::ChartThemeLight);
81 81 drilldownChart->setAnimationOptions(QChart::AllAnimations);
82 82
83 83 QPieSeries* yearSeries = new QPieSeries(&window);
84 84 yearSeries->setTitle("Sales by year - All");
85 85
86 86 QList<QString> months;
87 87 months << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun" << "Jul" << "Aug" << "Sep" << "Oct" << "Nov" << "Dec";
88 88 QList<QString> names;
89 89 names << "Jane" << "John" << "Axel" << "Mary" << "Samantha" << "Bob";
90 90
91 91 foreach (QString name, names) {
92 92 QPieSeries* series = new QPieSeries(&window);
93 93 series->setTitle("Sales by month - " + name);
94 94
95 95 foreach (QString month, months)
96 96 *series << new DrilldownSlice(qrand() % 1000, month, yearSeries);
97 97
98 QObject::connect(series, SIGNAL(clicked(QPieSlice*)), drilldownChart, SLOT(handleSliceClicked(QPieSlice*)));
98 QObject::connect(series, SIGNAL(clicked(QPieSlice*, Qt::MouseButtons)), drilldownChart, SLOT(handleSliceClicked(QPieSlice*)));
99 99
100 100 *yearSeries << new DrilldownSlice(series->total(), name, series);
101 101 }
102 102
103 QObject::connect(yearSeries, SIGNAL(clicked(QPieSlice*)), drilldownChart, SLOT(handleSliceClicked(QPieSlice*)));
103 QObject::connect(yearSeries, SIGNAL(clicked(QPieSlice*, Qt::MouseButtons)), drilldownChart, SLOT(handleSliceClicked(QPieSlice*)));
104 104
105 105 drilldownChart->changeSeries(yearSeries);
106 106
107 107 window.setCentralWidget(drilldownChart);
108 108 window.resize(800, 600);
109 109 window.show();
110 110
111 111 return a.exec();
112 112 }
113 113
114 114 #include "main.moc"
@@ -1,191 +1,191
1 1 #include "piechartitem_p.h"
2 2 #include "piesliceitem_p.h"
3 3 #include "qpieslice.h"
4 4 #include "qpiesliceprivate_p.h"
5 5 #include "qpieseries.h"
6 6 #include "chartpresenter_p.h"
7 7 #include "chartdataset_p.h"
8 8 #include "chartanimator_p.h"
9 9 #include <QDebug>
10 10 #include <QPainter>
11 11 #include <QTimer>
12 12
13 13 QTCOMMERCIALCHART_BEGIN_NAMESPACE
14 14
15 15 PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter* presenter)
16 16 :ChartItem(presenter),
17 17 m_series(series)
18 18 {
19 19 Q_ASSERT(series);
20 20 connect(series, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>)));
21 21 connect(series, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>)));
22 22 connect(series, SIGNAL(piePositionChanged()), this, SLOT(handlePieLayoutChanged()));
23 23 connect(series, SIGNAL(pieSizeChanged()), this, SLOT(handlePieLayoutChanged()));
24 24
25 25 QTimer::singleShot(0, this, SLOT(initialize()));
26 26
27 27 // Note: the following does not affect as long as the item does not have anything to paint
28 28 setZValue(ChartPresenter::PieSeriesZValue);
29 29 }
30 30
31 31 PieChartItem::~PieChartItem()
32 32 {
33 33 // slices deleted automatically through QGraphicsItem
34 34 }
35 35
36 36 void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
37 37 {
38 38 Q_UNUSED(painter)
39 39 // TODO: paint shadows for all components
40 40 // - get paths from items & merge & offset and draw with shadow color?
41 41 //painter->setBrush(QBrush(Qt::red));
42 42 //painter->drawRect(m_debugRect);
43 43 }
44 44
45 45 void PieChartItem::initialize()
46 46 {
47 47 handleSlicesAdded(m_series->slices());
48 48 }
49 49
50 50 void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices)
51 51 {
52 52 bool isEmpty = m_slices.isEmpty();
53 53
54 54 presenter()->theme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series), false);
55 55
56 56 foreach (QPieSlice *s, slices) {
57 57 PieSliceItem* item = new PieSliceItem(this);
58 58 m_slices.insert(s, item);
59 59 connect(s, SIGNAL(changed()), this, SLOT(handleSliceChanged()));
60 connect(item, SIGNAL(clicked()), s, SIGNAL(clicked()));
60 connect(item, SIGNAL(clicked(Qt::MouseButtons)), s, SIGNAL(clicked(Qt::MouseButtons)));
61 61 connect(item, SIGNAL(hoverEnter()), s, SIGNAL(hoverEnter()));
62 62 connect(item, SIGNAL(hoverLeave()), s, SIGNAL(hoverLeave()));
63 63
64 64 PieSliceData data = sliceData(s);
65 65
66 66 if (animator())
67 67 animator()->addAnimation(this, s, data, isEmpty);
68 68 else
69 69 setLayout(s, data);
70 70 }
71 71 }
72 72
73 73 void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices)
74 74 {
75 75 presenter()->theme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series), false);
76 76
77 77 foreach (QPieSlice *s, slices) {
78 78 if (animator())
79 79 animator()->removeAnimation(this, s);
80 80 else
81 81 destroySlice(s);
82 82 }
83 83 }
84 84
85 85 void PieChartItem::handlePieLayoutChanged()
86 86 {
87 87 PieLayout layout = calculateLayout();
88 88 applyLayout(layout);
89 89 update();
90 90 }
91 91
92 92 void PieChartItem::handleSliceChanged()
93 93 {
94 94 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
95 95 Q_ASSERT(m_slices.contains(slice));
96 96 PieSliceData data = sliceData(slice);
97 97 updateLayout(slice, data);
98 98 update();
99 99 }
100 100
101 101 void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal)
102 102 {
103 103 // TODO
104 104 }
105 105
106 106 void PieChartItem::handleGeometryChanged(const QRectF& rect)
107 107 {
108 108 prepareGeometryChange();
109 109 m_rect = rect;
110 110 handlePieLayoutChanged();
111 111 }
112 112
113 113 void PieChartItem::calculatePieLayout()
114 114 {
115 115 // find pie center coordinates
116 116 m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->pieHorizontalPosition()));
117 117 m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->pieVerticalPosition()));
118 118
119 119 // find maximum radius for pie
120 120 m_pieRadius = m_rect.height() / 2;
121 121 if (m_rect.width() < m_rect.height())
122 122 m_pieRadius = m_rect.width() / 2;
123 123
124 124 // apply size factor
125 125 m_pieRadius *= m_series->pieSize();
126 126 }
127 127
128 128 PieSliceData PieChartItem::sliceData(QPieSlice *slice)
129 129 {
130 130 PieSliceData sliceData = slice->data_ptr()->m_data;
131 131 sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice);
132 132 sliceData.m_radius = m_pieRadius;
133 133 return sliceData;
134 134 }
135 135
136 136 PieLayout PieChartItem::calculateLayout()
137 137 {
138 138 calculatePieLayout();
139 139 PieLayout layout;
140 140 foreach (QPieSlice* s, m_series->slices()) {
141 141 if (m_slices.contains(s)) // calculate layout only for those slices that are already visible
142 142 layout.insert(s, sliceData(s));
143 143 }
144 144 return layout;
145 145 }
146 146
147 147 void PieChartItem::applyLayout(const PieLayout &layout)
148 148 {
149 149 if (animator())
150 150 animator()->updateLayout(this, layout);
151 151 else
152 152 setLayout(layout);
153 153 }
154 154
155 155 void PieChartItem::updateLayout(QPieSlice *slice, const PieSliceData &sliceData)
156 156 {
157 157 if (animator())
158 158 animator()->updateLayout(this, slice, sliceData);
159 159 else
160 160 setLayout(slice, sliceData);
161 161 }
162 162
163 163 void PieChartItem::setLayout(const PieLayout &layout)
164 164 {
165 165 foreach (QPieSlice *slice, layout.keys()) {
166 166 PieSliceItem *item = m_slices.value(slice);
167 167 Q_ASSERT(item);
168 168 item->setSliceData(layout.value(slice));
169 169 item->updateGeometry();
170 170 item->update();
171 171 }
172 172 }
173 173
174 174 void PieChartItem::setLayout(QPieSlice *slice, const PieSliceData &sliceData)
175 175 {
176 176 // find slice
177 177 PieSliceItem *item = m_slices.value(slice);
178 178 Q_ASSERT(item);
179 179 item->setSliceData(sliceData);
180 180 item->updateGeometry();
181 181 item->update();
182 182 }
183 183
184 184 void PieChartItem::destroySlice(QPieSlice *slice)
185 185 {
186 186 delete m_slices.take(slice);
187 187 }
188 188
189 189 #include "moc_piechartitem_p.cpp"
190 190
191 191 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,184 +1,184
1 1 #include "piesliceitem_p.h"
2 2 #include "piechartitem_p.h"
3 3 #include "qpieseries.h"
4 4 #include "qpieslice.h"
5 5 #include "chartpresenter_p.h"
6 6 #include <QPainter>
7 7 #include <QDebug>
8 8 #include <qmath.h>
9 9 #include <QGraphicsSceneEvent>
10 10 #include <QTime>
11 11
12 12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
13 13
14 14 #define PI 3.14159265 // TODO: is this defined in some header?
15 15
16 16 QPointF offset(qreal angle, qreal length)
17 17 {
18 18 qreal dx = qSin(angle*(PI/180)) * length;
19 19 qreal dy = qCos(angle*(PI/180)) * length;
20 20 return QPointF(dx, -dy);
21 21 }
22 22
23 23 PieSliceItem::PieSliceItem(QGraphicsItem* parent)
24 24 :QGraphicsObject(parent)
25 25 {
26 26 setAcceptHoverEvents(true);
27 setAcceptedMouseButtons(Qt::LeftButton);
27 setAcceptedMouseButtons(Qt::MouseButtonMask);
28 28 setZValue(ChartPresenter::PieSeriesZValue);
29 29 }
30 30
31 31 PieSliceItem::~PieSliceItem()
32 32 {
33 33
34 34 }
35 35
36 36 QRectF PieSliceItem::boundingRect() const
37 37 {
38 38 return m_boundingRect;
39 39 }
40 40
41 41 QPainterPath PieSliceItem::shape() const
42 42 {
43 43 // Don't include the label and label arm.
44 44 // This is used to detect a mouse clicks. We do not want clicks from label.
45 45 return m_slicePath;
46 46 }
47 47
48 48 void PieSliceItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
49 49 {
50 50 painter->setClipRect(parentItem()->boundingRect());
51 51
52 52 painter->save();
53 53 painter->setPen(m_data.m_slicePen);
54 54 painter->setBrush(m_data.m_sliceBrush);
55 55 painter->drawPath(m_slicePath);
56 56 painter->restore();
57 57
58 58 if (m_data.m_isLabelVisible) {
59 59 painter->save();
60 60 painter->setPen(m_data.m_labelArmPen);
61 61 painter->drawPath(m_labelArmPath);
62 62 painter->restore();
63 63
64 64 painter->setFont(m_data.m_labelFont);
65 65 painter->drawText(m_labelTextRect.bottomLeft(), m_data.m_labelText);
66 66 }
67 67 }
68 68
69 69 void PieSliceItem::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
70 70 {
71 71 emit hoverEnter();
72 72 }
73 73
74 74 void PieSliceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
75 75 {
76 76 emit hoverLeave();
77 77 }
78 78
79 void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/)
79 void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
80 80 {
81 emit clicked();
81 emit clicked(event->buttons());
82 82 }
83 83
84 84 void PieSliceItem::setSliceData(PieSliceData sliceData)
85 85 {
86 86 m_data = sliceData;
87 87 }
88 88
89 89 void PieSliceItem::updateGeometry()
90 90 {
91 91 if (m_data.m_radius <= 0)
92 92 return;
93 93
94 94 prepareGeometryChange();
95 95
96 96 // update slice path
97 97 qreal centerAngle;
98 98 QPointF armStart;
99 99 m_slicePath = slicePath(m_data.m_center, m_data.m_radius, m_data.m_startAngle, m_data.m_angleSpan, &centerAngle, &armStart);
100 100
101 101 // update text rect
102 102 m_labelTextRect = labelTextRect(m_data.m_labelFont, m_data.m_labelText);
103 103
104 104 // update label arm path
105 105 QPointF labelTextStart;
106 106 m_labelArmPath = labelArmPath(armStart, centerAngle, m_data.m_radius * m_data.m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
107 107
108 108 // update text position
109 109 m_labelTextRect.moveBottomLeft(labelTextStart);
110 110
111 111 // update bounding rect
112 112 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
113 113 }
114 114
115 115 QPointF PieSliceItem::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
116 116 {
117 117 if (slice->isExploded()) {
118 118 qreal centerAngle = slice->startAngle() + ((slice->endAngle() - slice->startAngle())/2);
119 119 qreal len = radius * slice->explodeDistanceFactor();
120 120 qreal dx = qSin(centerAngle*(PI/180)) * len;
121 121 qreal dy = -qCos(centerAngle*(PI/180)) * len;
122 122 point += QPointF(dx, dy);
123 123 }
124 124 return point;
125 125 }
126 126
127 127 QPainterPath PieSliceItem::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal* centerAngle, QPointF* armStart)
128 128 {
129 129 // calculate center angle
130 130 *centerAngle = startAngle + (angleSpan/2);
131 131
132 132 // calculate slice rectangle
133 133 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
134 134
135 135 // slice path
136 136 // TODO: draw the shape so that it might have a hole in the center
137 137 QPainterPath path;
138 138 path.moveTo(rect.center());
139 139 path.arcTo(rect, -startAngle + 90, -angleSpan);
140 140 path.closeSubpath();
141 141
142 142 // calculate label arm start point
143 143 *armStart = center;
144 144 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
145 145
146 146 return path;
147 147 }
148 148
149 149 QPainterPath PieSliceItem::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart)
150 150 {
151 151 qreal dx = qSin(angle*(PI/180)) * length;
152 152 qreal dy = -qCos(angle*(PI/180)) * length;
153 153 QPointF parm1 = start + QPointF(dx, dy);
154 154
155 155 QPointF parm2 = parm1;
156 156 if (angle < 180) { // arm swings the other way on the left side
157 157 parm2 += QPointF(textWidth, 0);
158 158 *textStart = parm1;
159 159 }
160 160 else {
161 161 parm2 += QPointF(-textWidth,0);
162 162 *textStart = parm2;
163 163 }
164 164
165 165 // elevate the text position a bit so that it does not hit the line
166 166 *textStart += QPointF(0, -5);
167 167
168 168 QPainterPath path;
169 169 path.moveTo(start);
170 170 path.lineTo(parm1);
171 171 path.lineTo(parm2);
172 172
173 173 return path;
174 174 }
175 175
176 176 QRectF PieSliceItem::labelTextRect(QFont font, QString text)
177 177 {
178 178 QFontMetricsF fm(font);
179 179 return fm.boundingRect(text);
180 180 }
181 181
182 182 #include "moc_piesliceitem_p.cpp"
183 183
184 184 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,59 +1,59
1 1 #ifndef PIESLICEITEM_H
2 2 #define PIESLICEITEM_H
3 3
4 4 #include "qchartglobal.h"
5 5 #include "charttheme_p.h"
6 6 #include "qpieseries.h"
7 7 #include "qpiesliceprivate_p.h"
8 8 #include <QGraphicsItem>
9 9 #include <QRectF>
10 10 #include <QColor>
11 11 #include <QPen>
12 12
13 13 #define PIESLICE_LABEL_GAP 5
14 14
15 15 QTCOMMERCIALCHART_BEGIN_NAMESPACE
16 16 class PieChartItem;
17 17 class PieSliceLabel;
18 18 class QPieSlice;
19 19
20 20 class PieSliceItem : public QGraphicsObject
21 21 {
22 22 Q_OBJECT
23 23
24 24 public:
25 25 PieSliceItem(QGraphicsItem* parent = 0);
26 26 ~PieSliceItem();
27 27
28 28 public: // from QGraphicsItem
29 29 QRectF boundingRect() const;
30 30 QPainterPath shape() const;
31 31 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
32 32 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
33 33 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
34 34 void mousePressEvent(QGraphicsSceneMouseEvent *event);
35 35
36 36 Q_SIGNALS:
37 void clicked();
37 void clicked(Qt::MouseButtons buttons);
38 38 void hoverEnter();
39 39 void hoverLeave();
40 40
41 41 public:
42 42 void setSliceData(PieSliceData sliceData);
43 43 void updateGeometry();
44 44 static QPointF sliceCenter(QPointF point, qreal radius, QPieSlice *slice);
45 45 static QPainterPath slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal* centerAngle, QPointF* armStart);
46 46 static QPainterPath labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart);
47 47 static QRectF labelTextRect(QFont font, QString text);
48 48
49 49 private:
50 50 PieSliceData m_data;
51 51 QRectF m_boundingRect;
52 52 QPainterPath m_slicePath;
53 53 QPainterPath m_labelArmPath;
54 54 QRectF m_labelTextRect;
55 55 };
56 56
57 57 QTCOMMERCIALCHART_END_NAMESPACE
58 58
59 59 #endif // PIESLICEITEM_H
@@ -1,640 +1,640
1 1 #include "qpieseries.h"
2 2 #include "qpiesliceprivate_p.h"
3 3 #include "qpieseriesprivate_p.h"
4 4 #include <QDebug>
5 5
6 6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 7
8 8 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent)
9 9 :QObject(parent),
10 10 q_ptr(parent),
11 11 m_pieRelativeHorPos(0.5),
12 12 m_pieRelativeVerPos(0.5),
13 13 m_pieRelativeSize(0.7),
14 14 m_pieStartAngle(0),
15 15 m_pieEndAngle(360),
16 16 m_total(0)
17 17 {
18 18
19 19 }
20 20
21 21 QPieSeriesPrivate::~QPieSeriesPrivate()
22 22 {
23 23
24 24 }
25 25
26 26 void QPieSeriesPrivate::updateDerivativeData()
27 27 {
28 28 m_total = 0;
29 29
30 30 // nothing to do?
31 31 if (m_slices.count() == 0)
32 32 return;
33 33
34 34 // calculate total
35 35 foreach (QPieSlice* s, m_slices)
36 36 m_total += s->value();
37 37
38 38 // nothing to show..
39 39 if (m_total == 0)
40 40 return;
41 41
42 42 // update slice attributes
43 43 qreal sliceAngle = m_pieStartAngle;
44 44 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
45 45 QVector<QPieSlice*> changed;
46 46 foreach (QPieSlice* s, m_slices) {
47 47
48 48 bool isChanged = false;
49 49
50 50 qreal percentage = s->value() / m_total;
51 51 if (s->data_ptr()->m_data.m_percentage != percentage) {
52 52 s->data_ptr()->m_data.m_percentage = percentage;
53 53 isChanged = true;
54 54 }
55 55
56 56 qreal sliceSpan = pieSpan * percentage;
57 57 if (s->data_ptr()->m_data.m_angleSpan != sliceSpan) {
58 58 s->data_ptr()->m_data.m_angleSpan = sliceSpan;
59 59 isChanged = true;
60 60 }
61 61
62 62 if (s->data_ptr()->m_data.m_startAngle != sliceAngle) {
63 63 s->data_ptr()->m_data.m_startAngle = sliceAngle;
64 64 isChanged = true;
65 65 }
66 66 sliceAngle += sliceSpan;
67 67
68 68 if (isChanged)
69 69 changed << s;
70 70 }
71 71
72 72 // emit signals
73 73 foreach (QPieSlice* s, changed)
74 74 emit s->data_ptr()->changed();
75 75 }
76 76
77 77 void QPieSeriesPrivate::sliceChanged()
78 78 {
79 79 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
80 80 updateDerivativeData();
81 81 }
82 82
83 void QPieSeriesPrivate::sliceClicked()
83 void QPieSeriesPrivate::sliceClicked(Qt::MouseButtons buttons)
84 84 {
85 85 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
86 86 Q_ASSERT(m_slices.contains(slice));
87 87 Q_Q(QPieSeries);
88 emit q->clicked(slice);
88 emit q->clicked(slice, buttons);
89 89 }
90 90
91 91 void QPieSeriesPrivate::sliceHoverEnter()
92 92 {
93 93 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
94 94 Q_ASSERT(m_slices.contains(slice));
95 95 Q_Q(QPieSeries);
96 96 emit q->hoverEnter(slice);
97 97 }
98 98
99 99 void QPieSeriesPrivate::sliceHoverLeave()
100 100 {
101 101 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
102 102 Q_ASSERT(m_slices.contains(slice));
103 103 Q_Q(QPieSeries);
104 104 emit q->hoverLeave(slice);
105 105 }
106 106
107 107 void QPieSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
108 108 {
109 109 Q_UNUSED(bottomRight)
110 110 Q_Q(QPieSeries);
111 111
112 112 if (m_mapOrientation == Qt::Vertical)
113 113 {
114 114 // slices().at(topLeft.row())->setValue(m_model->data(m_model->index(topLeft.row(), topLeft.column()), Qt::DisplayRole).toDouble());
115 115 if (topLeft.column() == m_mapValues)
116 116 if (m_mapValues == m_mapLabels)
117 117 {
118 118 m_slices.at(topLeft.row())->setValue(q->m_model->data(topLeft, Qt::DisplayRole).toDouble());
119 119 m_slices.at(topLeft.row())->setLabel(q->m_model->data(topLeft, Qt::DisplayRole).toString());
120 120 }
121 121 else
122 122 {
123 123 m_slices.at(topLeft.row())->setValue(q->m_model->data(topLeft, Qt::DisplayRole).toDouble());
124 124 }
125 125 else if (topLeft.column() == m_mapLabels)
126 126 m_slices.at(topLeft.row())->setLabel(q->m_model->data(topLeft, Qt::DisplayRole).toString());
127 127 }
128 128 else
129 129 {
130 130 // slices().at(topLeft.column())->setValue(m_model->data(m_model->index(topLeft.row(), topLeft.column()), Qt::DisplayRole).toDouble());
131 131 if (topLeft.row() == m_mapValues)
132 132 if (m_mapValues == m_mapLabels)
133 133 {
134 134 m_slices.at(topLeft.column())->setValue(q->m_model->data(topLeft, Qt::DisplayRole).toDouble());
135 135 m_slices.at(topLeft.column())->setLabel(q->m_model->data(topLeft, Qt::DisplayRole).toString());
136 136 }
137 137 else
138 138 {
139 139 m_slices.at(topLeft.column())->setValue(q->m_model->data(topLeft, Qt::DisplayRole).toDouble());
140 140 }
141 141 else if (topLeft.row() == m_mapLabels)
142 142 m_slices.at(topLeft.column())->setLabel(q->m_model->data(topLeft, Qt::DisplayRole).toString());
143 143 }
144 144 }
145 145
146 146 void QPieSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end)
147 147 {
148 148 Q_UNUSED(parent)
149 149 Q_UNUSED(end)
150 150 Q_Q(QPieSeries);
151 151
152 152 QPieSlice* newSlice = new QPieSlice;
153 153 newSlice->setLabelVisible(true);
154 154 if (m_mapOrientation == Qt::Vertical)
155 155 {
156 156 newSlice->setValue(q->m_model->data(q->m_model->index(start, m_mapValues), Qt::DisplayRole).toDouble());
157 157 newSlice->setLabel(q->m_model->data(q->m_model->index(start, m_mapLabels), Qt::DisplayRole).toString());
158 158 }
159 159 else
160 160 {
161 161 newSlice->setValue(q->m_model->data(q->m_model->index(m_mapValues, start), Qt::DisplayRole).toDouble());
162 162 newSlice->setLabel(q->m_model->data(q->m_model->index(m_mapLabels, start), Qt::DisplayRole).toString());
163 163 }
164 164
165 165 q->insert(start, newSlice);
166 166 }
167 167
168 168 void QPieSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
169 169 {
170 170 Q_UNUSED(parent)
171 171 Q_UNUSED(end)
172 172 Q_Q(QPieSeries);
173 173 q->remove(m_slices.at(start));
174 174 }
175 175
176 176
177 177
178 178 /*!
179 179 \class QPieSeries
180 180 \brief Pie series API for QtCommercial Charts
181 181
182 182 The pie series defines a pie chart which consists of pie slices which are QPieSlice objects.
183 183 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
184 184 The actual slice size is determined by that relative value.
185 185
186 186 By default the pie is defined as a full pie but it can be a partial pie.
187 187 This can be done by setting a starting angle and angle span to the series.
188 188 */
189 189
190 190 /*!
191 191 Constructs a series object which is a child of \a parent.
192 192 */
193 193 QPieSeries::QPieSeries(QObject *parent) :
194 194 QSeries(parent),
195 195 d_ptr(new QPieSeriesPrivate(this))
196 196 {
197 197
198 198 }
199 199
200 200 /*!
201 201 Destroys the object. Note that adding series to QChart transfers the ownership to the chart.
202 202 */
203 203 QPieSeries::~QPieSeries()
204 204 {
205 205 // NOTE: d_prt destroyed by QObject
206 206 }
207 207
208 208 /*!
209 209 Returns QChartSeries::SeriesTypePie.
210 210 */
211 211 QSeries::QSeriesType QPieSeries::type() const
212 212 {
213 213 return QSeries::SeriesTypePie;
214 214 }
215 215
216 216 /*!
217 217 Sets an array of \a slices to the series replacing the existing slices.
218 218 Slice ownership is passed to the series.
219 219 */
220 220 void QPieSeries::replace(QList<QPieSlice*> slices)
221 221 {
222 222 clear();
223 223 add(slices);
224 224 }
225 225
226 226 /*!
227 227 Adds an array of \a slices to the series.
228 228 Slice ownership is passed to the series.
229 229 */
230 230 void QPieSeries::add(QList<QPieSlice*> slices)
231 231 {
232 232 Q_D(QPieSeries);
233 233
234 234 foreach (QPieSlice* s, slices) {
235 235 s->setParent(this);
236 236 d->m_slices << s;
237 237 }
238 238
239 239 d->updateDerivativeData();
240 240
241 241 foreach (QPieSlice* s, slices) {
242 242 connect(s, SIGNAL(changed()), d, SLOT(sliceChanged()));
243 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
243 connect(s, SIGNAL(clicked(Qt::MouseButtons)), d, SLOT(sliceClicked(Qt::MouseButtons)));
244 244 connect(s, SIGNAL(hoverEnter()), d, SLOT(sliceHoverEnter()));
245 245 connect(s, SIGNAL(hoverLeave()), d, SLOT(sliceHoverLeave()));
246 246 }
247 247
248 248 emit added(slices);
249 249 }
250 250
251 251 /*!
252 252 Adds a single \a slice to the series.
253 253 Slice ownership is passed to the series.
254 254 */
255 255 void QPieSeries::add(QPieSlice* slice)
256 256 {
257 257 add(QList<QPieSlice*>() << slice);
258 258 }
259 259
260 260 /*!
261 261 Adds a single \a slice to the series and returns a reference to the series.
262 262 Slice ownership is passed to the series.
263 263 */
264 264 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
265 265 {
266 266 add(slice);
267 267 return *this;
268 268 }
269 269
270 270
271 271 /*!
272 272 Adds a single slice to the series with give \a value and \a name.
273 273 Slice ownership is passed to the series.
274 274 */
275 275 QPieSlice* QPieSeries::add(qreal value, QString name)
276 276 {
277 277 QPieSlice* slice = new QPieSlice(value, name);
278 278 add(slice);
279 279 return slice;
280 280 }
281 281
282 282 void QPieSeries::insert(int i, QPieSlice* slice)
283 283 {
284 284 Q_D(QPieSeries);
285 285 Q_ASSERT(i <= d->m_slices.count());
286 286 slice->setParent(this);
287 287 d->m_slices.insert(i, slice);
288 288
289 289 d->updateDerivativeData();
290 290
291 291 connect(slice, SIGNAL(changed()), d, SLOT(sliceChanged()));
292 292 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
293 293 connect(slice, SIGNAL(hoverEnter()), d, SLOT(sliceHoverEnter()));
294 294 connect(slice, SIGNAL(hoverLeave()), d, SLOT(sliceHoverLeave()));
295 295
296 296 emit added(QList<QPieSlice*>() << slice);
297 297 }
298 298
299 299 /*!
300 300 Removes a single \a slice from the series and deletes the slice.
301 301
302 302 Do not reference this pointer after this call.
303 303 */
304 304 void QPieSeries::remove(QPieSlice* slice)
305 305 {
306 306 Q_D(QPieSeries);
307 307 if (!d->m_slices.removeOne(slice)) {
308 308 Q_ASSERT(0); // TODO: how should this be reported?
309 309 return;
310 310 }
311 311
312 312 d->updateDerivativeData();
313 313
314 314 emit removed(QList<QPieSlice*>() << slice);
315 315
316 316 delete slice;
317 317 slice = NULL;
318 318 }
319 319
320 320 /*!
321 321 Clears all slices from the series.
322 322 */
323 323 void QPieSeries::clear()
324 324 {
325 325 Q_D(QPieSeries);
326 326 if (d->m_slices.count() == 0)
327 327 return;
328 328
329 329 QList<QPieSlice*> slices = d->m_slices;
330 330 foreach (QPieSlice* s, d->m_slices) {
331 331 d->m_slices.removeOne(s);
332 332 delete s;
333 333 }
334 334
335 335 d->updateDerivativeData();
336 336
337 337 emit removed(slices);
338 338 }
339 339
340 340 /*!
341 341 Counts the number of the slices in this series.
342 342 */
343 343 int QPieSeries::count() const
344 344 {
345 345 Q_D(const QPieSeries);
346 346 return d->m_slices.count();
347 347 }
348 348
349 349 /*!
350 350 Returns true is the series is empty.
351 351 */
352 352 bool QPieSeries::isEmpty() const
353 353 {
354 354 Q_D(const QPieSeries);
355 355 return d->m_slices.isEmpty();
356 356 }
357 357
358 358 /*!
359 359 Returns a list of slices that belong to this series.
360 360 */
361 361 QList<QPieSlice*> QPieSeries::slices() const
362 362 {
363 363 Q_D(const QPieSeries);
364 364 return d->m_slices;
365 365 }
366 366
367 367 /*!
368 368 Sets the center position of the pie by \a relativeHorizontalPosition and \a relativeVerticalPosition.
369 369
370 370 The factors are relative to the chart rectangle where:
371 371
372 372 \a relativeHorizontalPosition 0.0 means the absolute left.
373 373 \a relativeHorizontalPosition 1.0 means the absolute right.
374 374 \a relativeVerticalPosition 0.0 means the absolute top.
375 375 \a relativeVerticalPosition 1.0 means the absolute bottom.
376 376
377 377 By default both values are 0.5 which puts the pie in the middle of the chart rectangle.
378 378
379 379 \sa pieHorizontalPosition(), pieVerticalPosition(), setPieSize()
380 380 */
381 381 void QPieSeries::setPiePosition(qreal relativeHorizontalPosition, qreal relativeVerticalPosition)
382 382 {
383 383 Q_D(QPieSeries);
384 384 if (relativeHorizontalPosition < 0.0 || relativeHorizontalPosition > 1.0 ||
385 385 relativeVerticalPosition < 0.0 || relativeVerticalPosition > 1.0)
386 386 return;
387 387
388 388 if (d->m_pieRelativeHorPos != relativeHorizontalPosition || d->m_pieRelativeVerPos != relativeVerticalPosition) {
389 389 d->m_pieRelativeHorPos = relativeHorizontalPosition;
390 390 d->m_pieRelativeVerPos = relativeVerticalPosition;
391 391 emit piePositionChanged();
392 392 }
393 393 }
394 394
395 395 /*!
396 396 Gets the horizontal position of the pie.
397 397
398 398 The returned value is relative to the chart rectangle where:
399 399
400 400 0.0 means the absolute left.
401 401 1.0 means the absolute right.
402 402
403 403 By default it is 0.5 which puts the pie in the horizontal middle of the chart rectangle.
404 404
405 405 \sa setPiePosition(), pieVerticalPosition(), setPieSize()
406 406 */
407 407 qreal QPieSeries::pieHorizontalPosition() const
408 408 {
409 409 Q_D(const QPieSeries);
410 410 return d->m_pieRelativeHorPos;
411 411 }
412 412
413 413 /*!
414 414 Gets the vertical position position of the pie.
415 415
416 416 The returned value is relative to the chart rectangle where:
417 417
418 418 0.0 means the absolute top.
419 419 1.0 means the absolute bottom.
420 420
421 421 By default it is 0.5 which puts the pie in the vertical middle of the chart rectangle.
422 422
423 423 \sa setPiePosition(), pieHorizontalPosition(), setPieSize()
424 424 */
425 425 qreal QPieSeries::pieVerticalPosition() const
426 426 {
427 427 Q_D(const QPieSeries);
428 428 return d->m_pieRelativeVerPos;
429 429 }
430 430
431 431 /*!
432 432 Sets the relative size of the pie.
433 433
434 434 The \a relativeSize is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
435 435
436 436 Default value is 0.7.
437 437
438 438 \sa pieSize(), setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
439 439 */
440 440 void QPieSeries::setPieSize(qreal relativeSize)
441 441 {
442 442 Q_D(QPieSeries);
443 443 if (relativeSize < 0.0 || relativeSize > 1.0)
444 444 return;
445 445
446 446 if (d->m_pieRelativeSize != relativeSize) {
447 447 d->m_pieRelativeSize = relativeSize;
448 448 emit pieSizeChanged();
449 449 }
450 450 }
451 451
452 452 /*!
453 453 Gets the relative size of the pie.
454 454
455 455 The size is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
456 456
457 457 Default value is 0.7.
458 458
459 459 \sa setPieSize(), setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
460 460 */
461 461 qreal QPieSeries::pieSize() const
462 462 {
463 463 Q_D(const QPieSeries);
464 464 return d->m_pieRelativeSize;
465 465 }
466 466
467 467
468 468 /*!
469 469 Sets the end angle of the pie.
470 470
471 471 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
472 472
473 473 \a angle must be less than pie end angle. Default value is 0.
474 474
475 475 \sa pieStartAngle(), pieEndAngle(), setPieEndAngle()
476 476 */
477 477 void QPieSeries::setPieStartAngle(qreal angle)
478 478 {
479 479 Q_D(QPieSeries);
480 480 if (angle >= 0 && angle <= 360 && angle != d->m_pieStartAngle && angle <= d->m_pieEndAngle) {
481 481 d->m_pieStartAngle = angle;
482 482 d->updateDerivativeData();
483 483 }
484 484 }
485 485
486 486 /*!
487 487 Gets the start angle of the pie.
488 488
489 489 Full pie is 360 degrees where 0 degrees is at 12 a'clock. Default value is 360.
490 490
491 491 \sa setPieStartAngle(), pieEndAngle(), setPieEndAngle()
492 492 */
493 493 qreal QPieSeries::pieStartAngle() const
494 494 {
495 495 Q_D(const QPieSeries);
496 496 return d->m_pieStartAngle;
497 497 }
498 498
499 499 /*!
500 500 Sets the end angle of the pie.
501 501
502 502 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
503 503
504 504 \a angle must be greater than start angle.
505 505
506 506 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
507 507 */
508 508 void QPieSeries::setPieEndAngle(qreal angle)
509 509 {
510 510 Q_D(QPieSeries);
511 511 if (angle >= 0 && angle <= 360 && angle != d->m_pieEndAngle && angle >= d->m_pieStartAngle) {
512 512 d->m_pieEndAngle = angle;
513 513 d->updateDerivativeData();
514 514 }
515 515 }
516 516
517 517 /*!
518 518 Returns the end angle of the pie.
519 519
520 520 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
521 521
522 522 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
523 523 */
524 524 qreal QPieSeries::pieEndAngle() const
525 525 {
526 526 Q_D(const QPieSeries);
527 527 return d->m_pieEndAngle;
528 528 }
529 529
530 530 /*!
531 531 Sets the all the slice labels \a visible or invisible.
532 532
533 533 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
534 534 */
535 535 void QPieSeries::setLabelsVisible(bool visible)
536 536 {
537 537 Q_D(QPieSeries);
538 538 foreach (QPieSlice* s, d->m_slices)
539 539 s->setLabelVisible(visible);
540 540 }
541 541
542 542 /*!
543 543 Returns the sum of all slice values in this series.
544 544
545 545 \sa QPieSlice::value(), QPieSlice::setValue()
546 546 */
547 547 qreal QPieSeries::total() const
548 548 {
549 549 Q_D(const QPieSeries);
550 550 return d->m_total;
551 551 }
552 552
553 553 /*!
554 554 \fn void QPieSeries::clicked(QPieSlice* slice)
555 555
556 556 This signal is emitted when a \a slice has been clicked.
557 557
558 558 \sa QPieSlice::clicked()
559 559 */
560 560
561 561 /*!
562 562 \fn void QPieSeries::hoverEnter(QPieSlice* slice)
563 563
564 564 This signal is emitted when user has hovered over a \a slice.
565 565
566 566 \sa QPieSlice::hoverEnter()
567 567 */
568 568
569 569 /*!
570 570 \fn void QPieSeries::hoverLeave(QPieSlice* slice)
571 571
572 572 This signal is emitted when user has hovered away from a \a slice.
573 573
574 574 \sa QPieSlice::hoverLeave()
575 575 */
576 576
577 577
578 578
579 579
580 580 bool QPieSeries::setModel(QAbstractItemModel* model)
581 581 {
582 582 Q_D(QPieSeries);
583 583 // disconnect signals from old model
584 584 if(m_model)
585 585 {
586 586 disconnect(m_model, 0, this, 0);
587 587 d->m_mapValues = -1;
588 588 d->m_mapLabels = -1;
589 589 d->m_mapOrientation = Qt::Vertical;
590 590 }
591 591
592 592 // set new model
593 593 if(model)
594 594 {
595 595 m_model = model;
596 596 return true;
597 597 }
598 598 else
599 599 {
600 600 m_model = NULL;
601 601 return false;
602 602 }
603 603 }
604 604
605 605 void QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
606 606 {
607 607 Q_D(QPieSeries);
608 608
609 609 if (m_model == NULL)
610 610 return;
611 611
612 612 d->m_mapValues = modelValuesLine;
613 613 d->m_mapLabels = modelLabelsLine;
614 614 d->m_mapOrientation = orientation;
615 615
616 616 // connect the signals
617 617 if (d->m_mapOrientation == Qt::Vertical) {
618 618 connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex, QModelIndex)));
619 619 connect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
620 620 connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
621 621 } else {
622 622 connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex, QModelIndex)));
623 623 connect(m_model, SIGNAL(columnsInserted(QModelIndex, int, int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
624 624 connect(m_model, SIGNAL(columnsRemoved(QModelIndex, int, int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
625 625 }
626 626
627 627 // create the initial slices set
628 628 if (d->m_mapOrientation == Qt::Vertical) {
629 629 for (int i = 0; i < m_model->rowCount(); i++)
630 630 add(m_model->data(m_model->index(i, d->m_mapValues), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(i, d->m_mapLabels), Qt::DisplayRole).toString());
631 631 } else {
632 632 for (int i = 0; i < m_model->columnCount(); i++)
633 633 add(m_model->data(m_model->index(d->m_mapValues, i), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(d->m_mapLabels, i), Qt::DisplayRole).toString());
634 634 }
635 635 }
636 636
637 637 #include "moc_qpieseries.cpp"
638 638 #include "moc_qpieseriesprivate_p.cpp"
639 639
640 640 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,80 +1,80
1 1 #ifndef PIESERIES_H
2 2 #define PIESERIES_H
3 3
4 4 #include <qseries.h>
5 5
6 6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 7 class QPieSeriesPrivate;
8 8 class QPieSlice;
9 9
10 10 class QTCOMMERCIALCHART_EXPORT QPieSeries : public QSeries
11 11 {
12 12 Q_OBJECT
13 13
14 14 public:
15 15 QPieSeries(QObject *parent = 0);
16 16 virtual ~QPieSeries();
17 17
18 18 public: // from QChartSeries
19 19 QSeriesType type() const;
20 20
21 21 public:
22 22
23 23 // slice setters
24 24 void add(QPieSlice* slice);
25 25 void add(QList<QPieSlice*> slices);
26 26 void insert(int i, QPieSlice* slice);
27 27 void replace(QList<QPieSlice*> slices);
28 28 void remove(QPieSlice* slice);
29 29 void clear();
30 30
31 31 // slice getters
32 32 QList<QPieSlice*> slices() const;
33 33
34 34 // calculated data
35 35 int count() const;
36 36 bool isEmpty() const;
37 37 qreal total() const;
38 38
39 39 // pie customization
40 40 void setPiePosition(qreal relativeHorizontalPosition, qreal relativeVerticalPosition);
41 41 qreal pieHorizontalPosition() const;
42 42 qreal pieVerticalPosition() const;
43 43 void setPieSize(qreal relativeSize);
44 44 qreal pieSize() const;
45 45 void setPieStartAngle(qreal startAngle);
46 46 qreal pieStartAngle() const;
47 47 void setPieEndAngle(qreal endAngle);
48 48 qreal pieEndAngle() const;
49 49
50 50 // convenience function
51 51 QPieSeries& operator << (QPieSlice* slice);
52 52 QPieSlice* add(qreal value, QString name);
53 53 void setLabelsVisible(bool visible = true);
54 54
55 55 // data from model
56 56 bool setModel(QAbstractItemModel* model);
57 57 void setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation = Qt::Vertical);
58 58
59 59 Q_SIGNALS:
60 void clicked(QPieSlice* slice);
60 void clicked(QPieSlice* slice, Qt::MouseButtons buttons);
61 61 void hoverEnter(QPieSlice* slice);
62 62 void hoverLeave(QPieSlice* slice);
63 63 void added(QList<QPieSlice*> slices);
64 64 void removed(QList<QPieSlice*> slices);
65 65 void piePositionChanged();
66 66 void pieSizeChanged();
67 67
68 68 private:
69 69 QPieSeriesPrivate * const d_ptr;
70 70 Q_DECLARE_PRIVATE(QPieSeries)
71 71 Q_DISABLE_COPY(QPieSeries)
72 72
73 73 public:
74 74 typedef QPieSeriesPrivate * const DataPtr;
75 75 inline DataPtr &data_ptr() { return d_ptr; }
76 76 };
77 77
78 78 QTCOMMERCIALCHART_END_NAMESPACE
79 79
80 80 #endif // PIESERIES_H
@@ -1,47 +1,47
1 1 #ifndef QPIESERIESPRIVATE_P_H
2 2 #define QPIESERIESPRIVATE_P_H
3 3
4 4 #include "qpieseries.h"
5 5
6 6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 7
8 8 class QPieSeriesPrivate : public QObject
9 9 {
10 10 Q_OBJECT
11 11 Q_DECLARE_PUBLIC(QPieSeries)
12 12
13 13 public:
14 14 QPieSeriesPrivate(QPieSeries *parent);
15 15 ~QPieSeriesPrivate();
16 16
17 17 void updateDerivativeData();
18 18
19 public Q_SLOTS: // TODO: should be private and not visible in the interface at all
19 public Q_SLOTS:
20 20 void sliceChanged();
21 void sliceClicked();
21 void sliceClicked(Qt::MouseButtons buttons);
22 22 void sliceHoverEnter();
23 23 void sliceHoverLeave();
24 24 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
25 25 void modelDataAdded(QModelIndex parent, int start, int end);
26 26 void modelDataRemoved(QModelIndex parent, int start, int end);
27 27
28 28 public:
29 29 QPieSeries * const q_ptr;
30 30
31 31 QList<QPieSlice*> m_slices;
32 32 qreal m_pieRelativeHorPos;
33 33 qreal m_pieRelativeVerPos;
34 34 qreal m_pieRelativeSize;
35 35 qreal m_pieStartAngle;
36 36 qreal m_pieEndAngle;
37 37 qreal m_total;
38 38
39 39 // model map
40 40 int m_mapValues;
41 41 int m_mapLabels;
42 42 Qt::Orientation m_mapOrientation;
43 43 };
44 44
45 45 QTCOMMERCIALCHART_END_NAMESPACE
46 46
47 47 #endif // QPIESERIESPRIVATE_P_H
@@ -1,71 +1,71
1 1 #ifndef QPIESLICE_H
2 2 #define QPIESLICE_H
3 3
4 4 #include <qchartglobal.h>
5 5 #include <QObject>
6 6 #include <QPen>
7 7 #include <QBrush>
8 8 #include <QFont>
9 9
10 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 11 class QPieSlicePrivate;
12 12
13 13 class QTCOMMERCIALCHART_EXPORT QPieSlice : public QObject
14 14 {
15 15 Q_OBJECT
16 16 Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY changed)
17 17 Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY changed)
18 18
19 19 public:
20 20 QPieSlice(QObject *parent = 0);
21 21 QPieSlice(qreal value, QString label, QObject *parent = 0);
22 22 virtual ~QPieSlice();
23 23
24 24 // data
25 25 void setValue(qreal value);
26 26 qreal value() const;
27 27 void setLabel(QString label);
28 28 QString label() const;
29 29 void setLabelVisible(bool visible = true);
30 30 bool isLabelVisible() const;
31 31 void setExploded(bool exploded = true);
32 32 bool isExploded() const;
33 33
34 34 // generated data
35 35 qreal percentage() const;
36 36 qreal startAngle() const;
37 37 qreal endAngle() const;
38 38
39 39 // customization
40 40 void setSlicePen(const QPen &pen);
41 41 QPen slicePen() const;
42 42 void setSliceBrush(const QBrush &brush);
43 43 QBrush sliceBrush() const;
44 44 void setLabelArmPen(const QPen &pen);
45 45 QPen labelArmPen() const;
46 46 void setLabelFont(const QFont &font);
47 47 QFont labelFont() const;
48 48 void setLabelArmLengthFactor(qreal factor);
49 49 qreal labelArmLengthFactor() const;
50 50 void setExplodeDistanceFactor(qreal factor);
51 51 qreal explodeDistanceFactor() const;
52 52
53 53 Q_SIGNALS:
54 void clicked();
54 void clicked(Qt::MouseButtons buttons);
55 55 void hoverEnter();
56 56 void hoverLeave();
57 57 void changed();
58 58
59 59 private:
60 60 QPieSlicePrivate * const d_ptr;
61 61 Q_DECLARE_PRIVATE(QPieSlice)
62 62 Q_DISABLE_COPY(QPieSlice)
63 63
64 64 public:
65 65 typedef QPieSlicePrivate * const DataPtr;
66 66 inline DataPtr &data_ptr() { return d_ptr; }
67 67 };
68 68
69 69 QTCOMMERCIALCHART_END_NAMESPACE
70 70
71 71 #endif // QPIESLICE_H
General Comments 0
You need to be logged in to leave comments. Login now