##// END OF EJS Templates
pie: change the order of parameters when creating slices to be more intuitive
Jani Honkonen -
r1206:080b090a9a03
parent child
Show More
@@ -1,376 +1,376
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "themewidget.h"
22 22
23 23 #include <QChartView>
24 24 #include <QPieSeries>
25 25 #include <QPieSlice>
26 26 #include <QBarSeries>
27 27 #include <QPercentBarSeries>
28 28 #include <QStackedBarSeries>
29 29 #include <QBarSet>
30 30 #include <QLineSeries>
31 31 #include <QSplineSeries>
32 32 #include <QScatterSeries>
33 33 #include <QAreaSeries>
34 34 #include <QLegend>
35 35 #include <QGridLayout>
36 36 #include <QFormLayout>
37 37 #include <QComboBox>
38 38 #include <QSpinBox>
39 39 #include <QCheckBox>
40 40 #include <QGroupBox>
41 41 #include <QLabel>
42 42 #include <QTime>
43 43
44 44 ThemeWidget::ThemeWidget(QWidget* parent) :
45 45 QWidget(parent),
46 46 m_listCount(3),
47 47 m_valueMax(10),
48 48 m_valueCount(7),
49 49 m_dataTable(generateRandomData(m_listCount,m_valueMax,m_valueCount)),
50 50 m_themeComboBox(createThemeBox()),
51 51 m_antialiasCheckBox(new QCheckBox("Anti-aliasing")),
52 52 m_animatedComboBox(createAnimationBox()),
53 53 m_legendComboBox(createLegendBox())
54 54 {
55 55 connectSignals();
56 56 // create layout
57 57 QGridLayout* baseLayout = new QGridLayout();
58 58 QHBoxLayout *settingsLayout = new QHBoxLayout();
59 59 settingsLayout->addWidget(new QLabel("Theme:"));
60 60 settingsLayout->addWidget(m_themeComboBox);
61 61 settingsLayout->addWidget(new QLabel("Animation:"));
62 62 settingsLayout->addWidget(m_animatedComboBox);
63 63 settingsLayout->addWidget(new QLabel("Legend:"));
64 64 settingsLayout->addWidget(m_legendComboBox);
65 65 settingsLayout->addWidget(m_antialiasCheckBox);
66 66 settingsLayout->addStretch();
67 67 baseLayout->addLayout(settingsLayout, 0, 0, 1, 3);
68 68
69 69 //create charts
70 70
71 71 QChartView *chartView;
72 72
73 73 chartView = new QChartView(createAreaChart());
74 74 baseLayout->addWidget(chartView, 1, 0);
75 75 m_charts << chartView;
76 76
77 77 chartView = new QChartView(createBarChart(m_valueCount));
78 78 baseLayout->addWidget(chartView, 1, 1);
79 79 m_charts << chartView;
80 80
81 81 chartView = new QChartView(createLineChart());
82 82 baseLayout->addWidget(chartView, 1, 2);
83 83 m_charts << chartView;
84 84
85 85 chartView = new QChartView(createPieChart());
86 86 chartView->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); // funny things happen if the pie slice labels no not fit the screen...
87 87 baseLayout->addWidget(chartView, 2, 0);
88 88 m_charts << chartView;
89 89
90 90 chartView = new QChartView(createSplineChart());
91 91 baseLayout->addWidget(chartView, 2, 1);
92 92 m_charts << chartView;
93 93
94 94 chartView = new QChartView(createScatterChart());
95 95 baseLayout->addWidget(chartView, 2, 2);
96 96 m_charts << chartView;
97 97
98 98 setLayout(baseLayout);
99 99
100 100 // Set defaults
101 101 m_antialiasCheckBox->setChecked(true);
102 102 updateUI();
103 103 }
104 104
105 105 ThemeWidget::~ThemeWidget()
106 106 {
107 107 }
108 108
109 109 void ThemeWidget::connectSignals()
110 110 {
111 111 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
112 112 connect(m_antialiasCheckBox, SIGNAL(toggled(bool)), this, SLOT(updateUI()));
113 113 connect(m_animatedComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
114 114 connect(m_legendComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
115 115 }
116 116
117 117 DataTable ThemeWidget::generateRandomData(int listCount,int valueMax,int valueCount) const
118 118 {
119 119 DataTable dataTable;
120 120
121 121 // set seed for random stuff
122 122 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
123 123
124 124 // generate random data
125 125 for (int i(0); i < listCount; i++) {
126 126 DataList dataList;
127 127 qreal yValue(0);
128 128 for (int j(0); j < valueCount; j++) {
129 129 yValue = yValue + (qreal) (qrand() % valueMax) / (qreal) valueCount;
130 130 QPointF value((j + (qreal) rand() / (qreal) RAND_MAX) * ((qreal) m_valueMax / (qreal) valueCount),
131 131 yValue);
132 132 QString label = "Slice " + QString::number(i) + ":" + QString::number(j);
133 133 dataList << Data(value, label);
134 134 }
135 135 dataTable << dataList;
136 136 }
137 137
138 138 return dataTable;
139 139 }
140 140
141 141 QComboBox* ThemeWidget::createThemeBox() const
142 142 {
143 143 // settings layout
144 144 QComboBox* themeComboBox = new QComboBox();
145 145 themeComboBox->addItem("Light", QChart::ChartThemeLight);
146 146 themeComboBox->addItem("Blue Cerulean", QChart::ChartThemeBlueCerulean);
147 147 themeComboBox->addItem("Dark", QChart::ChartThemeDark);
148 148 themeComboBox->addItem("Brown Sand", QChart::ChartThemeBrownSand);
149 149 themeComboBox->addItem("Blue NCS", QChart::ChartThemeBlueNcs);
150 150 themeComboBox->addItem("High Contrast", QChart::ChartThemeHighContrast);
151 151 themeComboBox->addItem("Blue Icy", QChart::ChartThemeBlueIcy);
152 152 return themeComboBox;
153 153 }
154 154
155 155 QComboBox* ThemeWidget::createAnimationBox() const
156 156 {
157 157 // settings layout
158 158 QComboBox* animationComboBox = new QComboBox();
159 159 animationComboBox->addItem("No Animations", QChart::NoAnimation);
160 160 animationComboBox->addItem("GridAxis Animations", QChart::GridAxisAnimations);
161 161 animationComboBox->addItem("Series Animations", QChart::SeriesAnimations);
162 162 animationComboBox->addItem("All Animations", QChart::AllAnimations);
163 163 return animationComboBox;
164 164 }
165 165
166 166 QComboBox* ThemeWidget::createLegendBox() const
167 167 {
168 168 QComboBox* legendComboBox = new QComboBox();
169 169 legendComboBox->addItem("No Legend ", 0);
170 170 legendComboBox->addItem("Legend Top", QLegend::AlignmentTop);
171 171 legendComboBox->addItem("Legend Bottom", QLegend::AlignmentBottom);
172 172 legendComboBox->addItem("Legend Left", QLegend::AlignmentLeft);
173 173 legendComboBox->addItem("Legend Right", QLegend::AlignmentRight);
174 174 return legendComboBox;
175 175 }
176 176
177 177 QChart* ThemeWidget::createAreaChart() const
178 178 {
179 179 QChart *chart = new QChart();
180 180 chart->axisX()->setNiceNumbersEnabled(true);
181 181 chart->axisY()->setNiceNumbersEnabled(true);
182 182 chart->setTitle("Area chart");
183 183
184 184 // The lower series initialized to zero values
185 185 QLineSeries *lowerSeries = 0;
186 186 QString name("Series ");
187 187 int nameIndex = 0;
188 188 for (int i(0); i < m_dataTable.count(); i++) {
189 189 QLineSeries *upperSeries = new QLineSeries(chart);
190 190 for (int j(0); j < m_dataTable[i].count(); j++) {
191 191 Data data = m_dataTable[i].at(j);
192 192 if (lowerSeries){
193 193 const QList<QPointF>& points = lowerSeries->points();
194 194 upperSeries->append(QPointF(j, points[i].y() + data.first.y()));
195 195 }else
196 196 upperSeries->append(QPointF(j, data.first.y()));
197 197 }
198 198 QAreaSeries *area = new QAreaSeries(upperSeries, lowerSeries);
199 199 area->setName(name + QString::number(nameIndex));
200 200 nameIndex++;
201 201 chart->addSeries(area);
202 202 lowerSeries = upperSeries;
203 203 }
204 204
205 205 return chart;
206 206 }
207 207
208 208 QChart* ThemeWidget::createBarChart(int valueCount) const
209 209 {
210 210 QChart* chart = new QChart();
211 211 chart->axisX()->setNiceNumbersEnabled(true);
212 212 chart->axisY()->setNiceNumbersEnabled(true);
213 213 chart->setTitle("Bar chart");
214 214
215 215 QBarCategories categories;
216 216 for (int i(0); i < valueCount; i++)
217 217 categories << QString::number(i);
218 218
219 219 QStackedBarSeries* series = new QStackedBarSeries(chart);
220 220 series->setCategories(categories);
221 221 for (int i(0); i < m_dataTable.count(); i++) {
222 222 QBarSet *set = new QBarSet("Bar set " + QString::number(i));
223 223 foreach (Data data, m_dataTable[i])
224 224 *set << data.first.y();
225 225 series->append(set);
226 226 }
227 227 chart->addSeries(series);
228 228
229 229 return chart;
230 230 }
231 231
232 232 QChart* ThemeWidget::createLineChart() const
233 233 {
234 234 QChart* chart = new QChart();
235 235 chart->axisX()->setNiceNumbersEnabled(true);
236 236 chart->axisY()->setNiceNumbersEnabled(true);
237 237 chart->setTitle("Line chart");
238 238
239 239 QString name("Series ");
240 240 int nameIndex = 0;
241 241 foreach (DataList list, m_dataTable) {
242 242 QLineSeries *series = new QLineSeries(chart);
243 243 foreach (Data data, list)
244 244 series->append(data.first);
245 245 series->setName(name + QString::number(nameIndex));
246 246 nameIndex++;
247 247 chart->addSeries(series);
248 248 }
249 249
250 250 return chart;
251 251 }
252 252
253 253 QChart* ThemeWidget::createPieChart() const
254 254 {
255 255 QChart* chart = new QChart();
256 256 chart->setTitle("Pie chart");
257 257
258 258 qreal pieSize = 1.0 / m_dataTable.count();
259 259 for (int i = 0; i < m_dataTable.count(); i++) {
260 260 QPieSeries *series = new QPieSeries(chart);
261 261 foreach (Data data, m_dataTable[i]) {
262 QPieSlice *slice = series->append(data.first.y(), data.second);
262 QPieSlice *slice = series->append(data.second, data.first.y());
263 263 if (data == m_dataTable[i].first()) {
264 264 slice->setLabelVisible();
265 265 slice->setExploded();
266 266 }
267 267 }
268 268 qreal hPos = (pieSize / 2) + (i / (qreal) m_dataTable.count());
269 269 series->setPieSize(pieSize);
270 270 series->setHorizontalPosition(hPos);
271 271 series->setVerticalPosition(0.5);
272 272 chart->addSeries(series);
273 273 }
274 274
275 275 return chart;
276 276 }
277 277
278 278 QChart* ThemeWidget::createSplineChart() const
279 279 { // spine chart
280 280 QChart* chart = new QChart();
281 281 chart->axisX()->setNiceNumbersEnabled(true);
282 282 chart->axisY()->setNiceNumbersEnabled(true);
283 283 chart->setTitle("Spline chart");
284 284 QString name("Series ");
285 285 int nameIndex = 0;
286 286 foreach (DataList list, m_dataTable) {
287 287 QSplineSeries *series = new QSplineSeries(chart);
288 288 foreach (Data data, list)
289 289 series->append(data.first);
290 290 series->setName(name + QString::number(nameIndex));
291 291 nameIndex++;
292 292 chart->addSeries(series);
293 293 }
294 294 return chart;
295 295 }
296 296
297 297 QChart* ThemeWidget::createScatterChart() const
298 298 { // scatter chart
299 299 QChart* chart = new QChart();
300 300 chart->axisX()->setNiceNumbersEnabled(true);
301 301 chart->axisY()->setNiceNumbersEnabled(true);
302 302 chart->setTitle("Scatter chart");
303 303 QString name("Series ");
304 304 int nameIndex = 0;
305 305 foreach (DataList list, m_dataTable) {
306 306 QScatterSeries *series = new QScatterSeries(chart);
307 307 foreach (Data data, list)
308 308 series->append(data.first);
309 309 series->setName(name + QString::number(nameIndex));
310 310 nameIndex++;
311 311 chart->addSeries(series);
312 312 }
313 313 return chart;
314 314 }
315 315
316 316 void ThemeWidget::updateUI()
317 317 {
318 318 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
319 319
320 320 if (m_charts.at(0)->chart()->theme() != theme) {
321 321 foreach (QChartView *chartView, m_charts)
322 322 chartView->chart()->setTheme(theme);
323 323
324 324 QPalette pal = window()->palette();
325 325 if (theme == QChart::ChartThemeLight) {
326 326 pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
327 327 pal.setColor(QPalette::WindowText, QRgb(0x404044));
328 328 } else if (theme == QChart::ChartThemeDark) {
329 329 pal.setColor(QPalette::Window, QRgb(0x121218));
330 330 pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
331 331 } else if (theme == QChart::ChartThemeBlueCerulean) {
332 332 pal.setColor(QPalette::Window, QRgb(0x40434a));
333 333 pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
334 334 } else if (theme == QChart::ChartThemeBrownSand) {
335 335 pal.setColor(QPalette::Window, QRgb(0x9e8965));
336 336 pal.setColor(QPalette::WindowText, QRgb(0x404044));
337 337 } else if (theme == QChart::ChartThemeBlueNcs) {
338 338 pal.setColor(QPalette::Window, QRgb(0x018bba));
339 339 pal.setColor(QPalette::WindowText, QRgb(0x404044));
340 340 } else if (theme == QChart::ChartThemeHighContrast) {
341 341 pal.setColor(QPalette::Window, QRgb(0xffab03));
342 342 pal.setColor(QPalette::WindowText, QRgb(0x181818));
343 343 } else if (theme == QChart::ChartThemeBlueIcy) {
344 344 pal.setColor(QPalette::Window, QRgb(0xcee7f0));
345 345 pal.setColor(QPalette::WindowText, QRgb(0x404044));
346 346 } else {
347 347 pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
348 348 pal.setColor(QPalette::WindowText, QRgb(0x404044));
349 349 }
350 350 window()->setPalette(pal);
351 351 }
352 352
353 353 bool checked = m_antialiasCheckBox->isChecked();
354 354 foreach (QChartView *chart, m_charts)
355 355 chart->setRenderHint(QPainter::Antialiasing, checked);
356 356
357 357 QChart::AnimationOptions options(m_animatedComboBox->itemData(m_animatedComboBox->currentIndex()).toInt());
358 358 if (m_charts.at(0)->chart()->animationOptions() != options) {
359 359 foreach (QChartView *chartView, m_charts)
360 360 chartView->chart()->setAnimationOptions(options);
361 361 }
362 362
363 363 QLegend::Alignments alignment(m_legendComboBox->itemData(m_legendComboBox->currentIndex()).toInt());
364 364
365 365 if (!alignment) {
366 366 foreach (QChartView *chartView, m_charts) {
367 367 chartView->chart()->legend()->hide();
368 368 }
369 369 } else {
370 370 foreach (QChartView *chartView, m_charts) {
371 371 chartView->chart()->legend()->setAlignment(alignment);
372 372 chartView->chart()->legend()->show();
373 373 }
374 374 }
375 375 }
376 376
@@ -1,48 +1,48
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "customslice.h"
22 22
23 23 QTCOMMERCIALCHART_USE_NAMESPACE
24 24
25 CustomSlice::CustomSlice(qreal value, QString label)
26 :QPieSlice(value, label)
25 CustomSlice::CustomSlice(QString label, qreal value)
26 :QPieSlice(label, value)
27 27 {
28 28 connect(this, SIGNAL(hovered(bool)), this, SLOT(showHighlight(bool)));
29 29 }
30 30
31 31 QBrush CustomSlice::originalBrush()
32 32 {
33 33 return m_originalBrush;
34 34 }
35 35
36 36 void CustomSlice::showHighlight(bool show)
37 37 {
38 38 if (show) {
39 39 QBrush brush = this->brush();
40 40 m_originalBrush = brush;
41 41 brush.setColor(brush.color().lighter());
42 42 setBrush(brush);
43 43 } else {
44 44 setBrush(m_originalBrush);
45 45 }
46 46 }
47 47
48 48 #include "moc_customslice.cpp"
@@ -1,44 +1,44
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20 #ifndef CUSTOMSLICE_H
21 21 #define CUSTOMSLICE_H
22 22
23 23 #include <QPieSlice>
24 24
25 25 QTCOMMERCIALCHART_USE_NAMESPACE
26 26
27 27 class CustomSlice : public QPieSlice
28 28 {
29 29 Q_OBJECT
30 30
31 31 public:
32 CustomSlice(qreal value, QString label);
32 CustomSlice(QString label, qreal value);
33 33
34 34 public:
35 35 QBrush originalBrush();
36 36
37 37 public Q_SLOTS:
38 38 void showHighlight(bool show);
39 39
40 40 private:
41 41 QBrush m_originalBrush;
42 42 };
43 43
44 44 #endif // CUSTOMSLICE_H
@@ -1,331 +1,331
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20 #include "mainwidget.h"
21 21 #include "customslice.h"
22 22 #include "pentool.h"
23 23 #include "brushtool.h"
24 24 #include <QPushButton>
25 25 #include <QComboBox>
26 26 #include <QCheckBox>
27 27 #include <QLabel>
28 28 #include <QGroupBox>
29 29 #include <QDoubleSpinBox>
30 30 #include <QFormLayout>
31 31 #include <QFontDialog>
32 32 #include <QChartView>
33 33 #include <QPieSeries>
34 34
35 35 QTCOMMERCIALCHART_USE_NAMESPACE
36 36
37 37 MainWidget::MainWidget(QWidget* parent)
38 38 :QWidget(parent),
39 39 m_slice(0)
40 40 {
41 41 // create chart
42 42 QChart *chart = new QChart;
43 43 chart->setTitle("Piechart customization");
44 44 chart->setAnimationOptions(QChart::AllAnimations);
45 45
46 46 // create series
47 47 m_series = new QPieSeries();
48 *m_series << new CustomSlice(10.0, "Slice 1");
49 *m_series << new CustomSlice(20.0, "Slice 2");
50 *m_series << new CustomSlice(30.0, "Slice 3");
51 *m_series << new CustomSlice(40.0, "Slice 4");
52 *m_series << new CustomSlice(50.0, "Slice 5");
48 *m_series << new CustomSlice("Slice 1", 10.0);
49 *m_series << new CustomSlice("Slice 2", 20.0);
50 *m_series << new CustomSlice("Slice 3", 30.0);
51 *m_series << new CustomSlice("Slice 4", 40.0);
52 *m_series << new CustomSlice("Slice 5", 50.0);
53 53 m_series->setLabelsVisible();
54 54 chart->addSeries(m_series);
55 55
56 56 connect(m_series, SIGNAL(clicked(QPieSlice*)), this, SLOT(handleSliceClicked(QPieSlice*)));
57 57
58 58 // chart settings
59 59 m_themeComboBox = new QComboBox();
60 60 m_themeComboBox->addItem("Light", QChart::ChartThemeLight);
61 61 m_themeComboBox->addItem("BlueCerulean", QChart::ChartThemeBlueCerulean);
62 62 m_themeComboBox->addItem("Dark", QChart::ChartThemeDark);
63 63 m_themeComboBox->addItem("BrownSand", QChart::ChartThemeBrownSand);
64 64 m_themeComboBox->addItem("BlueNcs", QChart::ChartThemeBlueNcs);
65 65 m_themeComboBox->addItem("High Contrast", QChart::ChartThemeHighContrast);
66 66 m_themeComboBox->addItem("Blue Icy", QChart::ChartThemeBlueIcy);
67 67
68 68 m_aaCheckBox = new QCheckBox();
69 69 m_animationsCheckBox = new QCheckBox();
70 70 m_animationsCheckBox->setCheckState(Qt::Checked);
71 71
72 72 m_legendCheckBox = new QCheckBox();
73 73
74 74 QFormLayout* chartSettingsLayout = new QFormLayout();
75 75 chartSettingsLayout->addRow("Theme", m_themeComboBox);
76 76 chartSettingsLayout->addRow("Antialiasing", m_aaCheckBox);
77 77 chartSettingsLayout->addRow("Animations", m_animationsCheckBox);
78 78 chartSettingsLayout->addRow("Legend", m_legendCheckBox);
79 79 QGroupBox* chartSettings = new QGroupBox("Chart");
80 80 chartSettings->setLayout(chartSettingsLayout);
81 81
82 82 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this ,SLOT(updateChartSettings()));
83 83 connect(m_aaCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
84 84 connect(m_animationsCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
85 85 connect(m_legendCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
86 86
87 87 // series settings
88 88 m_hPosition = new QDoubleSpinBox();
89 89 m_hPosition->setMinimum(0.0);
90 90 m_hPosition->setMaximum(1.0);
91 91 m_hPosition->setSingleStep(0.1);
92 92 m_hPosition->setValue(m_series->horizontalPosition());
93 93
94 94 m_vPosition = new QDoubleSpinBox();
95 95 m_vPosition->setMinimum(0.0);
96 96 m_vPosition->setMaximum(1.0);
97 97 m_vPosition->setSingleStep(0.1);
98 98 m_vPosition->setValue(m_series->verticalPosition());
99 99
100 100 m_sizeFactor = new QDoubleSpinBox();
101 101 m_sizeFactor->setMinimum(0.0);
102 102 m_sizeFactor->setMaximum(1.0);
103 103 m_sizeFactor->setSingleStep(0.1);
104 104 m_sizeFactor->setValue(m_series->pieSize());
105 105
106 106 m_startAngle = new QDoubleSpinBox();
107 107 m_startAngle->setMinimum(0.0);
108 108 m_startAngle->setMaximum(360);
109 109 m_startAngle->setValue(m_series->pieStartAngle());
110 110 m_startAngle->setSingleStep(1);
111 111
112 112 m_endAngle = new QDoubleSpinBox();
113 113 m_endAngle->setMinimum(0.0);
114 114 m_endAngle->setMaximum(360);
115 115 m_endAngle->setValue(m_series->pieEndAngle());
116 116 m_endAngle->setSingleStep(1);
117 117
118 118 QPushButton *appendSlice = new QPushButton("Append slice");
119 119 QPushButton *insertSlice = new QPushButton("Insert slice");
120 120
121 121 QFormLayout* seriesSettingsLayout = new QFormLayout();
122 122 seriesSettingsLayout->addRow("Horizontal position", m_hPosition);
123 123 seriesSettingsLayout->addRow("Vertical position", m_vPosition);
124 124 seriesSettingsLayout->addRow("Size factor", m_sizeFactor);
125 125 seriesSettingsLayout->addRow("Start angle", m_startAngle);
126 126 seriesSettingsLayout->addRow("End angle", m_endAngle);
127 127 seriesSettingsLayout->addRow(appendSlice);
128 128 seriesSettingsLayout->addRow(insertSlice);
129 129 QGroupBox* seriesSettings = new QGroupBox("Series");
130 130 seriesSettings->setLayout(seriesSettingsLayout);
131 131
132 132 connect(m_vPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
133 133 connect(m_hPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
134 134 connect(m_sizeFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
135 135 connect(m_startAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
136 136 connect(m_endAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
137 137 connect(appendSlice, SIGNAL(clicked()), this, SLOT(appendSlice()));
138 138 connect(insertSlice, SIGNAL(clicked()), this, SLOT(insertSlice()));
139 139
140 140 // slice settings
141 141 m_sliceName = new QLabel("<click a slice>");
142 142 m_sliceValue = new QDoubleSpinBox();
143 143 m_sliceValue->setMaximum(1000);
144 144 m_sliceLabelVisible = new QCheckBox();
145 145 m_sliceLabelArmFactor = new QDoubleSpinBox();
146 146 m_sliceLabelArmFactor->setSingleStep(0.01);
147 147 m_sliceExploded = new QCheckBox();
148 148 m_sliceExplodedFactor = new QDoubleSpinBox();
149 149 m_sliceExplodedFactor->setSingleStep(0.01);
150 150 m_pen = new QPushButton();
151 151 m_penTool = new PenTool("Slice pen", this);
152 152 m_brush = new QPushButton();
153 153 m_brushTool = new BrushTool("Slice brush", this);
154 154 m_font = new QPushButton();
155 155 m_labelPen = new QPushButton();
156 156 m_labelPenTool = new PenTool("Label pen", this);
157 157 QPushButton *removeSlice = new QPushButton("Remove slice");
158 158
159 159 QFormLayout* sliceSettingsLayout = new QFormLayout();
160 160 sliceSettingsLayout->addRow("Selected", m_sliceName);
161 161 sliceSettingsLayout->addRow("Value", m_sliceValue);
162 162 sliceSettingsLayout->addRow("Pen", m_pen);
163 163 sliceSettingsLayout->addRow("Brush", m_brush);
164 164 sliceSettingsLayout->addRow("Label visible", m_sliceLabelVisible);
165 165 sliceSettingsLayout->addRow("Label font", m_font);
166 166 sliceSettingsLayout->addRow("Label pen", m_labelPen);
167 167 sliceSettingsLayout->addRow("Label arm length", m_sliceLabelArmFactor);
168 168 sliceSettingsLayout->addRow("Exploded", m_sliceExploded);
169 169 sliceSettingsLayout->addRow("Explode distance", m_sliceExplodedFactor);
170 170 sliceSettingsLayout->addRow(removeSlice);
171 171 QGroupBox* sliceSettings = new QGroupBox("Slice");
172 172 sliceSettings->setLayout(sliceSettingsLayout);
173 173
174 174 connect(m_sliceValue, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
175 175 connect(m_pen, SIGNAL(clicked()), m_penTool, SLOT(show()));
176 176 connect(m_penTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
177 177 connect(m_brush, SIGNAL(clicked()), m_brushTool, SLOT(show()));
178 178 connect(m_brushTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
179 179 connect(m_font, SIGNAL(clicked()), this, SLOT(showFontDialog()));
180 180 connect(m_labelPen, SIGNAL(clicked()), m_labelPenTool, SLOT(show()));
181 181 connect(m_labelPenTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
182 182 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
183 183 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
184 184 connect(m_sliceLabelArmFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
185 185 connect(m_sliceExploded, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
186 186 connect(m_sliceExplodedFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
187 187 connect(removeSlice, SIGNAL(clicked()), this, SLOT(removeSlice()));
188 188
189 189 // create chart view
190 190 m_chartView = new QChartView(chart);
191 191
192 192 // create main layout
193 193 QVBoxLayout *settingsLayout = new QVBoxLayout();
194 194 settingsLayout->addWidget(chartSettings);
195 195 settingsLayout->addWidget(seriesSettings);
196 196 settingsLayout->addWidget(sliceSettings);
197 197 settingsLayout->addStretch();
198 198
199 199 QGridLayout* baseLayout = new QGridLayout();
200 200 baseLayout->addLayout(settingsLayout, 0, 0);
201 201 baseLayout->addWidget(m_chartView, 0, 1);
202 202 setLayout(baseLayout);
203 203
204 204 updateSerieSettings();
205 205 }
206 206
207 207
208 208 void MainWidget::updateChartSettings()
209 209 {
210 210 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
211 211 m_chartView->chart()->setTheme(theme);
212 212 m_chartView->setRenderHint(QPainter::Antialiasing, m_aaCheckBox->isChecked());
213 213
214 214 if (m_animationsCheckBox->checkState() == Qt::Checked)
215 215 m_chartView->chart()->setAnimationOptions(QChart::AllAnimations);
216 216 else
217 217 m_chartView->chart()->setAnimationOptions(QChart::NoAnimation);
218 218
219 219 if (m_legendCheckBox->checkState() == Qt::Checked)
220 220 m_chartView->chart()->legend()->show();
221 221 else
222 222 m_chartView->chart()->legend()->hide();
223 223 }
224 224
225 225 void MainWidget::updateSerieSettings()
226 226 {
227 227 m_series->setHorizontalPosition(m_hPosition->value());
228 228 m_series->setVerticalPosition(m_vPosition->value());
229 229 m_series->setPieSize(m_sizeFactor->value());
230 230 m_series->setPieStartAngle(m_startAngle->value());
231 231 m_series->setPieEndAngle(m_endAngle->value());
232 232 }
233 233
234 234 void MainWidget::updateSliceSettings()
235 235 {
236 236 if (!m_slice)
237 237 return;
238 238
239 239 m_slice->setValue(m_sliceValue->value());
240 240
241 241 m_slice->setPen(m_penTool->pen());
242 242 m_slice->setBrush(m_brushTool->brush());
243 243
244 244 m_slice->setLabelPen(m_labelPenTool->pen());
245 245 m_slice->setLabelVisible(m_sliceLabelVisible->isChecked());
246 246 m_slice->setLabelArmLengthFactor(m_sliceLabelArmFactor->value());
247 247
248 248 m_slice->setExploded(m_sliceExploded->isChecked());
249 249 m_slice->setExplodeDistanceFactor(m_sliceExplodedFactor->value());
250 250 }
251 251
252 252 void MainWidget::handleSliceClicked(QPieSlice* slice)
253 253 {
254 254 m_slice = static_cast<CustomSlice*>(slice);
255 255
256 256 // name
257 257 m_sliceName->setText(slice->label());
258 258
259 259 // value
260 260 m_sliceValue->blockSignals(true);
261 261 m_sliceValue->setValue(slice->value());
262 262 m_sliceValue->blockSignals(false);
263 263
264 264 // pen
265 265 m_pen->setText(PenTool::name(m_slice->pen()));
266 266 m_penTool->setPen(m_slice->pen());
267 267
268 268 // brush
269 269 m_brush->setText(m_slice->originalBrush().color().name());
270 270 m_brushTool->setBrush(m_slice->originalBrush());
271 271
272 272 // label
273 273 m_labelPen->setText(PenTool::name(m_slice->labelPen()));
274 274 m_labelPenTool->setPen(m_slice->labelPen());
275 275 m_font->setText(slice->labelFont().toString());
276 276 m_sliceLabelVisible->blockSignals(true);
277 277 m_sliceLabelVisible->setChecked(slice->isLabelVisible());
278 278 m_sliceLabelVisible->blockSignals(false);
279 279 m_sliceLabelArmFactor->blockSignals(true);
280 280 m_sliceLabelArmFactor->setValue(slice->labelArmLengthFactor());
281 281 m_sliceLabelArmFactor->blockSignals(false);
282 282
283 283 // exploded
284 284 m_sliceExploded->blockSignals(true);
285 285 m_sliceExploded->setChecked(slice->isExploded());
286 286 m_sliceExploded->blockSignals(false);
287 287 m_sliceExplodedFactor->blockSignals(true);
288 288 m_sliceExplodedFactor->setValue(slice->explodeDistanceFactor());
289 289 m_sliceExplodedFactor->blockSignals(false);
290 290 }
291 291
292 292 void MainWidget::showFontDialog()
293 293 {
294 294 if (!m_slice)
295 295 return;
296 296
297 297 QFontDialog dialog(m_slice->labelFont());
298 298 dialog.show();
299 299 dialog.exec();
300 300
301 301 m_slice->setLabelFont(dialog.currentFont());
302 302 m_font->setText(dialog.currentFont().toString());
303 303 }
304 304
305 305 void MainWidget::appendSlice()
306 306 {
307 *m_series << new CustomSlice(10.0, "Slice " + QString::number(m_series->count()+1));
307 *m_series << new CustomSlice("Slice " + QString::number(m_series->count()+1), 10.0);
308 308 }
309 309
310 310 void MainWidget::insertSlice()
311 311 {
312 312 if (!m_slice)
313 313 return;
314 314
315 315 int i = m_series->slices().indexOf(m_slice);
316 316
317 m_series->insert(i, new CustomSlice(10.0, "Slice " + QString::number(m_series->count()+1)));
317 m_series->insert(i, new CustomSlice("Slice " + QString::number(m_series->count()+1), 10.0));
318 318 }
319 319
320 320 void MainWidget::removeSlice()
321 321 {
322 322 if (!m_slice)
323 323 return;
324 324
325 325 m_sliceName->setText("<click a slice>");
326 326
327 327 m_series->remove(m_slice);
328 328 m_slice = 0;
329 329 }
330 330
331 331 #include "moc_mainwidget.cpp"
@@ -1,69 +1,69
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include <QApplication>
22 22 #include <QMainWindow>
23 23 #include <QChartView>
24 24 #include <QPieSeries>
25 25 #include <QPieSlice>
26 26
27 27 QTCOMMERCIALCHART_USE_NAMESPACE
28 28
29 29 int main(int argc, char *argv[])
30 30 {
31 31 QApplication a(argc, argv);
32 32
33 33 //![1]
34 34 QPieSeries *series = new QPieSeries();
35 series->append(1, "Jane");
36 series->append(2, "Joe");
37 series->append(3, "Andy");
38 series->append(4, "Barbara");
39 series->append(5, "Axel");
35 series->append("Jane", 1);
36 series->append("Joe", 2);
37 series->append("Andy", 3);
38 series->append("Barbara", 4);
39 series->append("Axel", 5);
40 40 //![1]
41 41
42 42 //![2]
43 43 QPieSlice *slice = series->slices().at(1);
44 44 slice->setExploded();
45 45 slice->setLabelVisible();
46 46 slice->setPen(QPen(Qt::darkGreen, 2));
47 47 slice->setBrush(Qt::green);
48 48 //![2]
49 49
50 50 //![3]
51 51 QChart* chart = new QChart();
52 52 chart->addSeries(series);
53 53 chart->setTitle("Simple piechart example");
54 54 //![3]
55 55
56 56 //![4]
57 57 QChartView* chartView = new QChartView(chart);
58 58 chartView->setRenderHint(QPainter::Antialiasing);
59 59 //![4]
60 60
61 61 //![5]
62 62 QMainWindow window;
63 63 window.setCentralWidget(chartView);
64 64 window.resize(400, 300);
65 65 window.show();
66 66 //![5]
67 67
68 68 return a.exec();
69 69 }
@@ -1,104 +1,104
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "declarativepieseries.h"
22 22 #include "declarativechart.h"
23 23 #include "qchart.h"
24 24 #include <qdeclarativelist.h>
25 25 #include "qpiemodelmapper.h"
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 DeclarativePieSeries::DeclarativePieSeries(QObject *parent) :
30 30 QPieSeries(parent)
31 31 {
32 32 // TODO: set default model on init?
33 33 // setModel(new DeclarativeTableModel());
34 34
35 35 // TODO: Set default mapper parameters to allow easy to use PieSeries api?
36 36 QPieModelMapper *mapper = modelMapper();//new QPieModelMapper();
37 37 mapper->setMapLabels(0);
38 38 mapper->setMapValues(1);
39 39 mapper->setOrientation(Qt::Vertical);
40 40 mapper->setFirst(0);
41 41 mapper->setCount(-1);
42 42 // setModelMapper(mapper);
43 43 }
44 44
45 45 void DeclarativePieSeries::classBegin()
46 46 {
47 47 }
48 48
49 49 void DeclarativePieSeries::componentComplete()
50 50 {
51 51 foreach(QObject *child, children()) {
52 52 if (qobject_cast<QPieSlice *>(child)) {
53 53 QPieSeries::append(qobject_cast<QPieSlice *>(child));
54 54 }
55 55 }
56 56 }
57 57
58 58 QDeclarativeListProperty<QPieSlice> DeclarativePieSeries::initialSlices()
59 59 {
60 60 return QDeclarativeListProperty<QPieSlice>(this, 0, &DeclarativePieSeries::appendInitialSlices);
61 61 }
62 62
63 63 QPieSlice *DeclarativePieSeries::at(int index)
64 64 {
65 65 QList<QPieSlice*> sliceList = slices();
66 66 if (index < sliceList.count())
67 67 return sliceList[index];
68 68
69 69 return 0;
70 70 }
71 71
72 72 QPieSlice* DeclarativePieSeries::find(QString label)
73 73 {
74 74 foreach (QPieSlice *slice, slices()) {
75 75 if (slice->label() == label)
76 76 return slice;
77 77 }
78 78 return 0;
79 79 }
80 80
81 81 QPieSlice* DeclarativePieSeries::append(QString name, qreal value)
82 82 {
83 83 // TODO: parameter order is wrong, switch it:
84 return QPieSeries::append(value, name);
84 return QPieSeries::append(name, value);
85 85 }
86 86
87 87 void DeclarativePieSeries::setPieModel(DeclarativeTableModel *model)
88 88 {
89 89 QAbstractItemModel *m = qobject_cast<QAbstractItemModel *>(model);
90 90 if (m) {
91 91 QPieSeries::setModel(m);
92 92 } else {
93 93 qWarning("DeclarativePieSeries: Illegal model");
94 94 }
95 95 }
96 96
97 97 DeclarativeTableModel *DeclarativePieSeries::pieModel()
98 98 {
99 99 return qobject_cast<DeclarativeTableModel *>(model());
100 100 }
101 101
102 102 #include "moc_declarativepieseries.cpp"
103 103
104 104 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,813 +1,813
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qpieseries.h"
22 22 #include "qpieseries_p.h"
23 23 #include "qpieslice.h"
24 24 #include "pieslicedata_p.h"
25 25 #include "chartdataset_p.h"
26 26 #include "charttheme_p.h"
27 27 #include "chartanimator_p.h"
28 28 #include "legendmarker_p.h"
29 29 #include <QAbstractItemModel>
30 30 #include "qpiemodelmapper.h"
31 31
32 32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 33
34 34 /*!
35 35 \class QPieSeries
36 36 \brief Pie series API for QtCommercial Charts
37 37
38 38 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
39 39 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
40 40 The actual slice size is determined by that relative value.
41 41
42 42 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
43 43 These relate to the actual chart rectangle.
44 44
45 45 By default the pie is defined as a full pie but it can also be a partial pie.
46 46 This can be done by setting a starting angle and angle span to the series.
47 47 Full pie is 360 degrees where 0 is at 12 a'clock.
48 48
49 49 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
50 50 \image examples_piechart.png
51 51 */
52 52
53 53 /*!
54 54 \property QPieSeries::horizontalPosition
55 55 \brief Defines the horizontal position of the pie.
56 56
57 57 The value is a relative value to the chart rectangle where:
58 58
59 59 \list
60 60 \o 0.0 is the absolute left.
61 61 \o 1.0 is the absolute right.
62 62 \endlist
63 63
64 64 Default value is 0.5 (center).
65 65 */
66 66
67 67 /*!
68 68 \property QPieSeries::verticalPosition
69 69 \brief Defines the vertical position of the pie.
70 70
71 71 The value is a relative value to the chart rectangle where:
72 72
73 73 \list
74 74 \o 0.0 is the absolute top.
75 75 \o 1.0 is the absolute bottom.
76 76 \endlist
77 77
78 78 Default value is 0.5 (center).
79 79 */
80 80
81 81 /*!
82 82 \property QPieSeries::size
83 83 \brief Defines the pie size.
84 84
85 85 The value is a relative value to the chart rectangle where:
86 86
87 87 \list
88 88 \o 0.0 is the minimum size (pie not drawn).
89 89 \o 1.0 is the maximum size that can fit the chart.
90 90 \endlist
91 91
92 92 Default value is 0.7.
93 93 */
94 94
95 95 /*!
96 96 \property QPieSeries::startAngle
97 97 \brief Defines the starting angle of the pie.
98 98
99 99 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
100 100
101 101 Default is value is 0.
102 102 */
103 103
104 104 /*!
105 105 \property QPieSeries::endAngle
106 106 \brief Defines the ending angle of the pie.
107 107
108 108 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
109 109
110 110 Default is value is 360.
111 111 */
112 112
113 113
114 114 /*!
115 115 Constructs a series object which is a child of \a parent.
116 116 */
117 117 QPieSeries::QPieSeries(QObject *parent) :
118 118 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
119 119 {
120 120
121 121 }
122 122
123 123 /*!
124 124 Destroys the series and its slices.
125 125 */
126 126 QPieSeries::~QPieSeries()
127 127 {
128 128 // NOTE: d_prt destroyed by QObject
129 129 }
130 130
131 131 /*!
132 132 Returns QChartSeries::SeriesTypePie.
133 133 */
134 134 QAbstractSeries::SeriesType QPieSeries::type() const
135 135 {
136 136 return QAbstractSeries::SeriesTypePie;
137 137 }
138 138
139 139 /*!
140 140 Appends an array of \a slices to the series.
141 141 Slice ownership is passed to the series.
142 142 */
143 143 bool QPieSeries::append(QList<QPieSlice*> slices)
144 144 {
145 145 Q_D(QPieSeries);
146 146
147 147 if (slices.count() == 0)
148 148 return false;
149 149
150 150 foreach (QPieSlice* s, slices) {
151 151 if (!s || d->m_slices.contains(s))
152 152 return false;
153 153 }
154 154
155 155 foreach (QPieSlice* s, slices) {
156 156 s->setParent(this);
157 157 d->m_slices << s;
158 158 }
159 159
160 160 d->updateDerivativeData();
161 161
162 162 foreach (QPieSlice* s, slices) {
163 163 connect(s, SIGNAL(changed()), d, SLOT(sliceChanged()));
164 164 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
165 165 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
166 166 }
167 167
168 168 emit d->added(slices);
169 169
170 170 return true;
171 171 }
172 172
173 173 /*!
174 174 Appends a single \a slice to the series.
175 175 Slice ownership is passed to the series.
176 176 */
177 177 bool QPieSeries::append(QPieSlice* slice)
178 178 {
179 179 return append(QList<QPieSlice*>() << slice);
180 180 }
181 181
182 182 /*!
183 183 Appends a single \a slice to the series and returns a reference to the series.
184 184 Slice ownership is passed to the series.
185 185 */
186 186 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
187 187 {
188 188 append(slice);
189 189 return *this;
190 190 }
191 191
192 192
193 193 /*!
194 Appends a single slice to the series with give \a value and \a name.
194 Appends a single slice to the series with give \a value and \a label.
195 195 Slice ownership is passed to the series.
196 196 */
197 QPieSlice* QPieSeries::append(qreal value, QString name)
197 QPieSlice* QPieSeries::append(QString label, qreal value)
198 198 {
199 QPieSlice* slice = new QPieSlice(value, name);
199 QPieSlice* slice = new QPieSlice(label, value);
200 200 append(slice);
201 201 return slice;
202 202 }
203 203
204 204 /*!
205 205 Inserts a single \a slice to the series before the slice at \a index position.
206 206 Slice ownership is passed to the series.
207 207 */
208 208 bool QPieSeries::insert(int index, QPieSlice* slice)
209 209 {
210 210 Q_D(QPieSeries);
211 211
212 212 if (index < 0 || index > d->m_slices.count())
213 213 return false;
214 214
215 215 if (!slice || d->m_slices.contains(slice))
216 216 return false;
217 217
218 218 slice->setParent(this);
219 219 d->m_slices.insert(index, slice);
220 220
221 221 d->updateDerivativeData();
222 222
223 223 connect(slice, SIGNAL(changed()), d, SLOT(sliceChanged()));
224 224 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
225 225 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
226 226
227 227 emit d->added(QList<QPieSlice*>() << slice);
228 228
229 229 return true;
230 230 }
231 231
232 232 /*!
233 233 Removes a single \a slice from the series and deletes the slice.
234 234
235 235 Do not reference the pointer after this call.
236 236 */
237 237 bool QPieSeries::remove(QPieSlice* slice)
238 238 {
239 239 Q_D(QPieSeries);
240 240
241 241 if (!d->m_slices.removeOne(slice))
242 242 return false;
243 243
244 244 d->updateDerivativeData();
245 245
246 246 emit d->removed(QList<QPieSlice*>() << slice);
247 247
248 248 delete slice;
249 249 slice = 0;
250 250
251 251 return true;
252 252 }
253 253
254 254 /*!
255 255 Clears all slices from the series.
256 256 */
257 257 void QPieSeries::clear()
258 258 {
259 259 Q_D(QPieSeries);
260 260 if (d->m_slices.count() == 0)
261 261 return;
262 262
263 263 QList<QPieSlice*> slices = d->m_slices;
264 264 foreach (QPieSlice* s, d->m_slices) {
265 265 d->m_slices.removeOne(s);
266 266 delete s;
267 267 }
268 268
269 269 d->updateDerivativeData();
270 270
271 271 emit d->removed(slices);
272 272 }
273 273
274 274 /*!
275 275 returns the number of the slices in this series.
276 276 */
277 277 int QPieSeries::count() const
278 278 {
279 279 Q_D(const QPieSeries);
280 280 return d->m_slices.count();
281 281 }
282 282
283 283 /*!
284 284 Returns true is the series is empty.
285 285 */
286 286 bool QPieSeries::isEmpty() const
287 287 {
288 288 Q_D(const QPieSeries);
289 289 return d->m_slices.isEmpty();
290 290 }
291 291
292 292 /*!
293 293 Returns a list of slices that belong to this series.
294 294 */
295 295 QList<QPieSlice*> QPieSeries::slices() const
296 296 {
297 297 Q_D(const QPieSeries);
298 298 return d->m_slices;
299 299 }
300 300
301 301 void QPieSeries::setHorizontalPosition(qreal relativePosition)
302 302 {
303 303 Q_D(QPieSeries);
304 304 if (d->setRealValue(d->m_pieRelativeHorPos, relativePosition, 1.0))
305 305 emit d->piePositionChanged();
306 306 }
307 307
308 308 void QPieSeries::setVerticalPosition(qreal relativePosition)
309 309 {
310 310 Q_D(QPieSeries);
311 311 if (d->setRealValue(d->m_pieRelativeVerPos, relativePosition, 1.0))
312 312 emit d->piePositionChanged();
313 313 }
314 314
315 315 qreal QPieSeries::horizontalPosition() const
316 316 {
317 317 Q_D(const QPieSeries);
318 318 return d->m_pieRelativeHorPos;
319 319 }
320 320
321 321 qreal QPieSeries::verticalPosition() const
322 322 {
323 323 Q_D(const QPieSeries);
324 324 return d->m_pieRelativeVerPos;
325 325 }
326 326
327 327 void QPieSeries::setPieSize(qreal relativeSize)
328 328 {
329 329 Q_D(QPieSeries);
330 330 if (d->setRealValue(d->m_pieRelativeSize, relativeSize, 1.0))
331 331 emit d->pieSizeChanged();
332 332 }
333 333
334 334 qreal QPieSeries::pieSize() const
335 335 {
336 336 Q_D(const QPieSeries);
337 337 return d->m_pieRelativeSize;
338 338 }
339 339
340 340
341 341 void QPieSeries::setPieStartAngle(qreal angle)
342 342 {
343 343 Q_D(QPieSeries);
344 344 if (d->setRealValue(d->m_pieStartAngle, angle, d->m_pieEndAngle))
345 345 d->updateDerivativeData();
346 346 }
347 347
348 348 qreal QPieSeries::pieStartAngle() const
349 349 {
350 350 Q_D(const QPieSeries);
351 351 return d->m_pieStartAngle;
352 352 }
353 353
354 354 /*!
355 355 Sets the end angle of the pie.
356 356
357 357 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
358 358
359 359 \a angle must be greater than start angle.
360 360
361 361 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
362 362 */
363 363 void QPieSeries::setPieEndAngle(qreal angle)
364 364 {
365 365 Q_D(QPieSeries);
366 366
367 367 if (d->setRealValue(d->m_pieEndAngle, angle, 360.0, d->m_pieStartAngle))
368 368 d->updateDerivativeData();
369 369 }
370 370
371 371 /*!
372 372 Returns the end angle of the pie.
373 373
374 374 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
375 375
376 376 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
377 377 */
378 378 qreal QPieSeries::pieEndAngle() const
379 379 {
380 380 Q_D(const QPieSeries);
381 381 return d->m_pieEndAngle;
382 382 }
383 383
384 384 /*!
385 385 Sets the all the slice labels \a visible or invisible.
386 386
387 387 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
388 388 */
389 389 void QPieSeries::setLabelsVisible(bool visible)
390 390 {
391 391 Q_D(QPieSeries);
392 392 foreach (QPieSlice* s, d->m_slices)
393 393 s->setLabelVisible(visible);
394 394 }
395 395
396 396 /*!
397 397 Returns the sum of all slice values in this series.
398 398
399 399 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
400 400 */
401 401 qreal QPieSeries::sum() const
402 402 {
403 403 Q_D(const QPieSeries);
404 404 return d->m_sum;
405 405 }
406 406
407 407 /*!
408 408 \fn void QPieSeries::clicked(QPieSlice* slice)
409 409
410 410 This signal is emitted when a \a slice has been clicked.
411 411
412 412 \sa QPieSlice::clicked()
413 413 */
414 414
415 415 /*!
416 416 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
417 417
418 418 This signal is emitted when user has hovered over or away from the \a slice.
419 419
420 420 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
421 421
422 422 \sa QPieSlice::hovered()
423 423 */
424 424
425 425 /*!
426 426 \fn bool QPieSeries::setModel(QAbstractItemModel *model)
427 427 Sets the \a model to be used as a data source
428 428 */
429 429 void QPieSeries::setModel(QAbstractItemModel* model)
430 430 {
431 431 Q_D(QPieSeries);
432 432 // disconnect signals from old model
433 433 if(d->m_model)
434 434 {
435 435 disconnect(d->m_model, 0, this, 0);
436 436 }
437 437
438 438 // set new model
439 439 if(model)
440 440 {
441 441 d->m_model = model;
442 442 // connect signals from the model
443 443 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
444 444 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
445 445 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
446 446 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
447 447 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
448 448
449 449 if (d->m_mapper)
450 450 d->initializePieFromModel();
451 451 }
452 452 else
453 453 {
454 454 d->m_model = 0;
455 455 }
456 456 }
457 457
458 458 void QPieSeries::setModelMapper(QPieModelMapper *mapper)
459 459 {
460 460 Q_D(QPieSeries);
461 461 // disconnect signals from old mapper
462 462 if (d->m_mapper) {
463 463 QObject::disconnect(d->m_mapper, 0, this, 0);
464 464 }
465 465
466 466 if (mapper) {
467 467 d->m_mapper = mapper;
468 468 // connect the signal from the mapper
469 469 connect(d->m_mapper, SIGNAL(updated()), d, SLOT(initializePieFromModel()));
470 470
471 471 if (d->m_model)
472 472 d->initializePieFromModel();
473 473 } else {
474 474 d->m_mapper = 0;
475 475 }
476 476 }
477 477
478 478 QPieModelMapper* QPieSeries::modelMapper() const
479 479 {
480 480 Q_D(const QPieSeries);
481 481 return d->m_mapper;
482 482 }
483 483
484 484 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
485 485
486 486
487 487 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
488 488 QAbstractSeriesPrivate(parent),
489 489 m_pieRelativeHorPos(0.5),
490 490 m_pieRelativeVerPos(0.5),
491 491 m_pieRelativeSize(0.7),
492 492 m_pieStartAngle(0),
493 493 m_pieEndAngle(360),
494 494 m_sum(0),
495 495 m_mapper(0)
496 496 {
497 497
498 498 }
499 499
500 500 QPieSeriesPrivate::~QPieSeriesPrivate()
501 501 {
502 502
503 503 }
504 504
505 505 void QPieSeriesPrivate::updateDerivativeData()
506 506 {
507 507 m_sum = 0;
508 508
509 509 // nothing to do?
510 510 if (m_slices.count() == 0)
511 511 return;
512 512
513 513 // calculate sum of all slices
514 514 foreach (QPieSlice* s, m_slices)
515 515 m_sum += s->value();
516 516
517 517 // nothing to show..
518 518 if (qFuzzyIsNull(m_sum))
519 519 return;
520 520
521 521 // update slice attributes
522 522 qreal sliceAngle = m_pieStartAngle;
523 523 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
524 524 QVector<QPieSlice*> changed;
525 525 foreach (QPieSlice* s, m_slices) {
526 526
527 527 PieSliceData data = PieSliceData::data(s);
528 528 data.m_percentage = s->value() / m_sum;
529 529 data.m_angleSpan = pieSpan * data.m_percentage;
530 530 data.m_startAngle = sliceAngle;
531 531 sliceAngle += data.m_angleSpan;
532 532
533 533 if (PieSliceData::data(s) != data) {
534 534 PieSliceData::data(s) = data;
535 535 changed << s;
536 536 }
537 537 }
538 538
539 539 // emit signals
540 540 foreach (QPieSlice* s, changed)
541 541 PieSliceData::data(s).emitChangedSignal(s);
542 542 }
543 543
544 544 QPieSeriesPrivate* QPieSeriesPrivate::seriesData(QPieSeries &series)
545 545 {
546 546 return series.d_func();
547 547 }
548 548
549 549 void QPieSeriesPrivate::sliceChanged()
550 550 {
551 551 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
552 552 updateDerivativeData();
553 553 }
554 554
555 555 void QPieSeriesPrivate::sliceClicked()
556 556 {
557 557 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
558 558 Q_ASSERT(m_slices.contains(slice));
559 559 Q_Q(QPieSeries);
560 560 emit q->clicked(slice);
561 561 }
562 562
563 563 void QPieSeriesPrivate::sliceHovered(bool state)
564 564 {
565 565 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
566 566 Q_ASSERT(m_slices.contains(slice));
567 567 Q_Q(QPieSeries);
568 568 emit q->hovered(slice, state);
569 569 }
570 570
571 571 void QPieSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
572 572 {
573 573 if (m_mapper) {
574 574 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
575 575 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
576 576 if (m_mapper->orientation() == Qt::Vertical)
577 577 {
578 578 if ( topLeft.row() >= m_mapper->first() && (m_mapper->count() == - 1 || topLeft.row() < m_mapper->first() + m_mapper->count())) {
579 579 if (topLeft.column() == m_mapper->mapValues())
580 580 m_slices.at(topLeft.row() - m_mapper->first())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
581 581 if (topLeft.column() == m_mapper->mapLabels())
582 582 m_slices.at(topLeft.row() - m_mapper->first())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
583 583 }
584 584 }
585 585 else
586 586 {
587 587 if (topLeft.column() >= m_mapper->first() && (m_mapper->count() == - 1 || topLeft.column() < m_mapper->first() + m_mapper->count())) {
588 588 if (topLeft.row() == m_mapper->mapValues())
589 589 m_slices.at(topLeft.column() - m_mapper->first())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
590 590 if (topLeft.row() == m_mapper->mapLabels())
591 591 m_slices.at(topLeft.column() - m_mapper->first())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
592 592 }
593 593 }
594 594 }
595 595 }
596 596 }
597 597 }
598 598
599 599
600 600 void QPieSeriesPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
601 601 {
602 602 Q_UNUSED(parent);
603 603 if (m_mapper) {
604 604 if (m_mapper->orientation() == Qt::Vertical)
605 605 insertData(start, end);
606 606 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
607 607 initializePieFromModel();
608 608 }
609 609 }
610 610
611 611 void QPieSeriesPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
612 612 {
613 613 Q_UNUSED(parent);
614 614 if (m_mapper) {
615 615 if (m_mapper->orientation() == Qt::Vertical)
616 616 removeData(start, end);
617 617 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
618 618 initializePieFromModel();
619 619 }
620 620 }
621 621
622 622 void QPieSeriesPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
623 623 {
624 624 Q_UNUSED(parent);
625 625 if (m_mapper) {
626 626 if (m_mapper->orientation() == Qt::Horizontal)
627 627 insertData(start, end);
628 628 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
629 629 initializePieFromModel();
630 630 }
631 631 }
632 632
633 633 void QPieSeriesPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
634 634 {
635 635 Q_UNUSED(parent);
636 636 if (m_mapper) {
637 637 if (m_mapper->orientation() == Qt::Horizontal)
638 638 removeData(start, end);
639 639 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
640 640 initializePieFromModel();
641 641 }
642 642 }
643 643
644 644 void QPieSeriesPrivate::insertData(int start, int end)
645 645 {
646 646 Q_Q(QPieSeries);
647 647 if (m_mapper) {
648 648 if (m_mapper->count() != -1 && start >= m_mapper->first() + m_mapper->count()) {
649 649 return;
650 650 } else {
651 651 int addedCount = end - start + 1;
652 652 if (m_mapper->count() != -1 && addedCount > m_mapper->count())
653 653 addedCount = m_mapper->count();
654 654 int first = qMax(start, m_mapper->first());
655 655 int last = qMin(first + addedCount - 1, m_mapper->orientation() == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
656 656 for (int i = first; i <= last; i++) {
657 657 QPieSlice *slice = new QPieSlice;
658 658 if (m_mapper->orientation() == Qt::Vertical) {
659 659 slice->setValue(m_model->data(m_model->index(i, m_mapper->mapValues()), Qt::DisplayRole).toDouble());
660 660 slice->setLabel(m_model->data(m_model->index(i, m_mapper->mapLabels()), Qt::DisplayRole).toString());
661 661 } else {
662 662 slice->setValue(m_model->data(m_model->index(m_mapper->mapValues(), i), Qt::DisplayRole).toDouble());
663 663 slice->setLabel(m_model->data(m_model->index(m_mapper->mapLabels(), i), Qt::DisplayRole).toString());
664 664 }
665 665 slice->setLabelVisible();
666 666 q->insert(i - m_mapper->first(), slice);
667 667 }
668 668 if (m_mapper->count() != -1 && m_slices.size() > m_mapper->count())
669 669 for (int i = m_slices.size() - 1; i >= m_mapper->count(); i--)
670 670 q->remove(q->slices().at(i));
671 671 }
672 672 }
673 673 }
674 674
675 675 void QPieSeriesPrivate::removeData(int start, int end)
676 676 {
677 677 Q_Q(QPieSeries);
678 678 if (m_mapper) {
679 679 int removedCount = end - start + 1;
680 680 if (m_mapper->count() != -1 && start >= m_mapper->first() + m_mapper->count()) {
681 681 return;
682 682 } else {
683 683 int toRemove = qMin(m_slices.size(), removedCount); // first find how many items can actually be removed
684 684 int first = qMax(start, m_mapper->first()); // get the index of the first item that will be removed.
685 685 int last = qMin(first + toRemove - 1, m_slices.size() + m_mapper->first() - 1); // get the index of the last item that will be removed.
686 686 for (int i = last; i >= first; i--)
687 687 q->remove(q->slices().at(i - m_mapper->first()));
688 688
689 689 if (m_mapper->count() != -1) {
690 690 int itemsAvailable; // check how many are available to be added
691 691 if (m_mapper->orientation() == Qt::Vertical)
692 692 itemsAvailable = m_model->rowCount() - m_mapper->first() - m_slices.size();
693 693 else
694 694 itemsAvailable = m_model->columnCount() - m_mapper->first() - m_slices.size();
695 695 int toBeAdded = qMin(itemsAvailable, m_mapper->count() - m_slices.size()); // add not more items than there is space left to be filled.
696 696 int currentSize = m_slices.size();
697 697 if (toBeAdded > 0)
698 698 for (int i = m_slices.size(); i < currentSize + toBeAdded; i++) {
699 699 QPieSlice *slice = new QPieSlice;
700 700 if (m_mapper->orientation() == Qt::Vertical) {
701 701 slice->setValue(m_model->data(m_model->index(i + m_mapper->first(), m_mapper->mapValues()), Qt::DisplayRole).toDouble());
702 702 slice->setLabel(m_model->data(m_model->index(i + m_mapper->first(), m_mapper->mapLabels()), Qt::DisplayRole).toString());
703 703 } else {
704 704 slice->setValue(m_model->data(m_model->index(m_mapper->mapValues(), i + m_mapper->first()), Qt::DisplayRole).toDouble());
705 705 slice->setLabel(m_model->data(m_model->index(m_mapper->mapLabels(), i + m_mapper->first()), Qt::DisplayRole).toString());
706 706 }
707 707 slice->setLabelVisible();
708 708 q->insert(i, slice);
709 709 }
710 710 }
711 711 }
712 712 }
713 713 }
714 714
715 715 void QPieSeriesPrivate::initializePieFromModel()
716 716 {
717 717 Q_Q(QPieSeries);
718 718
719 719 // clear current content
720 720 q->clear();
721 721
722 722 if (m_model == 0 || m_mapper == 0)
723 723 return;
724 724
725 725 // check if mappings are set
726 726 if (m_mapper->mapValues() == -1 || m_mapper->mapLabels() == -1)
727 727 return;
728 728
729 729 // create the initial slices set
730 730 if (m_mapper->orientation() == Qt::Vertical) {
731 731 if (m_mapper->mapValues() >= m_model->columnCount() || m_mapper->mapLabels() >= m_model->columnCount())
732 732 return; // mapped columns are not existing
733 733
734 734 int sliceCount = 0;
735 735 if(m_mapper->count() == -1)
736 736 sliceCount = m_model->rowCount() - m_mapper->first();
737 737 else
738 738 sliceCount = qMin(m_mapper->count(), m_model->rowCount() - m_mapper->first());
739 739 for (int i = m_mapper->first(); i < m_mapper->first() + sliceCount; i++)
740 q->append(m_model->data(m_model->index(i, m_mapper->mapValues()), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(i, m_mapper->mapLabels()), Qt::DisplayRole).toString());
740 q->append(m_model->data(m_model->index(i, m_mapper->mapLabels()), Qt::DisplayRole).toString(), m_model->data(m_model->index(i, m_mapper->mapValues()), Qt::DisplayRole).toDouble());
741 741 } else {
742 742 if (m_mapper->mapValues() >= m_model->rowCount() || m_mapper->mapLabels() >= m_model->rowCount())
743 743 return; // mapped columns are not existing
744 744
745 745 int sliceCount = 0;
746 746 if(m_mapper->count() == -1)
747 747 sliceCount = m_model->columnCount() - m_mapper->first();
748 748 else
749 749 sliceCount = qMin(m_mapper->count(), m_model->columnCount() - m_mapper->first());
750 750 for (int i = m_mapper->first(); i < m_mapper->first() + sliceCount; i++)
751 q->append(m_model->data(m_model->index(m_mapper->mapValues(), i), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(m_mapper->mapLabels(), i), Qt::DisplayRole).toString());
751 q->append(m_model->data(m_model->index(m_mapper->mapLabels(), i), Qt::DisplayRole).toString(), m_model->data(m_model->index(m_mapper->mapValues(), i), Qt::DisplayRole).toDouble());
752 752 }
753 753 q->setLabelsVisible(true);
754 754 }
755 755
756 756 bool QPieSeriesPrivate::setRealValue(qreal &value, qreal newValue, qreal max, qreal min)
757 757 {
758 758 // Remove rounding errors
759 759 qreal roundedValue = newValue;
760 760 if (qFuzzyIsNull(min) && qFuzzyIsNull(newValue))
761 761 roundedValue = 0.0;
762 762 else if (qFuzzyCompare(newValue, max))
763 763 roundedValue = max;
764 764 else if (qFuzzyCompare(newValue, min))
765 765 roundedValue = min;
766 766
767 767 // Check if the position is valid after removing the rounding errors
768 768 if (roundedValue < min || roundedValue > max) {
769 769 qWarning("QPieSeries: Illegal value");
770 770 return false;
771 771 }
772 772
773 773 if (!qFuzzyIsNull(value - roundedValue)) {
774 774 value = roundedValue;
775 775 return true;
776 776 }
777 777
778 778 // The change was so small it is considered a rounding error
779 779 return false;
780 780 }
781 781
782 782 void QPieSeriesPrivate::scaleDomain(Domain& domain)
783 783 {
784 784 Q_UNUSED(domain);
785 785 // does not apply to pie
786 786 }
787 787
788 788 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
789 789 {
790 790 Q_Q(QPieSeries);
791 791 PieChartItem* pie = new PieChartItem(q,presenter);
792 792 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
793 793 presenter->animator()->addAnimation(pie);
794 794 }
795 795 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
796 796 return pie;
797 797 }
798 798
799 799 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
800 800 {
801 801 Q_Q(QPieSeries);
802 802 QList<LegendMarker*> markers;
803 803 foreach(QPieSlice* slice, q->slices()) {
804 804 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
805 805 markers << marker;
806 806 }
807 807 return markers;
808 808 }
809 809
810 810 #include "moc_qpieseries.cpp"
811 811 #include "moc_qpieseries_p.cpp"
812 812
813 813 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,92 +1,92
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #ifndef PIESERIES_H
22 22 #define PIESERIES_H
23 23
24 24 #include <qabstractseries.h>
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27 class QPieSeriesPrivate;
28 28 class QPieSlice;
29 29 class QPieModelMapper;
30 30
31 31 class QTCOMMERCIALCHART_EXPORT QPieSeries : public QAbstractSeries
32 32 {
33 33 Q_OBJECT
34 34 Q_PROPERTY(qreal horizontalPosition READ horizontalPosition WRITE setHorizontalPosition)
35 35 Q_PROPERTY(qreal verticalPosition READ verticalPosition WRITE setVerticalPosition)
36 36 Q_PROPERTY(qreal size READ pieSize WRITE setPieSize)
37 37 Q_PROPERTY(qreal startAngle READ pieStartAngle WRITE setPieStartAngle)
38 38 Q_PROPERTY(qreal endAngle READ pieEndAngle WRITE setPieEndAngle)
39 39 Q_PROPERTY(int count READ count)
40 40 Q_PROPERTY(QPieModelMapper *modelMapper READ modelMapper)
41 41
42 42 public:
43 43 explicit QPieSeries(QObject *parent = 0);
44 44 virtual ~QPieSeries();
45 45
46 46 QAbstractSeries::SeriesType type() const;
47 47
48 48 bool append(QPieSlice* slice);
49 49 bool append(QList<QPieSlice*> slices);
50 50 QPieSeries& operator << (QPieSlice* slice);
51 QPieSlice* append(qreal value, QString name);
51 QPieSlice* append(QString label, qreal value);
52 52 bool insert(int index, QPieSlice* slice);
53 53 bool remove(QPieSlice* slice);
54 54 void clear();
55 55
56 56 QList<QPieSlice*> slices() const;
57 57 int count() const;
58 58 bool isEmpty() const;
59 59
60 60 qreal sum() const;
61 61
62 62 void setHorizontalPosition(qreal relativePosition);
63 63 qreal horizontalPosition() const;
64 64 void setVerticalPosition(qreal relativePosition);
65 65 qreal verticalPosition() const;
66 66
67 67 void setPieSize(qreal relativeSize);
68 68 qreal pieSize() const;
69 69
70 70 void setPieStartAngle(qreal startAngle);
71 71 qreal pieStartAngle() const;
72 72 void setPieEndAngle(qreal endAngle);
73 73 qreal pieEndAngle() const;
74 74
75 75 void setLabelsVisible(bool visible = true);
76 76
77 77 void setModel(QAbstractItemModel* model);
78 78 void setModelMapper(QPieModelMapper *mapper);
79 79 QPieModelMapper* modelMapper() const;
80 80
81 81 Q_SIGNALS:
82 82 void clicked(QPieSlice* slice);
83 83 void hovered(QPieSlice* slice, bool state);
84 84
85 85 private:
86 86 Q_DECLARE_PRIVATE(QPieSeries)
87 87 Q_DISABLE_COPY(QPieSeries)
88 88 };
89 89
90 90 QTCOMMERCIALCHART_END_NAMESPACE
91 91
92 92 #endif // PIESERIES_H
@@ -1,411 +1,411
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qpieslice.h"
22 22 #include "pieslicedata_p.h"
23 23
24 24 QTCOMMERCIALCHART_BEGIN_NAMESPACE
25 25
26 26 /*!
27 27 \class QPieSlice
28 28 \brief Defines a slice in pie series.
29 29
30 30 This object defines the properties of a single slice in a QPieSeries.
31 31
32 32 In addition to the obvious value and label properties the user can also control
33 33 the visual appearance of a slice. By modifying the visual appearance also means that
34 34 the user is overriding the default appearance set by the theme. Even if the theme is
35 35 changed users settings will persist.
36 36
37 37 To enable user interaction customization with the slices some basic signals
38 38 are provided about clicking and hovering.
39 39 */
40 40
41 41 /*!
42 42 \property QPieSlice::label
43 43
44 44 Label of the slice.
45 45 */
46 46
47 47 /*!
48 48 \property QPieSlice::value
49 49
50 50 Value of the slice.
51 51
52 52 \sa percentage(), QPieSeries::sum()
53 53 */
54 54
55 55 /*!
56 56 Constructs an empty slice with a \a parent.
57 57
58 58 \sa QPieSeries::append(), QPieSeries::insert()
59 59 */
60 60 QPieSlice::QPieSlice(QObject *parent)
61 61 :QObject(parent),
62 62 d(new PieSliceData())
63 63 {
64 64
65 65 }
66 66
67 67 /*!
68 68 Constructs an empty slice with given \a value, \a label and a \a parent.
69 69 \sa QPieSeries::append(), QPieSeries::insert()
70 70 */
71 QPieSlice::QPieSlice(qreal value, QString label, QObject *parent)
71 QPieSlice::QPieSlice(QString label, qreal value, QObject *parent)
72 72 :QObject(parent),
73 73 d(new PieSliceData())
74 74 {
75 75 d->m_value = value;
76 76 d->m_labelText = label;
77 77 }
78 78
79 79 /*!
80 80 Destroys the slice.
81 81 User should not delete the slice if it has been added to the series.
82 82 */
83 83 QPieSlice::~QPieSlice()
84 84 {
85 85 delete d;
86 86 }
87 87
88 88 /*!
89 89 Gets the value of the slice.
90 90 Note that all values in the series
91 91 \sa setValue()
92 92 */
93 93 qreal QPieSlice::value() const
94 94 {
95 95 return d->m_value;
96 96 }
97 97
98 98 /*!
99 99 Gets the label of the slice.
100 100 \sa setLabel()
101 101 */
102 102 QString QPieSlice::label() const
103 103 {
104 104 return d->m_labelText;
105 105 }
106 106
107 107 /*!
108 108 Returns true if label is set as visible.
109 109 \sa setLabelVisible()
110 110 */
111 111 bool QPieSlice::isLabelVisible() const
112 112 {
113 113 return d->m_isLabelVisible;
114 114 }
115 115
116 116 /*!
117 117 Returns true if slice is exloded from the pie.
118 118 \sa setExploded(), explodeDistanceFactor(), setExplodeDistanceFactor()
119 119 */
120 120 bool QPieSlice::isExploded() const
121 121 {
122 122 return d->m_isExploded;
123 123 }
124 124
125 125 /*!
126 126 Returns the explode distance factor.
127 127
128 128 The factor is relative to pie radius. For example:
129 129 1.0 means the distance is the same as the radius.
130 130 0.5 means the distance is half of the radius.
131 131
132 132 Default value is 0.15.
133 133
134 134 \sa setExplodeDistanceFactor(), isExploded(), setExploded()
135 135 */
136 136 qreal QPieSlice::explodeDistanceFactor() const
137 137 {
138 138 return d->m_explodeDistanceFactor;
139 139 }
140 140
141 141 /*!
142 142 Returns the percentage of this slice compared to the sum of all slices in the same series.
143 143 The returned value ranges from 0 to 1.0.
144 144
145 145 Updated internally after the slice is added to the series.
146 146
147 147 \sa QPieSeries::sum()
148 148 */
149 149 qreal QPieSlice::percentage() const
150 150 {
151 151 return d->m_percentage;
152 152 }
153 153
154 154 /*!
155 155 Returns the starting angle of this slice in the series it belongs to.
156 156
157 157 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
158 158
159 159 Updated internally after the slice is added to the series.
160 160 */
161 161 qreal QPieSlice::startAngle() const
162 162 {
163 163 return d->m_startAngle;
164 164 }
165 165
166 166 /*!
167 167 Returns the end angle of this slice in the series it belongs to.
168 168
169 169 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
170 170
171 171 Updated internally after the slice is added to the series.
172 172 */
173 173 qreal QPieSlice::endAngle() const
174 174 {
175 175 return d->m_startAngle + d->m_angleSpan;
176 176 }
177 177
178 178 /*!
179 179 Returns the pen used to draw this slice.
180 180 \sa setPen()
181 181 */
182 182 QPen QPieSlice::pen() const
183 183 {
184 184 return d->m_slicePen;
185 185 }
186 186
187 187 /*!
188 188 Returns the brush used to draw this slice.
189 189 \sa setBrush()
190 190 */
191 191 QBrush QPieSlice::brush() const
192 192 {
193 193 return d->m_sliceBrush;
194 194 }
195 195
196 196 /*!
197 197 Returns the pen used to draw the label in this slice.
198 198 \sa setLabelPen()
199 199 */
200 200 QPen QPieSlice::labelPen() const
201 201 {
202 202 return d->m_labelPen;
203 203 }
204 204
205 205 /*!
206 206 Returns the font used to draw label in this slice.
207 207 \sa setLabelFont()
208 208 */
209 209 QFont QPieSlice::labelFont() const
210 210 {
211 211 return d->m_labelFont;
212 212 }
213 213
214 214 /*!
215 215 Gets the label arm length factor.
216 216
217 217 The factor is relative to pie radius. For example:
218 218 1.0 means the length is the same as the radius.
219 219 0.5 means the length is half of the radius.
220 220
221 221 Default value is 0.15
222 222
223 223 \sa setLabelArmLengthFactor()
224 224 */
225 225 qreal QPieSlice::labelArmLengthFactor() const
226 226 {
227 227 return d->m_labelArmLengthFactor;
228 228 }
229 229
230 230 /*!
231 231 \fn void QPieSlice::clicked()
232 232
233 233 This signal is emitted when user has clicked the slice.
234 234
235 235 \sa QPieSeries::clicked()
236 236 */
237 237
238 238 /*!
239 239 \fn void QPieSlice::hovered(bool state)
240 240
241 241 This signal is emitted when user has hovered over or away from the slice.
242 242
243 243 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
244 244
245 245 \sa QPieSeries::hovered()
246 246 */
247 247
248 248 /*!
249 249 \fn void QPieSlice::changed()
250 250
251 251 This signal emitted when something has changed in the slice.
252 252 */
253 253
254 254 /*!
255 255 Sets the \a value of this slice.
256 256 \sa value()
257 257 */
258 258 void QPieSlice::setValue(qreal value)
259 259 {
260 260 if (!qFuzzyIsNull(d->m_value - value)) {
261 261 d->m_value = value;
262 262 emit changed();
263 263 }
264 264 }
265 265
266 266 /*!
267 267 Sets the \a label of the slice.
268 268 \sa label()
269 269 */
270 270 void QPieSlice::setLabel(QString label)
271 271 {
272 272 if (d->m_labelText != label) {
273 273 d->m_labelText = label;
274 274
275 275 emit changed();
276 276 }
277 277 }
278 278
279 279 /*!
280 280 Sets the label \a visible in this slice.
281 281 \sa isLabelVisible(), QPieSeries::setLabelsVisible()
282 282 */
283 283 void QPieSlice::setLabelVisible(bool visible)
284 284 {
285 285 if (d->m_isLabelVisible != visible) {
286 286 d->m_isLabelVisible = visible;
287 287 emit changed();
288 288 }
289 289 }
290 290
291 291 /*!
292 292 Sets this slices \a exploded state.
293 293
294 294 If the slice is exploded it is moved away from the pie center. The distance is defined by the explode distance factor.
295 295
296 296 \sa isExploded(), explodeDistanceFactor(), setExplodeDistanceFactor()
297 297 */
298 298 void QPieSlice::setExploded(bool exploded)
299 299 {
300 300 if (d->m_isExploded != exploded) {
301 301 d->m_isExploded = exploded;
302 302 emit changed();
303 303 }
304 304 }
305 305
306 306 /*!
307 307 Sets the explode distance \a factor.
308 308
309 309 The factor is relative to pie radius. For example:
310 310 1.0 means the distance is the same as the radius.
311 311 0.5 means the distance is half of the radius.
312 312
313 313 Default value is 0.15
314 314
315 315 \sa explodeDistanceFactor(), isExploded(), setExploded()
316 316 */
317 317 void QPieSlice::setExplodeDistanceFactor(qreal factor)
318 318 {
319 319 if (!qFuzzyIsNull(d->m_explodeDistanceFactor - factor)) {
320 320 d->m_explodeDistanceFactor = factor;
321 321 emit changed();
322 322 }
323 323 }
324 324
325 325 /*!
326 326 Sets the \a pen used to draw this slice.
327 327
328 328 Overrides the pen set by the theme.
329 329
330 330 \sa pen()
331 331 */
332 332 void QPieSlice::setPen(const QPen &pen)
333 333 {
334 334 if (d->m_slicePen != pen) {
335 335 d->m_slicePen = pen;
336 336 d->m_slicePen.setThemed(false);
337 337 emit changed();
338 338 }
339 339 }
340 340
341 341 /*!
342 342 Sets the \a brush used to draw this slice.
343 343
344 344 Overrides the brush set by the theme.
345 345
346 346 \sa brush()
347 347 */
348 348 void QPieSlice::setBrush(const QBrush &brush)
349 349 {
350 350 if (d->m_sliceBrush != brush) {
351 351 d->m_sliceBrush = brush;
352 352 d->m_sliceBrush.setThemed(false);
353 353 emit changed();
354 354 }
355 355 }
356 356
357 357 /*!
358 358 Sets the \a pen used to draw the label in this slice.
359 359
360 360 Overrides the pen set by the theme.
361 361
362 362 \sa labelPen()
363 363 */
364 364 void QPieSlice::setLabelPen(const QPen &pen)
365 365 {
366 366 if (d->m_labelPen != pen) {
367 367 d->m_labelPen = pen;
368 368 d->m_labelPen.setThemed(false);
369 369 emit changed();
370 370 }
371 371 }
372 372
373 373 /*!
374 374 Sets the \a font used to draw the label in this slice.
375 375
376 376 Overrides the font set by the theme.
377 377
378 378 \sa labelFont()
379 379 */
380 380 void QPieSlice::setLabelFont(const QFont &font)
381 381 {
382 382 if (d->m_labelFont != font) {
383 383 d->m_labelFont = font;
384 384 d->m_labelFont.setThemed(false);
385 385 emit changed();
386 386 }
387 387 }
388 388
389 389 /*!
390 390 Sets the label arm length \a factor.
391 391
392 392 The factor is relative to pie radius. For example:
393 393 1.0 means the length is the same as the radius.
394 394 0.5 means the length is half of the radius.
395 395
396 396 Default value is 0.15
397 397
398 398 \sa labelArmLengthFactor()
399 399 */
400 400 void QPieSlice::setLabelArmLengthFactor(qreal factor)
401 401 {
402 402 if (!qFuzzyIsNull(d->m_labelArmLengthFactor - factor)) {
403 403 d->m_labelArmLengthFactor = factor;
404 404 emit changed();
405 405 }
406 406 }
407 407
408 408 QTCOMMERCIALCHART_END_NAMESPACE
409 409
410 410 QTCOMMERCIALCHART_USE_NAMESPACE
411 411 #include "moc_qpieslice.cpp"
@@ -1,85 +1,85
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #ifndef QPIESLICE_H
22 22 #define QPIESLICE_H
23 23
24 24 #include <qchartglobal.h>
25 25 #include <QObject>
26 26 #include <QPen>
27 27 #include <QBrush>
28 28 #include <QFont>
29 29
30 30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 31 class PieSliceData;
32 32
33 33 class QTCOMMERCIALCHART_EXPORT QPieSlice : public QObject
34 34 {
35 35 Q_OBJECT
36 36 Q_PROPERTY(QString label READ label WRITE setLabel)
37 37 Q_PROPERTY(qreal value READ value WRITE setValue)
38 38 Q_PROPERTY(bool exploded READ isExploded WRITE setExploded)
39 39
40 40 public:
41 41 explicit QPieSlice(QObject *parent = 0);
42 QPieSlice(qreal value, QString label, QObject *parent = 0);
42 QPieSlice(QString label, qreal value, QObject *parent = 0);
43 43 virtual ~QPieSlice();
44 44
45 45 void setValue(qreal value);
46 46 qreal value() const;
47 47 void setLabel(QString label);
48 48 QString label() const;
49 49 void setLabelVisible(bool visible = true);
50 50 bool isLabelVisible() const;
51 51 void setExploded(bool exploded = true);
52 52 bool isExploded() const;
53 53
54 54 void setPen(const QPen &pen);
55 55 QPen pen() const;
56 56 void setBrush(const QBrush &brush);
57 57 QBrush brush() const;
58 58 void setLabelPen(const QPen &pen);
59 59 QPen labelPen() const;
60 60 void setLabelFont(const QFont &font);
61 61 QFont labelFont() const;
62 62
63 63 void setLabelArmLengthFactor(qreal factor);
64 64 qreal labelArmLengthFactor() const;
65 65 void setExplodeDistanceFactor(qreal factor);
66 66 qreal explodeDistanceFactor() const;
67 67
68 68 qreal percentage() const;
69 69 qreal startAngle() const;
70 70 qreal endAngle() const;
71 71
72 72 Q_SIGNALS:
73 73 void clicked();
74 74 void hovered(bool state);
75 75 void changed();
76 76
77 77 private:
78 78 friend class PieSliceData;
79 79 PieSliceData * const d;
80 80 Q_DISABLE_COPY(QPieSlice)
81 81 };
82 82
83 83 QTCOMMERCIALCHART_END_NAMESPACE
84 84
85 85 #endif // QPIESLICE_H
@@ -1,484 +1,484
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include <QtTest/QtTest>
22 22 #include <qchartview.h>
23 23 #include <qchart.h>
24 24 #include <qpieseries.h>
25 25 #include <qpieslice.h>
26 26 #include <qpiemodelmapper.h>
27 27 #include <QStandardItemModel>
28 28 #include <tst_definitions.h>
29 29
30 30 QTCOMMERCIALCHART_USE_NAMESPACE
31 31
32 32 Q_DECLARE_METATYPE(QPieSlice*)
33 33
34 34 class tst_qpieseries : public QObject
35 35 {
36 36 Q_OBJECT
37 37
38 38 public slots:
39 39 void initTestCase();
40 40 void cleanupTestCase();
41 41 void init();
42 42 void cleanup();
43 43
44 44 private slots:
45 45 void construction();
46 46 void append();
47 47 void insert();
48 48 void remove();
49 49 void calculatedValues();
50 50 void clickedSignal();
51 51 void hoverSignal();
52 52 void model();
53 53 void modelCustomMap();
54 54 void modelUpdate();
55 55
56 56 private:
57 57 void verifyCalculatedData(const QPieSeries &series, bool *ok);
58 58
59 59 private:
60 60
61 61 };
62 62
63 63 void tst_qpieseries::initTestCase()
64 64 {
65 65 qRegisterMetaType<QPieSlice*>("QPieSlice*");
66 66 }
67 67
68 68 void tst_qpieseries::cleanupTestCase()
69 69 {
70 70 }
71 71
72 72 void tst_qpieseries::init()
73 73 {
74 74
75 75 }
76 76
77 77 void tst_qpieseries::cleanup()
78 78 {
79 79
80 80 }
81 81
82 82 void tst_qpieseries::construction()
83 83 {
84 84 // verify default values
85 85 QPieSeries s;
86 86 QVERIFY(s.type() == QAbstractSeries::SeriesTypePie);
87 87 QVERIFY(s.count() == 0);
88 88 QVERIFY(s.isEmpty());
89 89 QCOMPARE(s.sum(), 0.0);
90 90 QCOMPARE(s.horizontalPosition(), 0.5);
91 91 QCOMPARE(s.verticalPosition(), 0.5);
92 92 QCOMPARE(s.pieSize(), 0.7);
93 93 QCOMPARE(s.pieStartAngle(), 0.0);
94 94 QCOMPARE(s.pieEndAngle(), 360.0);
95 95 }
96 96
97 97 void tst_qpieseries::append()
98 98 {
99 99 QPieSeries s;
100 100
101 101 // append pointer
102 102 QPieSlice *slice1 = 0;
103 103 QVERIFY(!s.append(slice1));
104 slice1 = new QPieSlice(1, "slice 1");
104 slice1 = new QPieSlice("slice 1", 1);
105 105 QVERIFY(s.append(slice1));
106 106 QVERIFY(!s.append(slice1));
107 107 QCOMPARE(s.count(), 1);
108 108
109 109 // append pointer list
110 110 QList<QPieSlice *> list;
111 111 QVERIFY(!s.append(list));
112 112 list << (QPieSlice *) 0;
113 113 QVERIFY(!s.append(list));
114 114 list.clear();
115 list << new QPieSlice(2, "slice 2");
116 list << new QPieSlice(3, "slice 3");
115 list << new QPieSlice("slice 2", 2);
116 list << new QPieSlice("slice 3", 3);
117 117 QVERIFY(s.append(list));
118 118 QVERIFY(!s.append(list));
119 119 QCOMPARE(s.count(), 3);
120 120
121 121 // append operator
122 s << new QPieSlice(4, "slice 4");
122 s << new QPieSlice("slice 4", 4);
123 123 s << slice1; // fails because already added
124 124 QCOMPARE(s.count(), 4);
125 125
126 126 // append with params
127 QPieSlice *slice5 = s.append(5, "slice 5");
127 QPieSlice *slice5 = s.append("slice 5", 5);
128 128 QVERIFY(slice5 != 0);
129 129 QCOMPARE(slice5->value(), 5.0);
130 130 QCOMPARE(slice5->label(), QString("slice 5"));
131 131 QCOMPARE(s.count(), 5);
132 132
133 133 // check slices
134 134 QVERIFY(!s.isEmpty());
135 135 for (int i=0; i<s.count(); i++) {
136 136 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
137 137 QCOMPARE(s.slices().at(i)->label(), QString("slice ") + QString::number(i+1));
138 138 }
139 139 }
140 140
141 141 void tst_qpieseries::insert()
142 142 {
143 143 QPieSeries s;
144 144
145 145 // insert one slice
146 146 QPieSlice *slice1 = 0;
147 147 QVERIFY(!s.insert(0, slice1));
148 slice1 = new QPieSlice(1, "slice 1");
148 slice1 = new QPieSlice("slice 1", 1);
149 149 QVERIFY(!s.insert(-1, slice1));
150 150 QVERIFY(!s.insert(5, slice1));
151 151 QVERIFY(s.insert(0, slice1));
152 152 QVERIFY(!s.insert(0, slice1));
153 153 QCOMPARE(s.count(), 1);
154 154
155 155 // add some more slices
156 s.append(2, "slice 2");
157 s.append(4, "slice 4");
156 s.append("slice 2", 2);
157 s.append("slice 4", 4);
158 158 QCOMPARE(s.count(), 3);
159 159
160 160 // insert between slices
161 s.insert(2, new QPieSlice(3, "slice 3"));
161 s.insert(2, new QPieSlice("slice 3", 3));
162 162 QCOMPARE(s.count(), 4);
163 163
164 164 // check slices
165 165 for (int i=0; i<s.count(); i++) {
166 166 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
167 167 QCOMPARE(s.slices().at(i)->label(), QString("slice ") + QString::number(i+1));
168 168 }
169 169 }
170 170
171 171 void tst_qpieseries::remove()
172 172 {
173 173 QPieSeries s;
174 174
175 175 // add some slices
176 QPieSlice *slice1 = s.append(1, "slice 1");
177 QPieSlice *slice2 = s.append(2, "slice 2");
178 QPieSlice *slice3 = s.append(3, "slice 3");
176 QPieSlice *slice1 = s.append("slice 1", 1);
177 QPieSlice *slice2 = s.append("slice 2", 2);
178 QPieSlice *slice3 = s.append("slice 3", 3);
179 179 QSignalSpy spy1(slice1, SIGNAL(destroyed()));
180 180 QSignalSpy spy2(slice2, SIGNAL(destroyed()));
181 181 QSignalSpy spy3(slice3, SIGNAL(destroyed()));
182 182 QCOMPARE(s.count(), 3);
183 183
184 184 // null pointer remove
185 185 QVERIFY(!s.remove(0));
186 186
187 187 // remove first
188 188 QVERIFY(s.remove(slice1));
189 189 QVERIFY(!s.remove(slice1));
190 190 QCOMPARE(s.count(), 2);
191 191 QCOMPARE(s.slices().at(0)->label(), slice2->label());
192 192
193 193 // remove all
194 194 s.clear();
195 195 QVERIFY(s.isEmpty());
196 196 QVERIFY(s.slices().isEmpty());
197 197 QCOMPARE(s.count(), 0);
198 198
199 199 // check that slices were actually destroyed
200 200 TRY_COMPARE(spy1.count(), 1);
201 201 TRY_COMPARE(spy2.count(), 1);
202 202 TRY_COMPARE(spy3.count(), 1);
203 203 }
204 204
205 205 void tst_qpieseries::calculatedValues()
206 206 {
207 207 bool ok;
208 208 QPieSeries s;
209 209
210 210 // add a slice
211 QPieSlice *slice1 = s.append(1, "slice 1");
211 QPieSlice *slice1 = s.append("slice 1", 1);
212 212 verifyCalculatedData(s, &ok);
213 213 if (!ok)
214 214 return;
215 215
216 216 // add some more slices
217 217 QList<QPieSlice *> list;
218 list << new QPieSlice(2, "slice 2");
219 list << new QPieSlice(3, "slice 3");
218 list << new QPieSlice("slice 2", 2);
219 list << new QPieSlice("slice 3", 3);
220 220 s.append(list);
221 221 verifyCalculatedData(s, &ok);
222 222 if (!ok)
223 223 return;
224 224
225 225 // remove a slice
226 226 s.remove(slice1);
227 227 verifyCalculatedData(s, &ok);
228 228 if (!ok)
229 229 return;
230 230
231 231 // insert a slice
232 s.insert(0, new QPieSlice(1, "Slice 4"));
232 s.insert(0, new QPieSlice("Slice 4", 4));
233 233 verifyCalculatedData(s, &ok);
234 234 if (!ok)
235 235 return;
236 236
237 237 // clear all
238 238 s.clear();
239 239 verifyCalculatedData(s, &ok);
240 240 }
241 241
242 242 void tst_qpieseries::verifyCalculatedData(const QPieSeries &series, bool *ok)
243 243 {
244 244 *ok = false;
245 245
246 246 qreal sum = 0;
247 247 foreach (const QPieSlice *slice, series.slices())
248 248 sum += slice->value();
249 249 QCOMPARE(series.sum(), sum);
250 250
251 251 qreal startAngle = series.pieStartAngle();
252 252 qreal pieAngleSpan = series.pieEndAngle() - series.pieStartAngle();
253 253 foreach (const QPieSlice *slice, series.slices()) {
254 254 qreal ratio = slice->value() / sum;
255 255 qreal sliceSpan = pieAngleSpan * ratio;
256 256 QCOMPARE(slice->startAngle(), startAngle);
257 257 QCOMPARE(slice->endAngle(), startAngle + sliceSpan);
258 258 QCOMPARE(slice->percentage(), ratio);
259 259 startAngle += sliceSpan;
260 260 }
261 261
262 262 if (!series.isEmpty())
263 263 QCOMPARE(series.slices().last()->endAngle(), series.pieEndAngle());
264 264
265 265 *ok = true;
266 266 }
267 267
268 268
269 269 void tst_qpieseries::clickedSignal()
270 270 {
271 271 // create a pie series
272 272 QPieSeries *series = new QPieSeries();
273 273 series->setPieSize(1.0);
274 QPieSlice *s1 = series->append(1, "slice 1");
275 series->append(2, "slice 2");
276 series->append(3, "slice 3");
274 QPieSlice *s1 = series->append("slice 1", 1);
275 series->append("slice 2", 2);
276 series->append("slice 3", 3);
277 277 QSignalSpy clickSpy1(series, SIGNAL(clicked(QPieSlice*)));
278 278
279 279 // add series to the chart
280 280 QChartView view(new QChart());
281 281 view.chart()->legend()->setVisible(false);
282 282 view.resize(200, 200);
283 283 view.chart()->addSeries(series);
284 284 view.show();
285 285 QTest::qWaitForWindowShown(&view);
286 286
287 287 // simulate clicks
288 288 // pie rectangle: QRectF(60,60 121x121)
289 289 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(146, 90)); // inside slice 1
290 290 TRY_COMPARE(clickSpy1.count(), 1);
291 291 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy1.at(0).at(0)), s1);
292 292 }
293 293
294 294 void tst_qpieseries::hoverSignal()
295 295 {
296 296 // create a pie series
297 297 QPieSeries *series = new QPieSeries();
298 298 series->setPieSize(1.0);
299 QPieSlice *s1 = series->append(1, "slice 1");
300 series->append(2, "slice 2");
301 series->append(3, "slice 3");
299 QPieSlice *s1 = series->append("slice 1", 1);
300 series->append("slice 2", 2);
301 series->append("slice 3", 3);
302 302
303 303 // add series to the chart
304 304 QChartView view(new QChart());
305 305 view.chart()->legend()->setVisible(false);
306 306 view.resize(200, 200);
307 307 view.chart()->addSeries(series);
308 308 view.show();
309 309 QTest::qWaitForWindowShown(&view);
310 310
311 311 // first move to right top corner
312 312 QTest::mouseMove(view.viewport(), QPoint(200, 0));
313 313 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
314 314
315 315 // move inside the slice
316 316 // pie rectangle: QRectF(60,60 121x121)
317 317 QSignalSpy hoverSpy(series, SIGNAL(hovered(QPieSlice*,bool)));
318 318 QTest::mouseMove(view.viewport(), QPoint(139, 85));
319 319 TRY_COMPARE(hoverSpy.count(), 1);
320 320 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(0).at(0)), s1);
321 321 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(0).at(1)), true);
322 322
323 323 // move outside the slice
324 324 QTest::mouseMove(view.viewport(), QPoint(200, 0));
325 325 TRY_COMPARE(hoverSpy.count(), 2);
326 326 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(1).at(0)), s1);
327 327 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(1).at(1)), false);
328 328 }
329 329
330 330 void tst_qpieseries::model()
331 331 {
332 332 QSKIP("Needs to be checked again. Model implementation changed", SkipAll);
333 333
334 334 QPieSeries *series = new QPieSeries;
335 335 QChart *chart = new QChart;
336 336 chart->addSeries(series);
337 337 QChartView *chartView = new QChartView(chart);
338 338 chartView->show();
339 339
340 340 QStandardItemModel *stdModel = new QStandardItemModel(0, 2);
341 341 series->setModel(stdModel);
342 342
343 343 int rowCount = 3;
344 344 for (int row = 0; row < rowCount; ++row) {
345 345 for (int column = 0; column < 2; column++) {
346 346 QStandardItem *item = new QStandardItem(row * column);
347 347 stdModel->setItem(row, column, item);
348 348 }
349 349 }
350 350
351 351 // data has been added to the model, but mapper is not set the number of slices should still be 0
352 352 QVERIFY2(series->slices().count() == 0, "Mapper has not been set, so the number of slices should be 0");
353 353
354 354 // set the mapper
355 355 QPieModelMapper *mapper = series->modelMapper();//new QPieModelMapper;
356 356 mapper->setMapValues(0);
357 357 mapper->setMapLabels(0);
358 358 // series->setModelMapper(mapper); // this should cause the Pie to get initialized from the model, since there is now both the model and the mapper defined
359 359 QCOMPARE(series->slices().count(), rowCount);
360 360
361 361 // set the mappings to be outside of the model
362 362 mapper->setMapLabels(5);
363 363 mapper->setMapValues(4);
364 364 QCOMPARE(series->slices().count(), 0); // Mappings are invalid, so the number of slices should be 0
365 365
366 366 // set back to correct ones
367 367 mapper->setMapValues(0);
368 368 mapper->setMapLabels(0);
369 369 QCOMPARE(series->slices().count(), rowCount);
370 370
371 371 // reset the mappings
372 372 mapper->reset();
373 373 QCOMPARE(series->slices().count(), 0); // Mappings have been reset and are invalid, so the number of slices should be 0
374 374
375 375 // unset the model and the mapper
376 376 series->setModel(0);
377 377 // series->setModelMapper(0);
378 378 QVERIFY(series->model() == 0); // Model should be unset
379 379 // QVERIFY(series->modelMapper() == 0); // Model mapper should be unset
380 380 }
381 381
382 382 void tst_qpieseries::modelCustomMap()
383 383 {
384 384 QSKIP("Needs to be checked again. Model implementation changed", SkipAll);
385 385
386 386 int rowCount = 12;
387 387 int columnCount = 3;
388 388 QStandardItemModel *stdModel = new QStandardItemModel(0, 3);
389 389 for (int row = 0; row < rowCount; ++row) {
390 390 for (int column = 0; column < 2; column++) {
391 391 QStandardItem *item = new QStandardItem(row * column);
392 392 stdModel->setItem(row, column, item);
393 393 }
394 394 }
395 395
396 396 QPieSeries *series = new QPieSeries;
397 397 QChart *chart = new QChart;
398 398 chart->addSeries(series);
399 399 QChartView *chartView = new QChartView(chart);
400 400 chartView->show();
401 401 series->setModel(stdModel);
402 402
403 403 QPieModelMapper *mapper = series->modelMapper();//new QPieModelMapper;
404 404 mapper->setMapValues(0);
405 405 mapper->setMapLabels(0);
406 406 // series->setModelMapper(mapper);
407 407 QCOMPARE(series->slices().count(), rowCount);
408 408
409 409 // lets change the orientation to horizontal
410 410 mapper->setOrientation(Qt::Horizontal);
411 411 QCOMPARE(series->slices().count(), columnCount);
412 412
413 413 // change it back to vertical
414 414 mapper->setOrientation(Qt::Vertical);
415 415 QCOMPARE(series->slices().count(), rowCount);
416 416
417 417 // lets customize the mapping
418 418 int first = 3;
419 419 mapper->setFirst(first);
420 420 QCOMPARE(series->slices().count(), rowCount - first);
421 421 int count = 7;
422 422 mapper->setCount(count);
423 423 QCOMPARE(series->slices().count(), count);
424 424 first = 9;
425 425 mapper->setFirst(first);
426 426 QCOMPARE(series->slices().count(), qMin(count, rowCount - first));
427 427 }
428 428
429 429 void tst_qpieseries::modelUpdate()
430 430 {
431 431 QSKIP("Needs to be checked again. Model implementation changed", SkipAll);
432 432
433 433 int rowCount = 12;
434 434 int columnCount = 7;
435 435 QStandardItemModel *stdModel = new QStandardItemModel(rowCount, columnCount);
436 436 for (int row = 0; row < rowCount; ++row) {
437 437 for (int column = 0; column < columnCount; column++) {
438 438 QStandardItem *item = new QStandardItem(row * column);
439 439 stdModel->setItem(row, column, item);
440 440 }
441 441 }
442 442
443 443 QPieSeries *series = new QPieSeries;
444 444 QChart *chart = new QChart;
445 445 chart->addSeries(series);
446 446 QChartView *chartView = new QChartView(chart);
447 447 chartView->show();
448 448 series->setModel(stdModel);
449 449
450 450 QPieModelMapper *mapper = series->modelMapper();//new QPieModelMapper;
451 451 mapper->setMapValues(0);
452 452 mapper->setMapLabels(0);
453 453 // series->setModelMapper(mapper);
454 454
455 455 stdModel->insertRows(3, 5);
456 456 QCOMPARE(series->slices().count(), rowCount + 5);
457 457
458 458 stdModel->removeRows(10, 5);
459 459 QCOMPARE(series->slices().count(), rowCount);
460 460
461 461 // limit the number of slices taken from the model to 12
462 462 mapper->setCount(rowCount);
463 463 stdModel->insertRows(3, 5);
464 464 QCOMPARE(series->slices().count(), rowCount);
465 465
466 466 stdModel->removeRows(0, 10);
467 467 QCOMPARE(series->slices().count(), rowCount - 5);
468 468
469 469 // change the orientation to horizontal
470 470 mapper->setOrientation(Qt::Horizontal);
471 471 QCOMPARE(series->slices().count(), columnCount);
472 472
473 473 stdModel->insertColumns(3, 10);
474 474 QCOMPARE(series->slices().count(), rowCount); // count is limited to rowCount (12)
475 475
476 476 stdModel->removeColumns(5, 10);
477 477 QCOMPARE(series->slices().count(), columnCount);
478 478
479 479 }
480 480
481 481 QTEST_MAIN(tst_qpieseries)
482 482
483 483 #include "tst_qpieseries.moc"
484 484
@@ -1,270 +1,270
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include <QtTest/QtTest>
22 22 #include <tst_definitions.h>
23 23 #include <qchartview.h>
24 24 #include <qchart.h>
25 25 #include <qpieslice.h>
26 26 #include <qpieseries.h>
27 27
28 28 QTCOMMERCIALCHART_USE_NAMESPACE
29 29
30 30 class tst_qpieslice : public QObject
31 31 {
32 32 Q_OBJECT
33 33
34 34 public slots:
35 35 void initTestCase();
36 36 void cleanupTestCase();
37 37 void init();
38 38 void cleanup();
39 39
40 40 private slots:
41 41 void construction();
42 42 void changedSignals();
43 43 void customize();
44 44 void mouseClick();
45 45 void mouseHover();
46 46
47 47 private:
48 48
49 49
50 50 private:
51 51
52 52 };
53 53
54 54 void tst_qpieslice::initTestCase()
55 55 {
56 56 }
57 57
58 58 void tst_qpieslice::cleanupTestCase()
59 59 {
60 60 }
61 61
62 62 void tst_qpieslice::init()
63 63 {
64 64
65 65 }
66 66
67 67 void tst_qpieslice::cleanup()
68 68 {
69 69
70 70 }
71 71
72 72 void tst_qpieslice::construction()
73 73 {
74 74 // no params
75 75 QPieSlice slice1;
76 76 QCOMPARE(slice1.value(), 0.0);
77 77 QVERIFY(slice1.label().isEmpty());
78 78 QVERIFY(!slice1.isLabelVisible());
79 79 QVERIFY(!slice1.isExploded());
80 80 QCOMPARE(slice1.pen(), QPen());
81 81 QCOMPARE(slice1.brush(), QBrush());
82 82 QCOMPARE(slice1.labelPen(), QPen());
83 83 QCOMPARE(slice1.labelFont(), QFont());
84 84 QCOMPARE(slice1.labelArmLengthFactor(), 0.15); // default value
85 85 QCOMPARE(slice1.explodeDistanceFactor(), 0.15); // default value
86 86 QCOMPARE(slice1.percentage(), 0.0);
87 87 QCOMPARE(slice1.startAngle(), 0.0);
88 88 QCOMPARE(slice1.endAngle(), 0.0);
89 89
90 90 // value and label params
91 QPieSlice slice2(1.0, "foobar");
91 QPieSlice slice2("foobar", 1.0);
92 92 QCOMPARE(slice2.value(), 1.0);
93 93 QCOMPARE(slice2.label(), QString("foobar"));
94 94 QVERIFY(!slice2.isLabelVisible());
95 95 QVERIFY(!slice2.isExploded());
96 96 QCOMPARE(slice2.pen(), QPen());
97 97 QCOMPARE(slice2.brush(), QBrush());
98 98 QCOMPARE(slice2.labelPen(), QPen());
99 99 QCOMPARE(slice2.labelFont(), QFont());
100 100 QCOMPARE(slice2.labelArmLengthFactor(), 0.15); // default value
101 101 QCOMPARE(slice2.explodeDistanceFactor(), 0.15); // default value
102 102 QCOMPARE(slice2.percentage(), 0.0);
103 103 QCOMPARE(slice2.startAngle(), 0.0);
104 104 QCOMPARE(slice2.endAngle(), 0.0);
105 105 }
106 106
107 107 void tst_qpieslice::changedSignals()
108 108 {
109 109 // set everything twice to see we do not get unnecessary signals
110 110 QPieSlice slice;
111 111 QSignalSpy spy(&slice, SIGNAL(changed())); // TODO: this will be changed to something more refined
112 112 slice.setValue(1);
113 113 slice.setValue(1);
114 114 slice.setLabel("foobar");
115 115 slice.setLabel("foobar");
116 116 slice.setLabelVisible();
117 117 slice.setLabelVisible();
118 118 slice.setExploded();
119 119 slice.setExploded();
120 120 slice.setPen(QPen(Qt::red));
121 121 slice.setPen(QPen(Qt::red));
122 122 slice.setBrush(QBrush(Qt::red));
123 123 slice.setBrush(QBrush(Qt::red));
124 124 slice.setLabelPen(QPen(Qt::green));
125 125 slice.setLabelPen(QPen(Qt::green));
126 126 slice.setLabelFont(QFont("Tahoma"));
127 127 slice.setLabelFont(QFont("Tahoma"));
128 128 slice.setLabelArmLengthFactor(0.1);
129 129 slice.setLabelArmLengthFactor(0.1);
130 130 slice.setExplodeDistanceFactor(0.1);
131 131 slice.setExplodeDistanceFactor(0.1);
132 132 TRY_COMPARE(spy.count(), 10);
133 133 }
134 134
135 135 void tst_qpieslice::customize()
136 136 {
137 137 // create a pie series
138 138 QPieSeries *series = new QPieSeries();
139 QPieSlice *s1 = series->append(1, "slice 1");
140 QPieSlice *s2 = series->append(2, "slice 2");
141 series->append(3, "slice 3");
139 QPieSlice *s1 = series->append("slice 1", 1);
140 QPieSlice *s2 = series->append("slice 2", 2);
141 series->append("slice 3", 3);
142 142
143 143 // customize a slice
144 144 QPen p1(Qt::red);
145 145 s1->setPen(p1);
146 146 QBrush b1(Qt::red);
147 147 s1->setBrush(b1);
148 148 s1->setLabelPen(p1);
149 149 QFont f1("Consolas");
150 150 s1->setLabelFont(f1);
151 151
152 152 // add series to the chart
153 153 QChartView view(new QChart());
154 154 view.resize(200, 200);
155 155 view.chart()->addSeries(series);
156 156 view.show();
157 157 QTest::qWaitForWindowShown(&view);
158 158 //QTest::qWait(1000);
159 159
160 160 // check that customizations persist
161 161 QCOMPARE(s1->pen(), p1);
162 162 QCOMPARE(s1->brush(), b1);
163 163 QCOMPARE(s1->labelPen(), p1);
164 164 QCOMPARE(s1->labelFont(), f1);
165 165
166 166 // remove a slice
167 167 series->remove(s2);
168 168 QCOMPARE(s1->pen(), p1);
169 169 QCOMPARE(s1->brush(), b1);
170 170 QCOMPARE(s1->labelPen(), p1);
171 171 QCOMPARE(s1->labelFont(), f1);
172 172
173 173 // add a slice
174 series->append(4, "slice 4");
174 series->append("slice 4", 4);
175 175 QCOMPARE(s1->pen(), p1);
176 176 QCOMPARE(s1->brush(), b1);
177 177 QCOMPARE(s1->labelPen(), p1);
178 178 QCOMPARE(s1->labelFont(), f1);
179 179
180 180 // insert a slice
181 series->insert(0, new QPieSlice(5, "slice 5"));
181 series->insert(0, new QPieSlice("slice 5", 5));
182 182 QCOMPARE(s1->pen(), p1);
183 183 QCOMPARE(s1->brush(), b1);
184 184 QCOMPARE(s1->labelPen(), p1);
185 185 QCOMPARE(s1->labelFont(), f1);
186 186
187 187 // change theme
188 188 // theme will overwrite customizations
189 189 view.chart()->setTheme(QChart::ChartThemeHighContrast);
190 190 QVERIFY(s1->pen() != p1);
191 191 QVERIFY(s1->brush() != b1);
192 192 QVERIFY(s1->labelPen() != p1);
193 193 QVERIFY(s1->labelFont() != f1);
194 194 }
195 195
196 196 void tst_qpieslice::mouseClick()
197 197 {
198 198 // create a pie series
199 199 QPieSeries *series = new QPieSeries();
200 200 series->setPieSize(1.0);
201 QPieSlice *s1 = series->append(1, "slice 1");
202 QPieSlice *s2 = series->append(2, "slice 2");
203 QPieSlice *s3 = series->append(3, "slice 3");
201 QPieSlice *s1 = series->append("slice 1", 1);
202 QPieSlice *s2 = series->append("slice 2", 2);
203 QPieSlice *s3 = series->append("slice 3", 3);
204 204 QSignalSpy clickSpy1(s1, SIGNAL(clicked()));
205 205 QSignalSpy clickSpy2(s2, SIGNAL(clicked()));
206 206 QSignalSpy clickSpy3(s3, SIGNAL(clicked()));
207 207
208 208 // add series to the chart
209 209 QChartView view(new QChart());
210 210 view.chart()->legend()->setVisible(false);
211 211 view.resize(200, 200);
212 212 view.chart()->addSeries(series);
213 213 view.show();
214 214 QTest::qWaitForWindowShown(&view);
215 215
216 216 // simulate clicks
217 217 // pie rectangle: QRectF(60,60 121x121)
218 218 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(139, 85)); // inside slice 1
219 219 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(146, 136)); // inside slice 2
220 220 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(91, 119)); // inside slice 3
221 221 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(70, 70)); // inside pie rectangle but not inside a slice
222 222 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(170, 170)); // inside pie rectangle but not inside a slice
223 223 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
224 224 QCOMPARE(clickSpy1.count(), 1);
225 225 QCOMPARE(clickSpy2.count(), 1);
226 226 QCOMPARE(clickSpy3.count(), 1);
227 227 }
228 228
229 229 void tst_qpieslice::mouseHover()
230 230 {
231 231 // create a pie series
232 232 QPieSeries *series = new QPieSeries();
233 233 series->setPieSize(1.0);
234 QPieSlice *s1 = series->append(1, "slice 1");
235 series->append(2, "slice 2");
236 series->append(3, "slice 3");
234 QPieSlice *s1 = series->append("slice 1", 1);
235 series->append("slice 2", 2);
236 series->append("slice 3", 3);
237 237
238 238 // add series to the chart
239 239 QChartView view(new QChart());
240 240 view.chart()->legend()->setVisible(false);
241 241 view.resize(200, 200);
242 242 view.chart()->addSeries(series);
243 243 view.show();
244 244 QTest::qWaitForWindowShown(&view);
245 245
246 246 // first move to right top corner
247 247 QTest::mouseMove(view.viewport(), QPoint(200, 0));
248 248 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
249 249
250 250 // move inside slice rectangle but NOT the actual slice
251 251 // pie rectangle: QRectF(60,60 121x121)
252 252 QSignalSpy hoverSpy(s1, SIGNAL(hovered(bool)));
253 253 QTest::mouseMove(view.viewport(), QPoint(170, 70));
254 254 TRY_COMPARE(hoverSpy.count(), 0);
255 255
256 256 // move inside the slice
257 257 QTest::mouseMove(view.viewport(), QPoint(139, 85));
258 258 TRY_COMPARE(hoverSpy.count(), 1);
259 259 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(0).at(0)), true);
260 260
261 261 // move outside the slice
262 262 QTest::mouseMove(view.viewport(), QPoint(200, 0));
263 263 TRY_COMPARE(hoverSpy.count(), 2);
264 264 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(1).at(0)), false);
265 265 }
266 266
267 267 QTEST_MAIN(tst_qpieslice)
268 268
269 269 #include "tst_qpieslice.moc"
270 270
@@ -1,349 +1,349
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "mainwidget.h"
22 22 #include "dataseriedialog.h"
23 23 #include "qchartview.h"
24 24 #include "qpieseries.h"
25 25 #include "qscatterseries.h"
26 26 #include "qlineseries.h"
27 27 #include <qareaseries.h>
28 28 #include <qsplineseries.h>
29 29 #include <qbarset.h>
30 30 #include <qbarseries.h>
31 31 #include <qstackedbarseries.h>
32 32 #include <qpercentbarseries.h>
33 33 #include <QPushButton>
34 34 #include <QComboBox>
35 35 #include <QSpinBox>
36 36 #include <QCheckBox>
37 37 #include <QGridLayout>
38 38 #include <QHBoxLayout>
39 39 #include <QLabel>
40 40 #include <QSpacerItem>
41 41 #include <QMessageBox>
42 42 #include <cmath>
43 43 #include <QDebug>
44 44 #include <QStandardItemModel>
45 45
46 46
47 47 QTCOMMERCIALCHART_USE_NAMESPACE
48 48
49 49 MainWidget::MainWidget(QWidget *parent) :
50 50 QWidget(parent),
51 51 m_addSerieDialog(0),
52 52 m_chart(0)
53 53 {
54 54 m_chart = new QChart();
55 55
56 56 // Grid layout for the controls for configuring the chart widget
57 57 QGridLayout *grid = new QGridLayout();
58 58 QPushButton *addSeriesButton = new QPushButton("Add series");
59 59 connect(addSeriesButton, SIGNAL(clicked()), this, SLOT(addSeries()));
60 60 grid->addWidget(addSeriesButton, 0, 1);
61 61 initBackroundCombo(grid);
62 62 initScaleControls(grid);
63 63 initThemeCombo(grid);
64 64 initCheckboxes(grid);
65 65
66 66 // add row with empty label to make all the other rows static
67 67 grid->addWidget(new QLabel(""), grid->rowCount(), 0);
68 68 grid->setRowStretch(grid->rowCount() - 1, 1);
69 69
70 70 // Create chart view with the chart
71 71 m_chartView = new QChartView(m_chart, this);
72 72 m_chartView->setRubberBand(QChartView::HorizonalRubberBand);
73 73
74 74 // Another grid layout as a main layout
75 75 QGridLayout *mainLayout = new QGridLayout();
76 76 mainLayout->addLayout(grid, 0, 0);
77 77 mainLayout->addWidget(m_chartView, 0, 1, 3, 1);
78 78 setLayout(mainLayout);
79 79 }
80 80
81 81 // Combo box for selecting the chart's background
82 82 void MainWidget::initBackroundCombo(QGridLayout *grid)
83 83 {
84 84 QComboBox *backgroundCombo = new QComboBox(this);
85 85 backgroundCombo->addItem("Color");
86 86 backgroundCombo->addItem("Gradient");
87 87 backgroundCombo->addItem("Image");
88 88 connect(backgroundCombo, SIGNAL(currentIndexChanged(int)),
89 89 this, SLOT(backgroundChanged(int)));
90 90
91 91 grid->addWidget(new QLabel("Background:"), grid->rowCount(), 0);
92 92 grid->addWidget(backgroundCombo, grid->rowCount() - 1, 1);
93 93 }
94 94
95 95 // Scale related controls (auto-scale vs. manual min-max values)
96 96 void MainWidget::initScaleControls(QGridLayout *grid)
97 97 {
98 98 m_autoScaleCheck = new QCheckBox("Automatic scaling");
99 99 connect(m_autoScaleCheck, SIGNAL(stateChanged(int)), this, SLOT(autoScaleChanged(int)));
100 100 // Allow setting also non-sense values (like -2147483648 and 2147483647)
101 101 m_xMinSpin = new QSpinBox();
102 102 m_xMinSpin->setMinimum(INT_MIN);
103 103 m_xMinSpin->setMaximum(INT_MAX);
104 104 m_xMinSpin->setValue(0);
105 105 connect(m_xMinSpin, SIGNAL(valueChanged(int)), this, SLOT(xMinChanged(int)));
106 106 m_xMaxSpin = new QSpinBox();
107 107 m_xMaxSpin->setMinimum(INT_MIN);
108 108 m_xMaxSpin->setMaximum(INT_MAX);
109 109 m_xMaxSpin->setValue(10);
110 110 connect(m_xMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(xMaxChanged(int)));
111 111 m_yMinSpin = new QSpinBox();
112 112 m_yMinSpin->setMinimum(INT_MIN);
113 113 m_yMinSpin->setMaximum(INT_MAX);
114 114 m_yMinSpin->setValue(0);
115 115 connect(m_yMinSpin, SIGNAL(valueChanged(int)), this, SLOT(yMinChanged(int)));
116 116 m_yMaxSpin = new QSpinBox();
117 117 m_yMaxSpin->setMinimum(INT_MIN);
118 118 m_yMaxSpin->setMaximum(INT_MAX);
119 119 m_yMaxSpin->setValue(10);
120 120 connect(m_yMaxSpin, SIGNAL(valueChanged(int)), this, SLOT(yMaxChanged(int)));
121 121
122 122 grid->addWidget(m_autoScaleCheck, grid->rowCount(), 0);
123 123 grid->addWidget(new QLabel("x min:"), grid->rowCount(), 0);
124 124 grid->addWidget(m_xMinSpin, grid->rowCount() - 1, 1);
125 125 grid->addWidget(new QLabel("x max:"), grid->rowCount(), 0);
126 126 grid->addWidget(m_xMaxSpin, grid->rowCount() - 1, 1);
127 127 grid->addWidget(new QLabel("y min:"), grid->rowCount(), 0);
128 128 grid->addWidget(m_yMinSpin, grid->rowCount() - 1, 1);
129 129 grid->addWidget(new QLabel("y max:"), grid->rowCount(), 0);
130 130 grid->addWidget(m_yMaxSpin, grid->rowCount() - 1, 1);
131 131
132 132 m_autoScaleCheck->setChecked(true);
133 133 }
134 134
135 135 // Combo box for selecting theme
136 136 void MainWidget::initThemeCombo(QGridLayout *grid)
137 137 {
138 138 QComboBox *chartTheme = new QComboBox();
139 139 chartTheme->addItem("Default");
140 140 chartTheme->addItem("Light");
141 141 chartTheme->addItem("Blue Cerulean");
142 142 chartTheme->addItem("Dark");
143 143 chartTheme->addItem("Brown Sand");
144 144 chartTheme->addItem("Blue NCS");
145 145 chartTheme->addItem("High Contrast");
146 146 chartTheme->addItem("Blue Icy");
147 147 connect(chartTheme, SIGNAL(currentIndexChanged(int)),
148 148 this, SLOT(changeChartTheme(int)));
149 149 grid->addWidget(new QLabel("Chart theme:"), 8, 0);
150 150 grid->addWidget(chartTheme, 8, 1);
151 151 }
152 152
153 153 // Different check boxes for customizing chart
154 154 void MainWidget::initCheckboxes(QGridLayout *grid)
155 155 {
156 156 // TODO: setZoomEnabled slot has been removed from QChartView -> Re-implement zoom on/off
157 157 QCheckBox *zoomCheckBox = new QCheckBox("Drag'n drop Zoom");
158 158 // connect(zoomCheckBox, SIGNAL(toggled(bool)), m_chartView, SLOT(setZoomEnabled(bool)));
159 159 zoomCheckBox->setChecked(true);
160 160 grid->addWidget(zoomCheckBox, grid->rowCount(), 0);
161 161
162 162 QCheckBox *aliasCheckBox = new QCheckBox("Anti-alias");
163 163 connect(aliasCheckBox, SIGNAL(toggled(bool)), this, SLOT(antiAliasToggled(bool)));
164 164 aliasCheckBox->setChecked(false);
165 165 grid->addWidget(aliasCheckBox, grid->rowCount(), 0);
166 166 }
167 167
168 168 void MainWidget::antiAliasToggled(bool enabled)
169 169 {
170 170 m_chartView->setRenderHint(QPainter::Antialiasing, enabled);
171 171 }
172 172
173 173 void MainWidget::addSeries()
174 174 {
175 175 if (!m_addSerieDialog) {
176 176 m_addSerieDialog = new DataSerieDialog(this);
177 177 connect(m_addSerieDialog, SIGNAL(accepted(QString,int,int,QString,bool)),
178 178 this, SLOT(addSeries(QString,int,int,QString,bool)));
179 179 }
180 180 m_addSerieDialog->exec();
181 181 }
182 182
183 183 QList<RealList> MainWidget::generateTestData(int columnCount, int rowCount, QString dataCharacteristics)
184 184 {
185 185 // TODO: dataCharacteristics
186 186 QList<RealList> testData;
187 187 for (int j(0); j < columnCount; j++) {
188 188 QList <qreal> newColumn;
189 189 for (int i(0); i < rowCount; i++) {
190 190 if (dataCharacteristics == "Sin") {
191 191 newColumn.append(abs(sin(3.14159265358979 / 50 * i) * 100));
192 192 } else if (dataCharacteristics == "Sin + random") {
193 193 newColumn.append(abs(sin(3.14159265358979 / 50 * i) * 100) + (rand() % 5));
194 194 } else if (dataCharacteristics == "Random") {
195 195 newColumn.append(rand() % 10 + (qreal) rand() / (qreal) RAND_MAX);
196 196 } else if (dataCharacteristics == "Linear") {
197 197 //newColumn.append(i * (j + 1.0));
198 198 // TODO: temporary hack to make pie work; prevent zero values:
199 199 newColumn.append(i * (j + 1.0) + 0.1);
200 200 } else { // "constant"
201 201 newColumn.append((j + 1.0));
202 202 }
203 203 }
204 204 testData.append(newColumn);
205 205 }
206 206 return testData;
207 207 }
208 208
209 209 QStringList MainWidget::generateLabels(int count)
210 210 {
211 211 QStringList result;
212 212 for (int i(0); i < count; i++)
213 213 result.append("label" + QString::number(i));
214 214 return result;
215 215 }
216 216
217 217 void MainWidget::addSeries(QString seriesName, int columnCount, int rowCount, QString dataCharacteristics, bool labelsEnabled)
218 218 {
219 219 qDebug() << "addSeries: " << seriesName
220 220 << " columnCount: " << columnCount
221 221 << " rowCount: " << rowCount
222 222 << " dataCharacteristics: " << dataCharacteristics
223 223 << " labels enabled: " << labelsEnabled;
224 224 m_defaultSeriesName = seriesName;
225 225
226 226 QList<RealList> data = generateTestData(columnCount, rowCount, dataCharacteristics);
227 227
228 228 // Line series and scatter series use similar data
229 229 if (seriesName == "Line") {
230 230 for (int j(0); j < data.count(); j ++) {
231 231 QList<qreal> column = data.at(j);
232 232 QLineSeries *series = new QLineSeries();
233 233 series->setName("line" + QString::number(j));
234 234 for (int i(0); i < column.count(); i++)
235 235 series->append(i, column.at(i));
236 236 m_chart->addSeries(series);
237 237 }
238 238 } else if (seriesName == "Area") {
239 239 // TODO: lower series for the area?
240 240 for (int j(0); j < data.count(); j ++) {
241 241 QList<qreal> column = data.at(j);
242 242 QLineSeries *lineSeries = new QLineSeries();
243 243 for (int i(0); i < column.count(); i++)
244 244 lineSeries->append(i, column.at(i));
245 245 QAreaSeries *areaSeries = new QAreaSeries(lineSeries);
246 246 areaSeries->setName("area" + QString::number(j));
247 247 m_chart->addSeries(areaSeries);
248 248 }
249 249 } else if (seriesName == "Scatter") {
250 250 for (int j(0); j < data.count(); j++) {
251 251 QList<qreal> column = data.at(j);
252 252 QScatterSeries *series = new QScatterSeries();
253 253 series->setName("scatter" + QString::number(j));
254 254 for (int i(0); i < column.count(); i++)
255 255 series->append(i, column.at(i));
256 256 m_chart->addSeries(series);
257 257 }
258 258 } else if (seriesName == "Pie") {
259 259 QStringList labels = generateLabels(rowCount);
260 260 for (int j(0); j < data.count(); j++) {
261 261 QPieSeries *series = new QPieSeries();
262 262 QList<qreal> column = data.at(j);
263 263 for (int i(0); i < column.count(); i++)
264 series->append(column.at(i), labels.at(i));
264 series->append(labels.at(i), column.at(i));
265 265 m_chart->addSeries(series);
266 266 }
267 267 } else if (seriesName == "Bar"
268 268 || seriesName == "Stacked bar"
269 269 || seriesName == "Percent bar") {
270 270 QStringList category;
271 271 QStringList labels = generateLabels(rowCount);
272 272 foreach(QString label, labels)
273 273 category << label;
274 274 QBarSeries* series = 0;
275 275 if (seriesName == "Bar") {
276 276 series = new QBarSeries(this);
277 277 series->setCategories(category);
278 278 } else if (seriesName == "Stacked bar") {
279 279 series = new QStackedBarSeries(this);
280 280 series->setCategories(category);
281 281 } else {
282 282 series = new QPercentBarSeries(this);
283 283 series->setCategories(category);
284 284 }
285 285
286 286 for (int j(0); j < data.count(); j++) {
287 287 QList<qreal> column = data.at(j);
288 288 QBarSet *set = new QBarSet("set" + QString::number(j));
289 289 for (int i(0); i < column.count(); i++)
290 290 *set << column.at(i);
291 291 series->append(set);
292 292 }
293 293
294 294 m_chart->addSeries(series);
295 295 } else if (seriesName == "Spline") {
296 296 for (int j(0); j < data.count(); j ++) {
297 297 QList<qreal> column = data.at(j);
298 298 QSplineSeries *series = new QSplineSeries();
299 299 for (int i(0); i < column.count(); i++)
300 300 series->append(i, column.at(i));
301 301 m_chart->addSeries(series);
302 302 }
303 303 }
304 304 }
305 305
306 306 void MainWidget::backgroundChanged(int itemIndex)
307 307 {
308 308 qDebug() << "backgroundChanged: " << itemIndex;
309 309 }
310 310
311 311 void MainWidget::autoScaleChanged(int value)
312 312 {
313 313 if (value) {
314 314 // TODO: enable auto scaling
315 315 } else {
316 316 // TODO: set scaling manually (and disable auto scaling)
317 317 }
318 318
319 319 m_xMinSpin->setEnabled(!value);
320 320 m_xMaxSpin->setEnabled(!value);
321 321 m_yMinSpin->setEnabled(!value);
322 322 m_yMaxSpin->setEnabled(!value);
323 323 }
324 324
325 325 void MainWidget::xMinChanged(int value)
326 326 {
327 327 qDebug() << "xMinChanged: " << value;
328 328 }
329 329
330 330 void MainWidget::xMaxChanged(int value)
331 331 {
332 332 qDebug() << "xMaxChanged: " << value;
333 333 }
334 334
335 335 void MainWidget::yMinChanged(int value)
336 336 {
337 337 qDebug() << "yMinChanged: " << value;
338 338 }
339 339
340 340 void MainWidget::yMaxChanged(int value)
341 341 {
342 342 qDebug() << "yMaxChanged: " << value;
343 343 }
344 344
345 345 void MainWidget::changeChartTheme(int themeIndex)
346 346 {
347 347 qDebug() << "changeChartTheme: " << themeIndex;
348 348 m_chart->setTheme((QChart::ChartTheme) themeIndex);
349 349 }
General Comments 0
You need to be logged in to leave comments. Login now