##// END OF EJS Templates
QSeries name and QPieSeries properties to QML api
Tero Ahola -
r884:bc9561bc4b37
parent child
Show More
@@ -1,373 +1,374
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 = "Item " + 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 // area chart
180 180 QChart *chart = new QChart();
181 181 chart->axisX()->setNiceNumbers(true);
182 182 chart->axisY()->setNiceNumbers(true);
183 183 chart->setTitle("Area chart");
184 184 QString name("Series ");
185 185 int nameIndex = 0;
186 186
187 187 // The lower series initialized to zero values
188 188 QLineSeries *lowerSeries = 0;
189 189 for (int i(0); i < m_dataTable.count(); i++) {
190 190 QLineSeries *upperSeries = new QLineSeries(chart);
191 191 for (int j(0); j < m_dataTable[i].count(); j++) {
192 192 Data data = m_dataTable[i].at(j);
193 193 if (lowerSeries)
194 194 upperSeries->append(QPointF(j, lowerSeries->y(i) + 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 return chart;
205 205 }
206 206
207 207 QChart* ThemeWidget::createBarChart(int valueCount) const
208 208 {
209 209 // bar chart
210 210 QChart* chart = new QChart();
211 211 chart->axisX()->setNiceNumbers(true);
212 212 chart->axisY()->setNiceNumbers(true);
213 213 chart->setTitle("Bar chart");
214 214 QBarCategories categories;
215 215 // TODO: categories
216 216 for (int i(0); i < valueCount; i++)
217 217 categories << QString::number(i);
218 218 // QBarSeries* series = new QBarSeries(categories, chart);
219 219 // QPercentBarSeries* series = new QPercentBarSeries(categories, chart);
220 220 QStackedBarSeries* series = new QStackedBarSeries(categories, chart);
221 221 for (int i(0); i < m_dataTable.count(); i++) {
222 222 QBarSet *set = new QBarSet("Set" + QString::number(i));
223 223 foreach (Data data, m_dataTable[i])
224 224 *set << data.first.y();
225 225 series->appendBarSet(set);
226 226 }
227 227 chart->addSeries(series);
228 228 return chart;
229 229 }
230 230
231 231 QChart* ThemeWidget::createLineChart() const
232 232 {
233 233 // line chart
234 234 QChart* chart = new QChart();
235 235 chart->axisX()->setNiceNumbers(true);
236 236 chart->axisY()->setNiceNumbers(true);
237 237 chart->setTitle("Line chart");
238 238 QString name("Series ");
239 239 int nameIndex = 0;
240 240 foreach (DataList list, m_dataTable) {
241 241 QLineSeries *series = new QLineSeries(chart);
242 242 foreach (Data data, list)
243 243 series->append(data.first);
244 244 series->setName(name + QString::number(nameIndex));
245 245 nameIndex++;
246 246 chart->addSeries(series);
247 247 }
248 248 return chart;
249 249 }
250 250
251 251 QChart* ThemeWidget::createPieChart() const
252 252 {
253 253 // pie chart
254 254 QChart* chart = new QChart();
255 255 chart->setTitle("Pie chart");
256 256 qreal pieSize = 1.0 / m_dataTable.count();
257 257 for (int i = 0; i < m_dataTable.count(); i++) {
258 258 QPieSeries *series = new QPieSeries(chart);
259 259 foreach (Data data, m_dataTable[i]) {
260 260 QPieSlice *slice = series->append(data.first.y(), data.second);
261 261 if (data == m_dataTable[i].first()) {
262 262 slice->setLabelVisible();
263 263 slice->setExploded();
264 264 }
265 265 }
266 266 qreal hPos = (pieSize / 2) + (i / (qreal) m_dataTable.count());
267 267 series->setPieSize(pieSize);
268 series->setPiePosition(hPos, 0.5);
268 series->setHorizontalPosition(hPos);
269 series->setVerticalPosition(0.5);
269 270 chart->addSeries(series);
270 271 }
271 272
272 273 return chart;
273 274 }
274 275
275 276 QChart* ThemeWidget::createSplineChart() const
276 277 { // spine chart
277 278 QChart* chart = new QChart();
278 279 chart->axisX()->setNiceNumbers(true);
279 280 chart->axisY()->setNiceNumbers(true);
280 281 chart->setTitle("Spline chart");
281 282 QString name("Series ");
282 283 int nameIndex = 0;
283 284 foreach (DataList list, m_dataTable) {
284 285 QSplineSeries *series = new QSplineSeries(chart);
285 286 foreach (Data data, list)
286 287 series->append(data.first);
287 288 series->setName(name + QString::number(nameIndex));
288 289 nameIndex++;
289 290 chart->addSeries(series);
290 291 }
291 292 return chart;
292 293 }
293 294
294 295 QChart* ThemeWidget::createScatterChart() const
295 296 { // scatter chart
296 297 QChart* chart = new QChart();
297 298 chart->axisX()->setNiceNumbers(true);
298 299 chart->axisY()->setNiceNumbers(true);
299 300 chart->setTitle("Scatter chart");
300 301 QString name("Series ");
301 302 int nameIndex = 0;
302 303 foreach (DataList list, m_dataTable) {
303 304 QScatterSeries *series = new QScatterSeries(chart);
304 305 foreach (Data data, list)
305 306 series->append(data.first);
306 307 series->setName(name + QString::number(nameIndex));
307 308 nameIndex++;
308 309 chart->addSeries(series);
309 310 }
310 311 return chart;
311 312 }
312 313
313 314 void ThemeWidget::updateUI()
314 315 {
315 316 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
316 317
317 318 if (m_charts.at(0)->chart()->theme() != theme) {
318 319 foreach (QChartView *chartView, m_charts)
319 320 chartView->chart()->setTheme(theme);
320 321
321 322 QPalette pal = window()->palette();
322 323 if (theme == QChart::ChartThemeLight) {
323 324 pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
324 325 pal.setColor(QPalette::WindowText, QRgb(0x404044));
325 326 } else if (theme == QChart::ChartThemeDark) {
326 327 pal.setColor(QPalette::Window, QRgb(0x121218));
327 328 pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
328 329 } else if (theme == QChart::ChartThemeBlueCerulean) {
329 330 pal.setColor(QPalette::Window, QRgb(0x40434a));
330 331 pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
331 332 } else if (theme == QChart::ChartThemeBrownSand) {
332 333 pal.setColor(QPalette::Window, QRgb(0x9e8965));
333 334 pal.setColor(QPalette::WindowText, QRgb(0x404044));
334 335 } else if (theme == QChart::ChartThemeBlueNcs) {
335 336 pal.setColor(QPalette::Window, QRgb(0x018bba));
336 337 pal.setColor(QPalette::WindowText, QRgb(0x404044));
337 338 } else if (theme == QChart::ChartThemeHighContrast) {
338 339 pal.setColor(QPalette::Window, QRgb(0xffab03));
339 340 pal.setColor(QPalette::WindowText, QRgb(0x181818));
340 341 } else if (theme == QChart::ChartThemeBlueIcy) {
341 342 pal.setColor(QPalette::Window, QRgb(0xcee7f0));
342 343 pal.setColor(QPalette::WindowText, QRgb(0x404044));
343 344 } else {
344 345 pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
345 346 pal.setColor(QPalette::WindowText, QRgb(0x404044));
346 347 }
347 348 window()->setPalette(pal);
348 349 }
349 350
350 351 bool checked = m_antialiasCheckBox->isChecked();
351 352 foreach (QChartView *chart, m_charts)
352 353 chart->setRenderHint(QPainter::Antialiasing, checked);
353 354
354 355 QChart::AnimationOptions options(m_animatedComboBox->itemData(m_animatedComboBox->currentIndex()).toInt());
355 356 if (m_charts.at(0)->chart()->animationOptions() != options) {
356 357 foreach (QChartView *chartView, m_charts)
357 358 chartView->chart()->setAnimationOptions(options);
358 359 }
359 360
360 361 QLegend::Alignments alignment(m_legendComboBox->itemData(m_legendComboBox->currentIndex()).toInt());
361 362
362 363 if (!alignment) {
363 364 foreach (QChartView *chartView, m_charts) {
364 365 chartView->chart()->legend()->hide();
365 366 }
366 367 }
367 368 else
368 369 foreach (QChartView *chartView, m_charts) {
369 370 chartView->chart()->legend()->setAlignmnent(alignment);
370 371 chartView->chart()->legend()->show();
371 372 }
372 373 }
373 374
@@ -1,321 +1,322
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 48 *m_series << new CustomSlice(10.0, "Slice 1");
49 49 *m_series << new CustomSlice(20.0, "Slice 2");
50 50 *m_series << new CustomSlice(30.0, "Slice 3");
51 51 *m_series << new CustomSlice(40.0, "Slice 4");
52 52 *m_series << new CustomSlice(50.0, "Slice 5");
53 53 m_series->setLabelsVisible();
54 54 chart->addSeries(m_series);
55 55
56 56 connect(m_series, SIGNAL(clicked(QPieSlice*, Qt::MouseButtons)), this, SLOT(handleSliceClicked(QPieSlice*, Qt::MouseButtons)));
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 QFormLayout* chartSettingsLayout = new QFormLayout();
73 73 chartSettingsLayout->addRow("Theme", m_themeComboBox);
74 74 chartSettingsLayout->addRow("Antialiasing", m_aaCheckBox);
75 75 chartSettingsLayout->addRow("Animations", m_animationsCheckBox);
76 76 QGroupBox* chartSettings = new QGroupBox("Chart");
77 77 chartSettings->setLayout(chartSettingsLayout);
78 78
79 79 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this ,SLOT(updateChartSettings()));
80 80 connect(m_aaCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
81 81 connect(m_animationsCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
82 82
83 83 // series settings
84 84 m_hPosition = new QDoubleSpinBox();
85 85 m_hPosition->setMinimum(0.0);
86 86 m_hPosition->setMaximum(1.0);
87 87 m_hPosition->setSingleStep(0.1);
88 m_hPosition->setValue(m_series->pieHorizontalPosition());
88 m_hPosition->setValue(m_series->horizontalPosition());
89 89
90 90 m_vPosition = new QDoubleSpinBox();
91 91 m_vPosition->setMinimum(0.0);
92 92 m_vPosition->setMaximum(1.0);
93 93 m_vPosition->setSingleStep(0.1);
94 m_vPosition->setValue(m_series->pieVerticalPosition());
94 m_vPosition->setValue(m_series->verticalPosition());
95 95
96 96 m_sizeFactor = new QDoubleSpinBox();
97 97 m_sizeFactor->setMinimum(0.0);
98 98 m_sizeFactor->setMaximum(1.0);
99 99 m_sizeFactor->setSingleStep(0.1);
100 100 m_sizeFactor->setValue(m_series->pieSize());
101 101
102 102 m_startAngle = new QDoubleSpinBox();
103 103 m_startAngle->setMinimum(0.0);
104 104 m_startAngle->setMaximum(360);
105 105 m_startAngle->setValue(m_series->pieStartAngle());
106 106 m_startAngle->setSingleStep(1);
107 107
108 108 m_endAngle = new QDoubleSpinBox();
109 109 m_endAngle->setMinimum(0.0);
110 110 m_endAngle->setMaximum(360);
111 111 m_endAngle->setValue(m_series->pieEndAngle());
112 112 m_endAngle->setSingleStep(1);
113 113
114 114 QPushButton *addSlice = new QPushButton("Add slice");
115 115 QPushButton *insertSlice = new QPushButton("Insert slice");
116 116
117 117 QFormLayout* seriesSettingsLayout = new QFormLayout();
118 118 seriesSettingsLayout->addRow("Horizontal position", m_hPosition);
119 119 seriesSettingsLayout->addRow("Vertical position", m_vPosition);
120 120 seriesSettingsLayout->addRow("Size factor", m_sizeFactor);
121 121 seriesSettingsLayout->addRow("Start angle", m_startAngle);
122 122 seriesSettingsLayout->addRow("End angle", m_endAngle);
123 123 seriesSettingsLayout->addRow(addSlice);
124 124 seriesSettingsLayout->addRow(insertSlice);
125 125 QGroupBox* seriesSettings = new QGroupBox("Series");
126 126 seriesSettings->setLayout(seriesSettingsLayout);
127 127
128 128 connect(m_vPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
129 129 connect(m_hPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
130 130 connect(m_sizeFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
131 131 connect(m_startAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
132 132 connect(m_endAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
133 133 connect(addSlice, SIGNAL(clicked()), this, SLOT(addSlice()));
134 134 connect(insertSlice, SIGNAL(clicked()), this, SLOT(insertSlice()));
135 135
136 136 // slice settings
137 137 m_sliceName = new QLabel("<click a slice>");
138 138 m_sliceValue = new QDoubleSpinBox();
139 139 m_sliceValue->setMaximum(1000);
140 140 m_sliceLabelVisible = new QCheckBox();
141 141 m_sliceLabelArmFactor = new QDoubleSpinBox();
142 142 m_sliceLabelArmFactor->setSingleStep(0.01);
143 143 m_sliceExploded = new QCheckBox();
144 144 m_sliceExplodedFactor = new QDoubleSpinBox();
145 145 m_sliceExplodedFactor->setSingleStep(0.01);
146 146 m_pen = new QPushButton();
147 147 m_penTool = new PenTool("Slice pen", this);
148 148 m_brush = new QPushButton();
149 149 m_brushTool = new BrushTool("Slice brush", this);
150 150 m_font = new QPushButton();
151 151 m_labelPen = new QPushButton();
152 152 m_labelPenTool = new PenTool("Label pen", this);
153 153 QPushButton *removeSlice = new QPushButton("Remove slice");
154 154
155 155 QFormLayout* sliceSettingsLayout = new QFormLayout();
156 156 sliceSettingsLayout->addRow("Selected", m_sliceName);
157 157 sliceSettingsLayout->addRow("Value", m_sliceValue);
158 158 sliceSettingsLayout->addRow("Pen", m_pen);
159 159 sliceSettingsLayout->addRow("Brush", m_brush);
160 160 sliceSettingsLayout->addRow("Label visible", m_sliceLabelVisible);
161 161 sliceSettingsLayout->addRow("Label font", m_font);
162 162 sliceSettingsLayout->addRow("Label pen", m_labelPen);
163 163 sliceSettingsLayout->addRow("Label arm length", m_sliceLabelArmFactor);
164 164 sliceSettingsLayout->addRow("Exploded", m_sliceExploded);
165 165 sliceSettingsLayout->addRow("Explode distance", m_sliceExplodedFactor);
166 166 sliceSettingsLayout->addRow(removeSlice);
167 167 QGroupBox* sliceSettings = new QGroupBox("Slice");
168 168 sliceSettings->setLayout(sliceSettingsLayout);
169 169
170 170 connect(m_sliceValue, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
171 171 connect(m_pen, SIGNAL(clicked()), m_penTool, SLOT(show()));
172 172 connect(m_penTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
173 173 connect(m_brush, SIGNAL(clicked()), m_brushTool, SLOT(show()));
174 174 connect(m_brushTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
175 175 connect(m_font, SIGNAL(clicked()), this, SLOT(showFontDialog()));
176 176 connect(m_labelPen, SIGNAL(clicked()), m_labelPenTool, SLOT(show()));
177 177 connect(m_labelPenTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
178 178 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
179 179 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
180 180 connect(m_sliceLabelArmFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
181 181 connect(m_sliceExploded, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
182 182 connect(m_sliceExplodedFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
183 183 connect(removeSlice, SIGNAL(clicked()), this, SLOT(removeSlice()));
184 184
185 185 // create chart view
186 186 m_chartView = new QChartView(chart);
187 187
188 188 // create main layout
189 189 QVBoxLayout *settingsLayout = new QVBoxLayout();
190 190 settingsLayout->addWidget(chartSettings);
191 191 settingsLayout->addWidget(seriesSettings);
192 192 settingsLayout->addWidget(sliceSettings);
193 193 settingsLayout->addStretch();
194 194
195 195 QGridLayout* baseLayout = new QGridLayout();
196 196 baseLayout->addLayout(settingsLayout, 0, 0);
197 197 baseLayout->addWidget(m_chartView, 0, 1);
198 198 setLayout(baseLayout);
199 199
200 200 updateSerieSettings();
201 201 }
202 202
203 203
204 204 void MainWidget::updateChartSettings()
205 205 {
206 206 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
207 207 m_chartView->chart()->setTheme(theme);
208 208 m_chartView->setRenderHint(QPainter::Antialiasing, m_aaCheckBox->isChecked());
209 209
210 210 if (m_animationsCheckBox->checkState() == Qt::Checked)
211 211 m_chartView->chart()->setAnimationOptions(QChart::AllAnimations);
212 212 else
213 213 m_chartView->chart()->setAnimationOptions(QChart::NoAnimation);
214 214 }
215 215
216 216 void MainWidget::updateSerieSettings()
217 217 {
218 m_series->setPiePosition(m_hPosition->value(), m_vPosition->value());
218 m_series->setHorizontalPosition(m_hPosition->value());
219 m_series->setVerticalPosition(m_vPosition->value());
219 220 m_series->setPieSize(m_sizeFactor->value());
220 221 m_series->setPieStartAngle(m_startAngle->value());
221 222 m_series->setPieEndAngle(m_endAngle->value());
222 223 }
223 224
224 225 void MainWidget::updateSliceSettings()
225 226 {
226 227 if (!m_slice)
227 228 return;
228 229
229 230 m_slice->setValue(m_sliceValue->value());
230 231
231 232 m_slice->setPen(m_penTool->pen());
232 233 m_slice->setBrush(m_brushTool->brush());
233 234
234 235 m_slice->setLabelPen(m_labelPenTool->pen());
235 236 m_slice->setLabelVisible(m_sliceLabelVisible->isChecked());
236 237 m_slice->setLabelArmLengthFactor(m_sliceLabelArmFactor->value());
237 238
238 239 m_slice->setExploded(m_sliceExploded->isChecked());
239 240 m_slice->setExplodeDistanceFactor(m_sliceExplodedFactor->value());
240 241 }
241 242
242 243 void MainWidget::handleSliceClicked(QPieSlice* slice, Qt::MouseButtons buttons)
243 244 {
244 245 Q_UNUSED(buttons);
245 246
246 247 m_slice = static_cast<CustomSlice*>(slice);
247 248
248 249 // name
249 250 m_sliceName->setText(slice->label());
250 251
251 252 // value
252 253 m_sliceValue->blockSignals(true);
253 254 m_sliceValue->setValue(slice->value());
254 255 m_sliceValue->blockSignals(false);
255 256
256 257 // pen
257 258 m_pen->setText(PenTool::name(m_slice->pen()));
258 259 m_penTool->setPen(m_slice->pen());
259 260
260 261 // brush
261 262 m_brush->setText(m_slice->originalBrush().color().name());
262 263 m_brushTool->setBrush(m_slice->originalBrush());
263 264
264 265 // label
265 266 m_labelPen->setText(PenTool::name(m_slice->labelPen()));
266 267 m_labelPenTool->setPen(m_slice->labelPen());
267 268 m_font->setText(slice->labelFont().toString());
268 269 m_sliceLabelVisible->blockSignals(true);
269 270 m_sliceLabelVisible->setChecked(slice->isLabelVisible());
270 271 m_sliceLabelVisible->blockSignals(false);
271 272 m_sliceLabelArmFactor->blockSignals(true);
272 273 m_sliceLabelArmFactor->setValue(slice->labelArmLengthFactor());
273 274 m_sliceLabelArmFactor->blockSignals(false);
274 275
275 276 // exploded
276 277 m_sliceExploded->blockSignals(true);
277 278 m_sliceExploded->setChecked(slice->isExploded());
278 279 m_sliceExploded->blockSignals(false);
279 280 m_sliceExplodedFactor->blockSignals(true);
280 281 m_sliceExplodedFactor->setValue(slice->explodeDistanceFactor());
281 282 m_sliceExplodedFactor->blockSignals(false);
282 283 }
283 284
284 285 void MainWidget::showFontDialog()
285 286 {
286 287 if (!m_slice)
287 288 return;
288 289
289 290 QFontDialog dialog(m_slice->labelFont());
290 291 dialog.show();
291 292 dialog.exec();
292 293
293 294 m_slice->setLabelFont(dialog.currentFont());
294 295 m_font->setText(dialog.currentFont().toString());
295 296 }
296 297
297 298 void MainWidget::addSlice()
298 299 {
299 300 *m_series << new CustomSlice(10.0, "Slice " + QString::number(m_series->count()+1));
300 301 }
301 302
302 303 void MainWidget::insertSlice()
303 304 {
304 305 if (!m_slice)
305 306 return;
306 307
307 308 int i = m_series->slices().indexOf(m_slice);
308 309
309 310 m_series->insert(i, new CustomSlice(10.0, "Slice " + QString::number(m_series->count()+1)));
310 311 }
311 312
312 313 void MainWidget::removeSlice()
313 314 {
314 315 if (!m_slice)
315 316 return;
316 317
317 318 m_series->remove(m_slice);
318 319 m_slice = 0;
319 320 }
320 321
321 322 #include "moc_mainwidget.cpp"
@@ -1,63 +1,62
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
25 25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 26
27 27 DeclarativePieSeries::DeclarativePieSeries(QObject *parent) :
28 28 QPieSeries(parent),
29 29 m_chart(0)
30 30 {
31 31 }
32 32
33 33 void DeclarativePieSeries::classBegin()
34 34 {
35 35 }
36 36
37 37 void DeclarativePieSeries::componentComplete()
38 38 {
39 39 DeclarativeChart *declarativeChart = qobject_cast<DeclarativeChart *>(parent());
40 40 if (declarativeChart) {
41 41 QChart *chart = qobject_cast<QChart *>(declarativeChart->m_chart);
42 42 Q_ASSERT(chart);
43 qDebug() << "parent for pie:" << chart;
44 43 chart->addSeries(this);
45 44 }
46 45 }
47 46
48 47 QDeclarativeListProperty<QPieSlice> DeclarativePieSeries::slices()
49 48 {
50 49 return QDeclarativeListProperty<QPieSlice>(this, 0, &DeclarativePieSeries::appendSlice);
51 50 }
52 51
53 52 void DeclarativePieSeries::appendSlice(QDeclarativeListProperty<QPieSlice> *list,
54 53 QPieSlice *slice)
55 54 {
56 55 DeclarativePieSeries *series = qobject_cast<DeclarativePieSeries *>(list->object);
57 56 if (series)
58 57 series->append(slice->value(), slice->label());
59 58 }
60 59
61 60 #include "moc_declarativepieseries.cpp"
62 61
63 62 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,212 +1,212
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 "piechartitem_p.h"
22 22 #include "piesliceitem_p.h"
23 23 #include "qpieslice.h"
24 24 #include "qpieseries.h"
25 25 #include "chartpresenter_p.h"
26 26 #include "chartdataset_p.h"
27 27 #include "chartanimator_p.h"
28 28 #include <QDebug>
29 29 #include <QPainter>
30 30 #include <QTimer>
31 31
32 32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 33
34 34 PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter* presenter)
35 35 :ChartItem(presenter),
36 36 m_series(series)
37 37 {
38 38 Q_ASSERT(series);
39 39 connect(series, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>)));
40 40 connect(series, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>)));
41 41 connect(series, SIGNAL(piePositionChanged()), this, SLOT(handlePieLayoutChanged()));
42 42 connect(series, SIGNAL(pieSizeChanged()), this, SLOT(handlePieLayoutChanged()));
43 43
44 44 QTimer::singleShot(0, this, SLOT(initialize()));
45 45
46 46 // Note: the following does not affect as long as the item does not have anything to paint
47 47 setZValue(ChartPresenter::PieSeriesZValue);
48 48 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
49 49 }
50 50
51 51 PieChartItem::~PieChartItem()
52 52 {
53 53 // slices deleted automatically through QGraphicsItem
54 54 }
55 55
56 56 void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
57 57 {
58 58 Q_UNUSED(painter)
59 59 // TODO: paint shadows for all components
60 60 // - get paths from items & merge & offset and draw with shadow color?
61 61 //painter->setBrush(QBrush(Qt::red));
62 62 //painter->drawRect(m_debugRect);
63 63 }
64 64
65 65 void PieChartItem::initialize()
66 66 {
67 67 handleSlicesAdded(m_series->slices());
68 68 }
69 69
70 70 void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices)
71 71 {
72 72 bool isEmpty = m_slices.isEmpty();
73 73
74 74 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series), false);
75 75
76 76 foreach (QPieSlice *s, slices) {
77 77 PieSliceItem* item = new PieSliceItem(this);
78 78 m_slices.insert(s, item);
79 79 connect(s, SIGNAL(changed()), this, SLOT(handleSliceChanged()));
80 80 connect(item, SIGNAL(clicked(Qt::MouseButtons)), s, SIGNAL(clicked(Qt::MouseButtons)));
81 81 connect(item, SIGNAL(hoverEnter()), s, SIGNAL(hoverEnter()));
82 82 connect(item, SIGNAL(hoverLeave()), s, SIGNAL(hoverLeave()));
83 83
84 84 PieSliceData data = sliceData(s);
85 85
86 86 if (animator())
87 87 animator()->addAnimation(this, s, data, isEmpty);
88 88 else
89 89 setLayout(s, data);
90 90 }
91 91 }
92 92
93 93 void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices)
94 94 {
95 95 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series), false);
96 96
97 97 foreach (QPieSlice *s, slices) {
98 98 if (animator())
99 99 animator()->removeAnimation(this, s);
100 100 else
101 101 destroySlice(s);
102 102 }
103 103 }
104 104
105 105 void PieChartItem::handlePieLayoutChanged()
106 106 {
107 107 PieLayout layout = calculateLayout();
108 108 applyLayout(layout);
109 109 update();
110 110 }
111 111
112 112 void PieChartItem::handleSliceChanged()
113 113 {
114 114 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
115 115 Q_ASSERT(m_slices.contains(slice));
116 116 PieSliceData data = sliceData(slice);
117 117 updateLayout(slice, data);
118 118 update();
119 119 }
120 120
121 121 void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal)
122 122 {
123 123 // TODO
124 124 }
125 125
126 126 void PieChartItem::handleGeometryChanged(const QRectF& rect)
127 127 {
128 128 prepareGeometryChange();
129 129 m_rect = rect;
130 130 handlePieLayoutChanged();
131 131 }
132 132
133 133 void PieChartItem::calculatePieLayout()
134 134 {
135 135 // find pie center coordinates
136 m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->pieHorizontalPosition()));
137 m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->pieVerticalPosition()));
136 m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->horizontalPosition()));
137 m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->verticalPosition()));
138 138
139 139 // find maximum radius for pie
140 140 m_pieRadius = m_rect.height() / 2;
141 141 if (m_rect.width() < m_rect.height())
142 142 m_pieRadius = m_rect.width() / 2;
143 143
144 144 // apply size factor
145 145 m_pieRadius *= m_series->pieSize();
146 146 }
147 147
148 148 PieSliceData PieChartItem::sliceData(QPieSlice *slice)
149 149 {
150 150 // TODO: This function is kid of useless now. Refactor.
151 151 PieSliceData sliceData = PieSliceData::data(slice);
152 152 sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice);
153 153 sliceData.m_radius = m_pieRadius;
154 154 return sliceData;
155 155 }
156 156
157 157 PieLayout PieChartItem::calculateLayout()
158 158 {
159 159 calculatePieLayout();
160 160 PieLayout layout;
161 161 foreach (QPieSlice* s, m_series->slices()) {
162 162 if (m_slices.contains(s)) // calculate layout only for those slices that are already visible
163 163 layout.insert(s, sliceData(s));
164 164 }
165 165 return layout;
166 166 }
167 167
168 168 void PieChartItem::applyLayout(const PieLayout &layout)
169 169 {
170 170 if (animator())
171 171 animator()->updateLayout(this, layout);
172 172 else
173 173 setLayout(layout);
174 174 }
175 175
176 176 void PieChartItem::updateLayout(QPieSlice *slice, const PieSliceData &sliceData)
177 177 {
178 178 if (animator())
179 179 animator()->updateLayout(this, slice, sliceData);
180 180 else
181 181 setLayout(slice, sliceData);
182 182 }
183 183
184 184 void PieChartItem::setLayout(const PieLayout &layout)
185 185 {
186 186 foreach (QPieSlice *slice, layout.keys()) {
187 187 PieSliceItem *item = m_slices.value(slice);
188 188 Q_ASSERT(item);
189 189 item->setSliceData(layout.value(slice));
190 190 item->updateGeometry();
191 191 item->update();
192 192 }
193 193 }
194 194
195 195 void PieChartItem::setLayout(QPieSlice *slice, const PieSliceData &sliceData)
196 196 {
197 197 // find slice
198 198 PieSliceItem *item = m_slices.value(slice);
199 199 Q_ASSERT(item);
200 200 item->setSliceData(sliceData);
201 201 item->updateGeometry();
202 202 item->update();
203 203 }
204 204
205 205 void PieChartItem::destroySlice(QPieSlice *slice)
206 206 {
207 207 delete m_slices.take(slice);
208 208 }
209 209
210 210 #include "moc_piechartitem_p.cpp"
211 211
212 212 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,697 +1,706
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 "qpieseriesprivate_p.h"
23 23 #include "qpieslice.h"
24 24 #include "pieslicedata_p.h"
25 25 #include <QAbstractItemModel>
26 26 #include <QDebug>
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent)
31 31 :QObject(parent),
32 32 q_ptr(parent),
33 33 m_pieRelativeHorPos(0.5),
34 34 m_pieRelativeVerPos(0.5),
35 35 m_pieRelativeSize(0.7),
36 36 m_pieStartAngle(0),
37 37 m_pieEndAngle(360),
38 38 m_total(0),
39 39 m_mapValues(0),
40 40 m_mapLabels(0),
41 41 m_mapOrientation(Qt::Horizontal)
42 42 {
43 43
44 44 }
45 45
46 46 QPieSeriesPrivate::~QPieSeriesPrivate()
47 47 {
48 48
49 49 }
50 50
51 51 void QPieSeriesPrivate::updateDerivativeData()
52 52 {
53 53 m_total = 0;
54 54
55 55 // nothing to do?
56 56 if (m_slices.count() == 0)
57 57 return;
58 58
59 59 // calculate total
60 60 foreach (QPieSlice* s, m_slices)
61 61 m_total += s->value();
62 62
63 63 // nothing to show..
64 64 if (qFuzzyIsNull(m_total))
65 65 return;
66 66
67 67 // update slice attributes
68 68 qreal sliceAngle = m_pieStartAngle;
69 69 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
70 70 QVector<QPieSlice*> changed;
71 71 foreach (QPieSlice* s, m_slices) {
72 72
73 73 PieSliceData data = PieSliceData::data(s);
74 74 data.m_percentage = s->value() / m_total;
75 75 data.m_angleSpan = pieSpan * data.m_percentage;
76 76 data.m_startAngle = sliceAngle;
77 77 sliceAngle += data.m_angleSpan;
78 78
79 79 if (PieSliceData::data(s) != data) {
80 80 PieSliceData::data(s) = data;
81 81 changed << s;
82 82 }
83 83 }
84 84
85 85 // emit signals
86 86 foreach (QPieSlice* s, changed)
87 87 PieSliceData::data(s).emitChangedSignal(s);
88 88 }
89 89
90 90 void QPieSeriesPrivate::sliceChanged()
91 91 {
92 92 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
93 93 updateDerivativeData();
94 94 }
95 95
96 96 void QPieSeriesPrivate::sliceClicked(Qt::MouseButtons buttons)
97 97 {
98 98 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
99 99 Q_ASSERT(m_slices.contains(slice));
100 100 Q_Q(QPieSeries);
101 101 emit q->clicked(slice, buttons);
102 102 }
103 103
104 104 void QPieSeriesPrivate::sliceHoverEnter()
105 105 {
106 106 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
107 107 Q_ASSERT(m_slices.contains(slice));
108 108 Q_Q(QPieSeries);
109 109 emit q->hoverEnter(slice);
110 110 }
111 111
112 112 void QPieSeriesPrivate::sliceHoverLeave()
113 113 {
114 114 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
115 115 Q_ASSERT(m_slices.contains(slice));
116 116 Q_Q(QPieSeries);
117 117 emit q->hoverLeave(slice);
118 118 }
119 119
120 120 void QPieSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
121 121 {
122 122 Q_UNUSED(bottomRight)
123 123 Q_Q(QPieSeries);
124 124
125 125 if (m_mapOrientation == Qt::Vertical)
126 126 {
127 127 if (topLeft.column() == m_mapValues)
128 128 if (m_mapValues == m_mapLabels)
129 129 {
130 130 m_slices.at(topLeft.row())->setValue(q->m_model->data(topLeft, Qt::DisplayRole).toDouble());
131 131 m_slices.at(topLeft.row())->setLabel(q->m_model->data(topLeft, Qt::DisplayRole).toString());
132 132 }
133 133 else
134 134 {
135 135 m_slices.at(topLeft.row())->setValue(q->m_model->data(topLeft, Qt::DisplayRole).toDouble());
136 136 }
137 137 else if (topLeft.column() == m_mapLabels)
138 138 m_slices.at(topLeft.row())->setLabel(q->m_model->data(topLeft, Qt::DisplayRole).toString());
139 139 }
140 140 else
141 141 {
142 142 if (topLeft.row() == m_mapValues)
143 143 if (m_mapValues == m_mapLabels)
144 144 {
145 145 m_slices.at(topLeft.column())->setValue(q->m_model->data(topLeft, Qt::DisplayRole).toDouble());
146 146 m_slices.at(topLeft.column())->setLabel(q->m_model->data(topLeft, Qt::DisplayRole).toString());
147 147 }
148 148 else
149 149 {
150 150 m_slices.at(topLeft.column())->setValue(q->m_model->data(topLeft, Qt::DisplayRole).toDouble());
151 151 }
152 152 else if (topLeft.row() == m_mapLabels)
153 153 m_slices.at(topLeft.column())->setLabel(q->m_model->data(topLeft, Qt::DisplayRole).toString());
154 154 }
155 155 }
156 156
157 157 void QPieSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end)
158 158 {
159 159 Q_UNUSED(parent)
160 160 Q_UNUSED(end)
161 161 Q_Q(QPieSeries);
162 162
163 163 QPieSlice* newSlice = new QPieSlice;
164 164 newSlice->setLabelVisible(true);
165 165 if (m_mapOrientation == Qt::Vertical)
166 166 {
167 167 newSlice->setValue(q->m_model->data(q->m_model->index(start, m_mapValues), Qt::DisplayRole).toDouble());
168 168 newSlice->setLabel(q->m_model->data(q->m_model->index(start, m_mapLabels), Qt::DisplayRole).toString());
169 169 }
170 170 else
171 171 {
172 172 newSlice->setValue(q->m_model->data(q->m_model->index(m_mapValues, start), Qt::DisplayRole).toDouble());
173 173 newSlice->setLabel(q->m_model->data(q->m_model->index(m_mapLabels, start), Qt::DisplayRole).toString());
174 174 }
175 175
176 176 q->insert(start, newSlice);
177 177 }
178 178
179 179 void QPieSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
180 180 {
181 181 Q_UNUSED(parent)
182 182 Q_UNUSED(end)
183 183 Q_Q(QPieSeries);
184 184 q->remove(m_slices.at(start));
185 185 }
186 186
187 bool QPieSeriesPrivate::setRealValue(qreal &value, qreal newValue, qreal max, qreal min)
188 {
189 // Remove rounding errors
190 qreal roundedValue = newValue;
191 if (qFuzzyIsNull(min) && qFuzzyIsNull(newValue))
192 roundedValue = 0.0;
193 else if (qFuzzyCompare(newValue, max))
194 roundedValue = max;
195 else if (qFuzzyCompare(newValue, min))
196 roundedValue = min;
197
198 // Check if the position is valid after removing the rounding errors
199 if (roundedValue < min || roundedValue > max) {
200 qWarning("QPieSeries: Illegal value");
201 return false;
202 }
203
204 if (!qFuzzyIsNull(value - roundedValue)) {
205 value = roundedValue;
206 return true;
207 }
208
209 // The change was so small it is considered a rounding error
210 return false;
211 }
212
187 213
188 214
189 215 /*!
190 216 \class QPieSeries
191 217 \brief Pie series API for QtCommercial Charts
192 218
193 219 The pie series defines a pie chart which consists of pie slices which are QPieSlice objects.
194 220 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
195 221 The actual slice size is determined by that relative value.
196 222
197 223 By default the pie is defined as a full pie but it can be a partial pie.
198 224 This can be done by setting a starting angle and angle span to the series.
199 225 */
200 226
201 227 /*!
202 228 Constructs a series object which is a child of \a parent.
203 229 */
204 230 QPieSeries::QPieSeries(QObject *parent) :
205 231 QSeries(parent),
206 232 d_ptr(new QPieSeriesPrivate(this))
207 233 {
208 234
209 235 }
210 236
211 237 /*!
212 238 Destroys the object. Note that adding series to QChart transfers the ownership to the chart.
213 239 */
214 240 QPieSeries::~QPieSeries()
215 241 {
216 242 // NOTE: d_prt destroyed by QObject
217 243 }
218 244
219 245 /*!
220 246 Returns QChartSeries::SeriesTypePie.
221 247 */
222 248 QSeries::QSeriesType QPieSeries::type() const
223 249 {
224 250 return QSeries::SeriesTypePie;
225 251 }
226 252
227 253 /*!
228 254 Sets an array of \a slices to the series replacing the existing slices.
229 255 Slice ownership is passed to the series.
230 256 */
231 257 void QPieSeries::replace(QList<QPieSlice*> slices)
232 258 {
233 259 clear();
234 260 append(slices);
235 261 }
236 262
237 263 /*!
238 264 Adds an array of \a slices to the series.
239 265 Slice ownership is passed to the series.
240 266 */
241 267 void QPieSeries::append(QList<QPieSlice*> slices)
242 268 {
243 269 Q_D(QPieSeries);
244 270
245 271 foreach (QPieSlice* s, slices) {
246 272 s->setParent(this);
247 273 d->m_slices << s;
248 274 }
249 275
250 276 d->updateDerivativeData();
251 277
252 278 foreach (QPieSlice* s, slices) {
253 279 connect(s, SIGNAL(changed()), d, SLOT(sliceChanged()));
254 280 connect(s, SIGNAL(clicked(Qt::MouseButtons)), d, SLOT(sliceClicked(Qt::MouseButtons)));
255 281 connect(s, SIGNAL(hoverEnter()), d, SLOT(sliceHoverEnter()));
256 282 connect(s, SIGNAL(hoverLeave()), d, SLOT(sliceHoverLeave()));
257 283 }
258 284
259 285 emit added(slices);
260 286 }
261 287
262 288 /*!
263 289 Adds a single \a slice to the series.
264 290 Slice ownership is passed to the series.
265 291 */
266 292 void QPieSeries::append(QPieSlice* slice)
267 293 {
268 294 append(QList<QPieSlice*>() << slice);
269 295 }
270 296
271 297 /*!
272 298 Adds a single \a slice to the series and returns a reference to the series.
273 299 Slice ownership is passed to the series.
274 300 */
275 301 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
276 302 {
277 303 append(slice);
278 304 return *this;
279 305 }
280 306
281 307
282 308 /*!
283 309 Appends a single slice to the series with give \a value and \a name.
284 310 Slice ownership is passed to the series.
285 311 */
286 312 QPieSlice* QPieSeries::append(qreal value, QString name)
287 313 {
288 314 QPieSlice* slice = new QPieSlice(value, name);
289 315 append(slice);
290 316 return slice;
291 317 }
292 318
293 319 /*!
294 320 Inserts a single \a slice to the series before the slice at \a index position.
295 321 Slice ownership is passed to the series.
296 322 */
297 323 void QPieSeries::insert(int index, QPieSlice* slice)
298 324 {
299 325 Q_D(QPieSeries);
300 326 Q_ASSERT(index <= d->m_slices.count());
301 327 slice->setParent(this);
302 328 d->m_slices.insert(index, slice);
303 329
304 330 d->updateDerivativeData();
305 331
306 332 connect(slice, SIGNAL(changed()), d, SLOT(sliceChanged()));
307 333 connect(slice, SIGNAL(clicked(Qt::MouseButtons)), d, SLOT(sliceClicked(Qt::MouseButtons)));
308 334 connect(slice, SIGNAL(hoverEnter()), d, SLOT(sliceHoverEnter()));
309 335 connect(slice, SIGNAL(hoverLeave()), d, SLOT(sliceHoverLeave()));
310 336
311 337 emit added(QList<QPieSlice*>() << slice);
312 338 }
313 339
314 340 /*!
315 341 Removes a single \a slice from the series and deletes the slice.
316 342
317 343 Do not reference this pointer after this call.
318 344 */
319 345 void QPieSeries::remove(QPieSlice* slice)
320 346 {
321 347 Q_D(QPieSeries);
322 348 if (!d->m_slices.removeOne(slice)) {
323 349 Q_ASSERT(0); // TODO: how should this be reported?
324 350 return;
325 351 }
326 352
327 353 d->updateDerivativeData();
328 354
329 355 emit removed(QList<QPieSlice*>() << slice);
330 356
331 357 delete slice;
332 358 slice = 0;
333 359 }
334 360
335 361 /*!
336 362 Clears all slices from the series.
337 363 */
338 364 void QPieSeries::clear()
339 365 {
340 366 Q_D(QPieSeries);
341 367 if (d->m_slices.count() == 0)
342 368 return;
343 369
344 370 QList<QPieSlice*> slices = d->m_slices;
345 371 foreach (QPieSlice* s, d->m_slices) {
346 372 d->m_slices.removeOne(s);
347 373 delete s;
348 374 }
349 375
350 376 d->updateDerivativeData();
351 377
352 378 emit removed(slices);
353 379 }
354 380
355 381 /*!
356 382 Counts the number of the slices in this series.
357 383 */
358 384 int QPieSeries::count() const
359 385 {
360 386 Q_D(const QPieSeries);
361 387 return d->m_slices.count();
362 388 }
363 389
364 390 /*!
365 391 Returns true is the series is empty.
366 392 */
367 393 bool QPieSeries::isEmpty() const
368 394 {
369 395 Q_D(const QPieSeries);
370 396 return d->m_slices.isEmpty();
371 397 }
372 398
373 399 /*!
374 400 Returns a list of slices that belong to this series.
375 401 */
376 402 QList<QPieSlice*> QPieSeries::slices() const
377 403 {
378 404 Q_D(const QPieSeries);
379 405 return d->m_slices;
380 406 }
381 407
382 408 /*!
383 Sets the center position of the pie by \a relativeHorizontalPosition and \a relativeVerticalPosition.
384
385 The factors are relative to the chart rectangle where:
409 Sets the horizontal center position of the pie to \relativePosition. If \relativePosition is
410 set to 0.0 the pie is drawn on the left side of the chart and if it's set to 1.0 the pie is
411 drawn on right side of the chart. The default value 0.5 puts the pie in the middle.
386 412
387 \a relativeHorizontalPosition 0.0 means the absolute left.
388 \a relativeHorizontalPosition 1.0 means the absolute right.
389 \a relativeVerticalPosition 0.0 means the absolute top.
390 \a relativeVerticalPosition 1.0 means the absolute bottom.
413 \sa setHorizontalPosition(), setPieSize()
414 */
415 void QPieSeries::setHorizontalPosition(qreal relativePosition)
416 {
417 Q_D(QPieSeries);
418 if (d->setRealValue(d->m_pieRelativeHorPos, relativePosition, 1.0))
419 emit piePositionChanged();
420 }
391 421
392 By default both values are 0.5 which puts the pie in the middle of the chart rectangle.
422 /*!
423 Sets the vertical center position of the pie to \relativePosition. If \relativePosition is
424 set to 0.0 the pie is drawn on the top of the chart and if it's set to 1.0 the pie is drawn
425 on bottom of the chart. The default value 0.5 puts the pie in the middle.
393 426
394 \sa pieHorizontalPosition(), pieVerticalPosition(), setPieSize()
427 \sa setVerticalPosition(), setPieSize()
395 428 */
396 void QPieSeries::setPiePosition(qreal relativeHorizontalPosition, qreal relativeVerticalPosition)
429 void QPieSeries::setVerticalPosition(qreal relativePosition)
397 430 {
398 431 Q_D(QPieSeries);
399 if (relativeHorizontalPosition < 0.0 || relativeHorizontalPosition > 1.0 ||
400 relativeVerticalPosition < 0.0 || relativeVerticalPosition > 1.0)
401 return;
402
403 if (!qFuzzyIsNull(d->m_pieRelativeHorPos - relativeHorizontalPosition) ||
404 !qFuzzyIsNull(d->m_pieRelativeVerPos - relativeVerticalPosition)) {
405 d->m_pieRelativeHorPos = relativeHorizontalPosition;
406 d->m_pieRelativeVerPos = relativeVerticalPosition;
432 if (d->setRealValue(d->m_pieRelativeVerPos, relativePosition, 1.0))
407 433 emit piePositionChanged();
408 434 }
409 }
410 435
411 436 /*!
412 437 Gets the horizontal position of the pie.
413 438
414 439 The returned value is relative to the chart rectangle where:
415 440
416 441 0.0 means the absolute left.
417 442 1.0 means the absolute right.
418 443
419 444 By default it is 0.5 which puts the pie in the horizontal middle of the chart rectangle.
420 445
421 \sa setPiePosition(), pieVerticalPosition(), setPieSize()
446 \sa verticalPosition(), setPieSize()
422 447 */
423 qreal QPieSeries::pieHorizontalPosition() const
448 qreal QPieSeries::horizontalPosition() const
424 449 {
425 450 Q_D(const QPieSeries);
426 451 return d->m_pieRelativeHorPos;
427 452 }
428 453
429 454 /*!
430 455 Gets the vertical position position of the pie.
431 456
432 457 The returned value is relative to the chart rectangle where:
433 458
434 459 0.0 means the absolute top.
435 460 1.0 means the absolute bottom.
436 461
437 462 By default it is 0.5 which puts the pie in the vertical middle of the chart rectangle.
438 463
439 \sa setPiePosition(), pieHorizontalPosition(), setPieSize()
464 \sa horizontalPosition(), setPieSize()
440 465 */
441 qreal QPieSeries::pieVerticalPosition() const
466 qreal QPieSeries::verticalPosition() const
442 467 {
443 468 Q_D(const QPieSeries);
444 469 return d->m_pieRelativeVerPos;
445 470 }
446 471
447 472 /*!
448 473 Sets the relative size of the pie.
449 474
450 475 The \a relativeSize is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
451 476
452 477 Default value is 0.7.
453 478
454 479 \sa pieSize(), setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
455 480 */
456 481 void QPieSeries::setPieSize(qreal relativeSize)
457 482 {
458 483 Q_D(QPieSeries);
459 if (relativeSize < 0.0 || relativeSize > 1.0)
460 return;
461
462 if (!qFuzzyIsNull(d->m_pieRelativeSize- relativeSize)) {
463 d->m_pieRelativeSize = relativeSize;
484 if (d->setRealValue(d->m_pieRelativeSize, relativeSize, 1.0))
464 485 emit pieSizeChanged();
465 486 }
466 }
467 487
468 488 /*!
469 489 Gets the relative size of the pie.
470 490
471 491 The size is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
472 492
473 493 Default value is 0.7.
474 494
475 495 \sa setPieSize(), setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
476 496 */
477 497 qreal QPieSeries::pieSize() const
478 498 {
479 499 Q_D(const QPieSeries);
480 500 return d->m_pieRelativeSize;
481 501 }
482 502
483 503
484 504 /*!
485 505 Sets the end angle of the pie.
486 506
487 507 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
488 508
489 509 \a angle must be less than pie end angle. Default value is 0.
490 510
491 511 \sa pieStartAngle(), pieEndAngle(), setPieEndAngle()
492 512 */
493 513 void QPieSeries::setPieStartAngle(qreal angle)
494 514 {
495 515 Q_D(QPieSeries);
496
497 if (angle < 0 || angle > 360 || angle > d->m_pieEndAngle)
498 return;
499
500 if (!qFuzzyIsNull(angle - d->m_pieStartAngle)) {
501 d->m_pieStartAngle = angle;
516 if (d->setRealValue(d->m_pieStartAngle, angle, d->m_pieEndAngle))
502 517 d->updateDerivativeData();
503 518 }
504 }
505 519
506 520 /*!
507 521 Gets the start angle of the pie.
508 522
509 523 Full pie is 360 degrees where 0 degrees is at 12 a'clock. Default value is 360.
510 524
511 525 \sa setPieStartAngle(), pieEndAngle(), setPieEndAngle()
512 526 */
513 527 qreal QPieSeries::pieStartAngle() const
514 528 {
515 529 Q_D(const QPieSeries);
516 530 return d->m_pieStartAngle;
517 531 }
518 532
519 533 /*!
520 534 Sets the end angle of the pie.
521 535
522 536 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
523 537
524 538 \a angle must be greater than start angle.
525 539
526 540 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
527 541 */
528 542 void QPieSeries::setPieEndAngle(qreal angle)
529 543 {
530 544 Q_D(QPieSeries);
531 545
532 if (angle < 0 || angle > 360 || angle < d->m_pieStartAngle)
533 return;
534
535 if (!qFuzzyIsNull(angle - d->m_pieEndAngle)) {
536 d->m_pieEndAngle = angle;
546 if (d->setRealValue(d->m_pieEndAngle, angle, 360.0, d->m_pieStartAngle))
537 547 d->updateDerivativeData();
538 548 }
539 }
540 549
541 550 /*!
542 551 Returns the end angle of the pie.
543 552
544 553 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
545 554
546 555 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
547 556 */
548 557 qreal QPieSeries::pieEndAngle() const
549 558 {
550 559 Q_D(const QPieSeries);
551 560 return d->m_pieEndAngle;
552 561 }
553 562
554 563 /*!
555 564 Sets the all the slice labels \a visible or invisible.
556 565
557 566 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
558 567 */
559 568 void QPieSeries::setLabelsVisible(bool visible)
560 569 {
561 570 Q_D(QPieSeries);
562 571 foreach (QPieSlice* s, d->m_slices)
563 572 s->setLabelVisible(visible);
564 573 }
565 574
566 575 /*!
567 576 Returns the sum of all slice values in this series.
568 577
569 578 \sa QPieSlice::value(), QPieSlice::setValue()
570 579 */
571 580 qreal QPieSeries::total() const
572 581 {
573 582 Q_D(const QPieSeries);
574 583 return d->m_total;
575 584 }
576 585
577 586 /*!
578 587 \fn void QPieSeries::clicked(QPieSlice* slice, Qt::MouseButtons buttons)
579 588
580 589 This signal is emitted when a \a slice has been clicked with mouse \a buttons.
581 590
582 591 \sa QPieSlice::clicked()
583 592 */
584 593
585 594 /*!
586 595 \fn void QPieSeries::hoverEnter(QPieSlice* slice)
587 596
588 597 This signal is emitted when user has hovered over a \a slice.
589 598
590 599 \sa QPieSlice::hoverEnter()
591 600 */
592 601
593 602 /*!
594 603 \fn void QPieSeries::hoverLeave(QPieSlice* slice)
595 604
596 605 This signal is emitted when user has hovered away from a \a slice.
597 606
598 607 \sa QPieSlice::hoverLeave()
599 608 */
600 609
601 610 /*!
602 611 \fn void QPieSeries::added(QList<QPieSlice*> slices)
603 612
604 613 This signal is emitted when \a slices has been added to the series.
605 614
606 615 \sa append(), insert()
607 616 */
608 617
609 618 /*!
610 619 \fn void QPieSeries::removed(QList<QPieSlice*> slices)
611 620
612 621 This signal is emitted when \a slices has been removed from the series.
613 622
614 623 \sa remove(), clear()
615 624 */
616 625
617 626 /*!
618 627 \fn void QPieSeries::piePositionChanged()
619 628
620 629 This signal is emitted when pie position has changed.
621 630
622 631 \sa setPiePosition(), pieVerticalPosition(), pieHorizontalPosition()
623 632 */
624 633
625 634 /*!
626 635 \fn void QPieSeries::pieSizeChanged()
627 636
628 637 This signal is emitted when pie size has changed.
629 638
630 639 \sa pieSize(), setPieSize()
631 640 */
632 641
633 642 /*!
634 643 \fn bool QPieSeries::setModel(QAbstractItemModel *model)
635 644 Sets the \a model to be used as a data source
636 645 */
637 646 bool QPieSeries::setModel(QAbstractItemModel* model)
638 647 {
639 648 Q_D(QPieSeries);
640 649 // disconnect signals from old model
641 650 if(m_model)
642 651 {
643 652 disconnect(m_model, 0, this, 0);
644 653 d->m_mapValues = -1;
645 654 d->m_mapLabels = -1;
646 655 d->m_mapOrientation = Qt::Vertical;
647 656 }
648 657
649 658 // set new model
650 659 if(model)
651 660 {
652 661 m_model = model;
653 662 return true;
654 663 }
655 664 else
656 665 {
657 666 m_model = 0;
658 667 return false;
659 668 }
660 669 }
661 670
662 671 void QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
663 672 {
664 673 Q_D(QPieSeries);
665 674
666 675 if (m_model == 0)
667 676 return;
668 677
669 678 d->m_mapValues = modelValuesLine;
670 679 d->m_mapLabels = modelLabelsLine;
671 680 d->m_mapOrientation = orientation;
672 681
673 682 // connect the signals
674 683 if (d->m_mapOrientation == Qt::Vertical) {
675 684 connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex, QModelIndex)));
676 685 connect(m_model, SIGNAL(rowsInserted(QModelIndex, int, int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
677 686 connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
678 687 } else {
679 688 connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex, QModelIndex)));
680 689 connect(m_model, SIGNAL(columnsInserted(QModelIndex, int, int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
681 690 connect(m_model, SIGNAL(columnsRemoved(QModelIndex, int, int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
682 691 }
683 692
684 693 // create the initial slices set
685 694 if (d->m_mapOrientation == Qt::Vertical) {
686 695 for (int i = 0; i < m_model->rowCount(); i++)
687 696 append(m_model->data(m_model->index(i, d->m_mapValues), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(i, d->m_mapLabels), Qt::DisplayRole).toString());
688 697 } else {
689 698 for (int i = 0; i < m_model->columnCount(); i++)
690 699 append(m_model->data(m_model->index(d->m_mapValues, i), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(d->m_mapLabels, i), Qt::DisplayRole).toString());
691 700 }
692 701 }
693 702
694 703 #include "moc_qpieseries.cpp"
695 704 #include "moc_qpieseriesprivate_p.cpp"
696 705
697 706 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,96 +1,102
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 <qseries.h>
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27 class QPieSeriesPrivate;
28 28 class QPieSlice;
29 29
30 30 class QTCOMMERCIALCHART_EXPORT QPieSeries : public QSeries
31 31 {
32 32 Q_OBJECT
33 Q_PROPERTY(qreal horizontalPosition READ horizontalPosition WRITE setHorizontalPosition)
34 Q_PROPERTY(qreal verticalPosition READ verticalPosition WRITE setVerticalPosition)
35 Q_PROPERTY(qreal size READ pieSize WRITE setPieSize)
36 Q_PROPERTY(qreal startAngle READ pieStartAngle WRITE setPieStartAngle)
37 Q_PROPERTY(qreal endAngle READ pieEndAngle WRITE setPieEndAngle)
33 38
34 39 public:
35 40 QPieSeries(QObject *parent = 0);
36 41 virtual ~QPieSeries();
37 42
38 43 public: // from QChartSeries
39 44 QSeriesType type() const;
40 45
41 46 public:
42 47
43 48 // slice setters
44 49 void append(QPieSlice* slice);
45 50 void append(QList<QPieSlice*> slices);
46 51 void insert(int index, QPieSlice* slice);
47 52 void replace(QList<QPieSlice*> slices);
48 53 void remove(QPieSlice* slice);
49 54 void clear();
50 55
51 56 // slice getters
52 57 QList<QPieSlice*> slices() const;
53 58
54 59 // calculated data
55 60 int count() const;
56 61 bool isEmpty() const;
57 62 qreal total() const;
58 63
59 64 // pie customization
60 void setPiePosition(qreal relativeHorizontalPosition, qreal relativeVerticalPosition);
61 qreal pieHorizontalPosition() const;
62 qreal pieVerticalPosition() const;
65 void setHorizontalPosition(qreal relativePosition);
66 qreal horizontalPosition() const;
67 void setVerticalPosition(qreal relativePosition);
68 qreal verticalPosition() const;
63 69 void setPieSize(qreal relativeSize);
64 70 qreal pieSize() const;
65 71 void setPieStartAngle(qreal startAngle);
66 72 qreal pieStartAngle() const;
67 73 void setPieEndAngle(qreal endAngle);
68 74 qreal pieEndAngle() const;
69 75
70 76 // convenience function
71 77 QPieSeries& operator << (QPieSlice* slice);
72 78 QPieSlice* append(qreal value, QString name);
73 79 void setLabelsVisible(bool visible = true);
74 80
75 81 // data from model
76 82 bool setModel(QAbstractItemModel* model);
77 83 void setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation = Qt::Vertical);
78 84
79 85 Q_SIGNALS:
80 86 void clicked(QPieSlice* slice, Qt::MouseButtons buttons);
81 87 void hoverEnter(QPieSlice* slice);
82 88 void hoverLeave(QPieSlice* slice);
83 89 void added(QList<QPieSlice*> slices);
84 90 void removed(QList<QPieSlice*> slices);
85 91 void piePositionChanged();
86 92 void pieSizeChanged();
87 93
88 94 private:
89 95 QPieSeriesPrivate * const d_ptr;
90 96 Q_DECLARE_PRIVATE(QPieSeries)
91 97 Q_DISABLE_COPY(QPieSeries)
92 98 };
93 99
94 100 QTCOMMERCIALCHART_END_NAMESPACE
95 101
96 102 #endif // PIESERIES_H
@@ -1,69 +1,70
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 QPIESERIESPRIVATE_P_H
22 22 #define QPIESERIESPRIVATE_P_H
23 23
24 24 #include "qpieseries.h"
25 25
26 26 class QModelIndex;
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 class QPieSeriesPrivate : public QObject
31 31 {
32 32 Q_OBJECT
33 33 Q_DECLARE_PUBLIC(QPieSeries)
34 34
35 35 public:
36 36 QPieSeriesPrivate(QPieSeries *parent);
37 37 ~QPieSeriesPrivate();
38 38
39 39 void updateDerivativeData();
40 40
41 41 public Q_SLOTS:
42 42 void sliceChanged();
43 43 void sliceClicked(Qt::MouseButtons buttons);
44 44 void sliceHoverEnter();
45 45 void sliceHoverLeave();
46 46 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
47 47 void modelDataAdded(QModelIndex parent, int start, int end);
48 48 void modelDataRemoved(QModelIndex parent, int start, int end);
49 bool setRealValue(qreal &value, qreal newValue, qreal max, qreal min = 0.0);
49 50
50 51 public:
51 52 QPieSeries * const q_ptr;
52 53
53 54 QList<QPieSlice*> m_slices;
54 55 qreal m_pieRelativeHorPos;
55 56 qreal m_pieRelativeVerPos;
56 57 qreal m_pieRelativeSize;
57 58 qreal m_pieStartAngle;
58 59 qreal m_pieEndAngle;
59 60 qreal m_total;
60 61
61 62 // model map
62 63 int m_mapValues;
63 64 int m_mapLabels;
64 65 Qt::Orientation m_mapOrientation;
65 66 };
66 67
67 68 QTCOMMERCIALCHART_END_NAMESPACE
68 69
69 70 #endif // QPIESERIESPRIVATE_P_H
@@ -1,87 +1,86
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 "qseries.h"
22 22
23 23 /*!
24 24 \class QSeries
25 25 \brief Base class for all QtCommercial Chart series.
26 26 \mainclass
27 27
28 28 Usually you use the series type specific inherited classes instead of the base class.
29 29 \sa QScatterSeries
30 30 */
31 31
32 32 /*!
33 33 \enum QSeries::QSeriesType
34 34
35 35 The type of the series object.
36 36
37 37 \value SeriesTypeLine
38 38 \value SeriesTypeArea
39 39 \value SeriesTypeBar
40 40 \value SeriesTypeStackedBar
41 41 \value SeriesTypePercentBar
42 42 \value SeriesTypePie
43 43 \value SeriesTypeScatter
44 44 \value SeriesTypeSpline
45 45 */
46 46
47 47 /*!
48 48 \fn QSeries::QSeries(QObject *parent)
49 49 \brief Constructs ChartSeries object with \a parent.
50 50 */
51 51
52 52 /*!
53 53 \fn QSeries::~QSeries()
54 54 \brief Virtual destructor for the chart series.
55 55 */
56 56
57 57 /*!
58 58 \fn QSeriesType QSeries::type() const
59 59 \brief The type of the series.
60 60 */
61 61
62 62 /*!
63 63 \fn bool QSeries::setModel(QAbstractItemModel *model)
64 64 \brief Use the \a model to provide data for the series. The model overrides possible user data
65 65 set with QChartSeries type specific data setters. For example if you call both
66 66 QScatterSeries::addData() and QScatterSeries::setModel, only the data provided by the model is
67 67 used by the series. Returns true if the model is valid for the series.
68 68 */
69 69
70 70 /*!
71 71 \fn void QSeries::setName(QString name)
72 72 \brief Sets a \a name for the series.
73 73
74 74 The name of a series is shown in the legend for QXYSeries.
75 75 \sa QChart::setTitle()
76 76 \sa QPieSlice::setLabel()
77 77 \sa QBarSet::setName()
78 78 */
79 79
80 80 /*!
81 81 \fn QString QSeries::name()
82 82 \brief Returns the name of the series.
83 83 */
84 84
85 QTCOMMERCIALCHART_BEGIN_NAMESPACE
85 QTCOMMERCIALCHART_USE_NAMESPACE
86 86 #include "moc_qseries.cpp"
87 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,70 +1,72
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 QSERIES_H
22 22 #define QSERIES_H
23 23
24 24 #include <qchartglobal.h>
25 25 #include <QObject>
26 26 //#include <QAbstractItemModel>
27 27 #include <QPen>
28 28
29 29 class QAbstractItemModel;
30 30
31 31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 32
33 33 class QTCOMMERCIALCHART_EXPORT QSeries : public QObject
34 34 {
35 35 Q_OBJECT
36 Q_PROPERTY(QString name READ name WRITE setName)
37
36 38 public:
37 39 enum QSeriesType {
38 40 SeriesTypeLine,
39 41 SeriesTypeArea,
40 42 SeriesTypeBar,
41 43 SeriesTypeStackedBar,
42 44 SeriesTypePercentBar,
43 45 SeriesTypePie,
44 46 SeriesTypeScatter,
45 47 SeriesTypeSpline
46 48 };
47 49
48 50 protected:
49 51 QSeries(QObject *parent = 0) : QObject(parent) {m_model = 0;}
50 52
51 53 public:
52 54 virtual ~QSeries() {}
53 55 virtual QSeriesType type() const = 0;
54 56 // TODO
55 57 virtual bool setModel(QAbstractItemModel* /*model*/) { return false; }
56 58 QAbstractItemModel* model() const { return m_model; }
57 59
58 60 void setName(QString name) { m_name = name; }
59 61 QString name() const { return m_name; }
60 62
61 63 protected:
62 64 QAbstractItemModel* m_model;
63 65
64 66 private:
65 67 QString m_name;
66 68 };
67 69
68 70 QTCOMMERCIALCHART_END_NAMESPACE
69 71
70 72 #endif
@@ -1,136 +1,146
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 import QtQuick 1.0
22 22 import QtCommercial.Chart 1.0
23 23
24 24 Rectangle {
25 25 width: parent.width
26 26 height: parent.height
27 27
28 28 // Another option for QML data api:
29 29 // ListModel {
30 30 // id: listModelForPie
31 31 // // PieDataElement
32 32 // ListElement {
33 33 // label: "Apple"
34 34 // value: 4.3
35 35 // }
36 36 // ListElement {
37 37 // label: "Blackberry"
38 38 // value: 15.1
39 39 // }
40 40 // }
41 41
42 42 Component.onCompleted: {
43 43 // console.log("model:" + myModel.item(0));
44 44 // myModel.insert(1, {"time":1.4; "speed":41.1 });
45 45 // scatter.appendData();
46 46 // chart1.theme = Chart.ThemeHighContrast;
47 47 // chart2.theme = Chart.ThemeHighContrast;
48 48 }
49 49
50 50
51 51 Chart {
52 52 id: chart1
53 53 anchors.top: parent.top
54 54 anchors.left: parent.left
55 55 anchors.right: parent.right
56 56 height: parent.height / 2
57 57 theme: Chart.ChartThemeDark
58 58
59 59 BarSeries {
60 60 barCategories: [ "2008", "2009", "2010", "2011", "2012" ]
61 // TBD: data
61 62 }
62 63
63 64 PieSeries {
65 horizontalPosition: 0.2
66 verticalPosition: 0.3
67 size: 0.4
68 endAngle: 0.52 * 360 // The share of "others" is 52%
64 69 slices: [
65 70 PieSlice { label: "Volkswagen"; value: 13.5 },
66 71 PieSlice { label: "Toyota"; value: 10.9 },
67 72 PieSlice { label: "Ford"; value: 8.6 },
68 73 PieSlice { label: "Skoda"; value: 8.2 },
69 PieSlice { label: "Volvo"; value: 6.8 },
70 PieSlice { label: "Others"; value: 52.0 }
74 PieSlice { label: "Volvo"; value: 6.8 }
71 75 ]
72 76 }
73 77 }
74 78
75 79
76 80 Chart {
77 81 id: chart2
78 82 anchors.top: chart1.bottom
79 83 anchors.bottom: parent.bottom
80 84 anchors.left: parent.left
81 85 anchors.right: parent.right
82 86 theme: Chart.ChartThemeBrownSand
83 87
84 88 LineSeries {
89 name: "Line"
85 90 points: [
86 91 XyPoint { x: 0.0; y: 0.0 },
87 92 XyPoint { x: 1.1; y: 2.1 },
88 93 XyPoint { x: 2.9; y: 4.9 },
89 94 XyPoint { x: 3.2; y: 3.0 }
90 95 ]
91 96 }
92 97
93 98 SplineSeries {
99 name: "Spline"
94 100 points: [
95 101 XyPoint { x: 0.0; y: 0.3 },
96 102 XyPoint { x: 1.1; y: 3.2 },
97 103 XyPoint { x: 4.17; y: 3.15 }
98 104 ]
99 105 }
100 106
101 107 AreaSeries {
108 name: "Area"
102 109 points: [
103 110 XyPoint { x: 0.0; y: 1.1 },
104 111 XyPoint { x: 2.5; y: 3.6 },
105 112 XyPoint { x: 3.57; y: 2.55 }
106 113 ]
107 114 lowerPoints: [
108 115 XyPoint { x: 0.0; y: 0.0 },
109 116 XyPoint { x: 2.5; y: 0.0 },
110 117 XyPoint { x: 3.57; y: 0.0 }
111 118 ]
112 119 }
113 120
114 121 ScatterSeries {
122 name: "Scatter1"
115 123 points: [
116 124 XyPoint { x: 1.5; y: 1.5 },
117 125 XyPoint { x: 1.5; y: 1.6 },
118 126 XyPoint { x: 1.57; y: 1.55 }
119 127 ]
120 128 }
121 129 ScatterSeries {
130 name: "Scatter2"
122 131 points: [
123 132 XyPoint { x: 2.0; y: 2.0 },
124 133 XyPoint { x: 2.0; y: 2.1 },
125 134 XyPoint { x: 2.07; y: 2.05 }
126 135 ]
127 136 }
128 137 ScatterSeries {
138 name: "Scatter3"
129 139 points: [
130 140 XyPoint { x: 2.6; y: 2.6 },
131 141 XyPoint { x: 2.6; y: 2.7 },
132 142 XyPoint { x: 2.67; y: 2.65 }
133 143 ]
134 144 }
135 145 }
136 146 }
General Comments 0
You need to be logged in to leave comments. Login now