##// END OF EJS Templates
Bugfix: remove restrictions from pie start & end angles...
Jani Honkonen -
r1207:614787b7b70d
parent child
Show More
@@ -1,331 +1,331
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20 #include "mainwidget.h"
20 #include "mainwidget.h"
21 #include "customslice.h"
21 #include "customslice.h"
22 #include "pentool.h"
22 #include "pentool.h"
23 #include "brushtool.h"
23 #include "brushtool.h"
24 #include <QPushButton>
24 #include <QPushButton>
25 #include <QComboBox>
25 #include <QComboBox>
26 #include <QCheckBox>
26 #include <QCheckBox>
27 #include <QLabel>
27 #include <QLabel>
28 #include <QGroupBox>
28 #include <QGroupBox>
29 #include <QDoubleSpinBox>
29 #include <QDoubleSpinBox>
30 #include <QFormLayout>
30 #include <QFormLayout>
31 #include <QFontDialog>
31 #include <QFontDialog>
32 #include <QChartView>
32 #include <QChartView>
33 #include <QPieSeries>
33 #include <QPieSeries>
34
34
35 QTCOMMERCIALCHART_USE_NAMESPACE
35 QTCOMMERCIALCHART_USE_NAMESPACE
36
36
37 MainWidget::MainWidget(QWidget* parent)
37 MainWidget::MainWidget(QWidget* parent)
38 :QWidget(parent),
38 :QWidget(parent),
39 m_slice(0)
39 m_slice(0)
40 {
40 {
41 // create chart
41 // create chart
42 QChart *chart = new QChart;
42 QChart *chart = new QChart;
43 chart->setTitle("Piechart customization");
43 chart->setTitle("Piechart customization");
44 chart->setAnimationOptions(QChart::AllAnimations);
44 chart->setAnimationOptions(QChart::AllAnimations);
45
45
46 // create series
46 // create series
47 m_series = new QPieSeries();
47 m_series = new QPieSeries();
48 *m_series << new CustomSlice("Slice 1", 10.0);
48 *m_series << new CustomSlice("Slice 1", 10.0);
49 *m_series << new CustomSlice("Slice 2", 20.0);
49 *m_series << new CustomSlice("Slice 2", 20.0);
50 *m_series << new CustomSlice("Slice 3", 30.0);
50 *m_series << new CustomSlice("Slice 3", 30.0);
51 *m_series << new CustomSlice("Slice 4", 40.0);
51 *m_series << new CustomSlice("Slice 4", 40.0);
52 *m_series << new CustomSlice("Slice 5", 50.0);
52 *m_series << new CustomSlice("Slice 5", 50.0);
53 m_series->setLabelsVisible();
53 m_series->setLabelsVisible();
54 chart->addSeries(m_series);
54 chart->addSeries(m_series);
55
55
56 connect(m_series, SIGNAL(clicked(QPieSlice*)), this, SLOT(handleSliceClicked(QPieSlice*)));
56 connect(m_series, SIGNAL(clicked(QPieSlice*)), this, SLOT(handleSliceClicked(QPieSlice*)));
57
57
58 // chart settings
58 // chart settings
59 m_themeComboBox = new QComboBox();
59 m_themeComboBox = new QComboBox();
60 m_themeComboBox->addItem("Light", QChart::ChartThemeLight);
60 m_themeComboBox->addItem("Light", QChart::ChartThemeLight);
61 m_themeComboBox->addItem("BlueCerulean", QChart::ChartThemeBlueCerulean);
61 m_themeComboBox->addItem("BlueCerulean", QChart::ChartThemeBlueCerulean);
62 m_themeComboBox->addItem("Dark", QChart::ChartThemeDark);
62 m_themeComboBox->addItem("Dark", QChart::ChartThemeDark);
63 m_themeComboBox->addItem("BrownSand", QChart::ChartThemeBrownSand);
63 m_themeComboBox->addItem("BrownSand", QChart::ChartThemeBrownSand);
64 m_themeComboBox->addItem("BlueNcs", QChart::ChartThemeBlueNcs);
64 m_themeComboBox->addItem("BlueNcs", QChart::ChartThemeBlueNcs);
65 m_themeComboBox->addItem("High Contrast", QChart::ChartThemeHighContrast);
65 m_themeComboBox->addItem("High Contrast", QChart::ChartThemeHighContrast);
66 m_themeComboBox->addItem("Blue Icy", QChart::ChartThemeBlueIcy);
66 m_themeComboBox->addItem("Blue Icy", QChart::ChartThemeBlueIcy);
67
67
68 m_aaCheckBox = new QCheckBox();
68 m_aaCheckBox = new QCheckBox();
69 m_animationsCheckBox = new QCheckBox();
69 m_animationsCheckBox = new QCheckBox();
70 m_animationsCheckBox->setCheckState(Qt::Checked);
70 m_animationsCheckBox->setCheckState(Qt::Checked);
71
71
72 m_legendCheckBox = new QCheckBox();
72 m_legendCheckBox = new QCheckBox();
73
73
74 QFormLayout* chartSettingsLayout = new QFormLayout();
74 QFormLayout* chartSettingsLayout = new QFormLayout();
75 chartSettingsLayout->addRow("Theme", m_themeComboBox);
75 chartSettingsLayout->addRow("Theme", m_themeComboBox);
76 chartSettingsLayout->addRow("Antialiasing", m_aaCheckBox);
76 chartSettingsLayout->addRow("Antialiasing", m_aaCheckBox);
77 chartSettingsLayout->addRow("Animations", m_animationsCheckBox);
77 chartSettingsLayout->addRow("Animations", m_animationsCheckBox);
78 chartSettingsLayout->addRow("Legend", m_legendCheckBox);
78 chartSettingsLayout->addRow("Legend", m_legendCheckBox);
79 QGroupBox* chartSettings = new QGroupBox("Chart");
79 QGroupBox* chartSettings = new QGroupBox("Chart");
80 chartSettings->setLayout(chartSettingsLayout);
80 chartSettings->setLayout(chartSettingsLayout);
81
81
82 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this ,SLOT(updateChartSettings()));
82 connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this ,SLOT(updateChartSettings()));
83 connect(m_aaCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
83 connect(m_aaCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
84 connect(m_animationsCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
84 connect(m_animationsCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
85 connect(m_legendCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
85 connect(m_legendCheckBox, SIGNAL(toggled(bool)), this ,SLOT(updateChartSettings()));
86
86
87 // series settings
87 // series settings
88 m_hPosition = new QDoubleSpinBox();
88 m_hPosition = new QDoubleSpinBox();
89 m_hPosition->setMinimum(0.0);
89 m_hPosition->setMinimum(0.0);
90 m_hPosition->setMaximum(1.0);
90 m_hPosition->setMaximum(1.0);
91 m_hPosition->setSingleStep(0.1);
91 m_hPosition->setSingleStep(0.1);
92 m_hPosition->setValue(m_series->horizontalPosition());
92 m_hPosition->setValue(m_series->horizontalPosition());
93
93
94 m_vPosition = new QDoubleSpinBox();
94 m_vPosition = new QDoubleSpinBox();
95 m_vPosition->setMinimum(0.0);
95 m_vPosition->setMinimum(0.0);
96 m_vPosition->setMaximum(1.0);
96 m_vPosition->setMaximum(1.0);
97 m_vPosition->setSingleStep(0.1);
97 m_vPosition->setSingleStep(0.1);
98 m_vPosition->setValue(m_series->verticalPosition());
98 m_vPosition->setValue(m_series->verticalPosition());
99
99
100 m_sizeFactor = new QDoubleSpinBox();
100 m_sizeFactor = new QDoubleSpinBox();
101 m_sizeFactor->setMinimum(0.0);
101 m_sizeFactor->setMinimum(0.0);
102 m_sizeFactor->setMaximum(1.0);
102 m_sizeFactor->setMaximum(1.0);
103 m_sizeFactor->setSingleStep(0.1);
103 m_sizeFactor->setSingleStep(0.1);
104 m_sizeFactor->setValue(m_series->pieSize());
104 m_sizeFactor->setValue(m_series->pieSize());
105
105
106 m_startAngle = new QDoubleSpinBox();
106 m_startAngle = new QDoubleSpinBox();
107 m_startAngle->setMinimum(0.0);
107 m_startAngle->setMinimum(-720);
108 m_startAngle->setMaximum(360);
108 m_startAngle->setMaximum(720);
109 m_startAngle->setValue(m_series->pieStartAngle());
109 m_startAngle->setValue(m_series->pieStartAngle());
110 m_startAngle->setSingleStep(1);
110 m_startAngle->setSingleStep(1);
111
111
112 m_endAngle = new QDoubleSpinBox();
112 m_endAngle = new QDoubleSpinBox();
113 m_endAngle->setMinimum(0.0);
113 m_endAngle->setMinimum(-720);
114 m_endAngle->setMaximum(360);
114 m_endAngle->setMaximum(720);
115 m_endAngle->setValue(m_series->pieEndAngle());
115 m_endAngle->setValue(m_series->pieEndAngle());
116 m_endAngle->setSingleStep(1);
116 m_endAngle->setSingleStep(1);
117
117
118 QPushButton *appendSlice = new QPushButton("Append slice");
118 QPushButton *appendSlice = new QPushButton("Append slice");
119 QPushButton *insertSlice = new QPushButton("Insert slice");
119 QPushButton *insertSlice = new QPushButton("Insert slice");
120
120
121 QFormLayout* seriesSettingsLayout = new QFormLayout();
121 QFormLayout* seriesSettingsLayout = new QFormLayout();
122 seriesSettingsLayout->addRow("Horizontal position", m_hPosition);
122 seriesSettingsLayout->addRow("Horizontal position", m_hPosition);
123 seriesSettingsLayout->addRow("Vertical position", m_vPosition);
123 seriesSettingsLayout->addRow("Vertical position", m_vPosition);
124 seriesSettingsLayout->addRow("Size factor", m_sizeFactor);
124 seriesSettingsLayout->addRow("Size factor", m_sizeFactor);
125 seriesSettingsLayout->addRow("Start angle", m_startAngle);
125 seriesSettingsLayout->addRow("Start angle", m_startAngle);
126 seriesSettingsLayout->addRow("End angle", m_endAngle);
126 seriesSettingsLayout->addRow("End angle", m_endAngle);
127 seriesSettingsLayout->addRow(appendSlice);
127 seriesSettingsLayout->addRow(appendSlice);
128 seriesSettingsLayout->addRow(insertSlice);
128 seriesSettingsLayout->addRow(insertSlice);
129 QGroupBox* seriesSettings = new QGroupBox("Series");
129 QGroupBox* seriesSettings = new QGroupBox("Series");
130 seriesSettings->setLayout(seriesSettingsLayout);
130 seriesSettings->setLayout(seriesSettingsLayout);
131
131
132 connect(m_vPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
132 connect(m_vPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
133 connect(m_hPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
133 connect(m_hPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
134 connect(m_sizeFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
134 connect(m_sizeFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
135 connect(m_startAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
135 connect(m_startAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
136 connect(m_endAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
136 connect(m_endAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
137 connect(appendSlice, SIGNAL(clicked()), this, SLOT(appendSlice()));
137 connect(appendSlice, SIGNAL(clicked()), this, SLOT(appendSlice()));
138 connect(insertSlice, SIGNAL(clicked()), this, SLOT(insertSlice()));
138 connect(insertSlice, SIGNAL(clicked()), this, SLOT(insertSlice()));
139
139
140 // slice settings
140 // slice settings
141 m_sliceName = new QLabel("<click a slice>");
141 m_sliceName = new QLabel("<click a slice>");
142 m_sliceValue = new QDoubleSpinBox();
142 m_sliceValue = new QDoubleSpinBox();
143 m_sliceValue->setMaximum(1000);
143 m_sliceValue->setMaximum(1000);
144 m_sliceLabelVisible = new QCheckBox();
144 m_sliceLabelVisible = new QCheckBox();
145 m_sliceLabelArmFactor = new QDoubleSpinBox();
145 m_sliceLabelArmFactor = new QDoubleSpinBox();
146 m_sliceLabelArmFactor->setSingleStep(0.01);
146 m_sliceLabelArmFactor->setSingleStep(0.01);
147 m_sliceExploded = new QCheckBox();
147 m_sliceExploded = new QCheckBox();
148 m_sliceExplodedFactor = new QDoubleSpinBox();
148 m_sliceExplodedFactor = new QDoubleSpinBox();
149 m_sliceExplodedFactor->setSingleStep(0.01);
149 m_sliceExplodedFactor->setSingleStep(0.01);
150 m_pen = new QPushButton();
150 m_pen = new QPushButton();
151 m_penTool = new PenTool("Slice pen", this);
151 m_penTool = new PenTool("Slice pen", this);
152 m_brush = new QPushButton();
152 m_brush = new QPushButton();
153 m_brushTool = new BrushTool("Slice brush", this);
153 m_brushTool = new BrushTool("Slice brush", this);
154 m_font = new QPushButton();
154 m_font = new QPushButton();
155 m_labelPen = new QPushButton();
155 m_labelPen = new QPushButton();
156 m_labelPenTool = new PenTool("Label pen", this);
156 m_labelPenTool = new PenTool("Label pen", this);
157 QPushButton *removeSlice = new QPushButton("Remove slice");
157 QPushButton *removeSlice = new QPushButton("Remove slice");
158
158
159 QFormLayout* sliceSettingsLayout = new QFormLayout();
159 QFormLayout* sliceSettingsLayout = new QFormLayout();
160 sliceSettingsLayout->addRow("Selected", m_sliceName);
160 sliceSettingsLayout->addRow("Selected", m_sliceName);
161 sliceSettingsLayout->addRow("Value", m_sliceValue);
161 sliceSettingsLayout->addRow("Value", m_sliceValue);
162 sliceSettingsLayout->addRow("Pen", m_pen);
162 sliceSettingsLayout->addRow("Pen", m_pen);
163 sliceSettingsLayout->addRow("Brush", m_brush);
163 sliceSettingsLayout->addRow("Brush", m_brush);
164 sliceSettingsLayout->addRow("Label visible", m_sliceLabelVisible);
164 sliceSettingsLayout->addRow("Label visible", m_sliceLabelVisible);
165 sliceSettingsLayout->addRow("Label font", m_font);
165 sliceSettingsLayout->addRow("Label font", m_font);
166 sliceSettingsLayout->addRow("Label pen", m_labelPen);
166 sliceSettingsLayout->addRow("Label pen", m_labelPen);
167 sliceSettingsLayout->addRow("Label arm length", m_sliceLabelArmFactor);
167 sliceSettingsLayout->addRow("Label arm length", m_sliceLabelArmFactor);
168 sliceSettingsLayout->addRow("Exploded", m_sliceExploded);
168 sliceSettingsLayout->addRow("Exploded", m_sliceExploded);
169 sliceSettingsLayout->addRow("Explode distance", m_sliceExplodedFactor);
169 sliceSettingsLayout->addRow("Explode distance", m_sliceExplodedFactor);
170 sliceSettingsLayout->addRow(removeSlice);
170 sliceSettingsLayout->addRow(removeSlice);
171 QGroupBox* sliceSettings = new QGroupBox("Slice");
171 QGroupBox* sliceSettings = new QGroupBox("Slice");
172 sliceSettings->setLayout(sliceSettingsLayout);
172 sliceSettings->setLayout(sliceSettingsLayout);
173
173
174 connect(m_sliceValue, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
174 connect(m_sliceValue, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
175 connect(m_pen, SIGNAL(clicked()), m_penTool, SLOT(show()));
175 connect(m_pen, SIGNAL(clicked()), m_penTool, SLOT(show()));
176 connect(m_penTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
176 connect(m_penTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
177 connect(m_brush, SIGNAL(clicked()), m_brushTool, SLOT(show()));
177 connect(m_brush, SIGNAL(clicked()), m_brushTool, SLOT(show()));
178 connect(m_brushTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
178 connect(m_brushTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
179 connect(m_font, SIGNAL(clicked()), this, SLOT(showFontDialog()));
179 connect(m_font, SIGNAL(clicked()), this, SLOT(showFontDialog()));
180 connect(m_labelPen, SIGNAL(clicked()), m_labelPenTool, SLOT(show()));
180 connect(m_labelPen, SIGNAL(clicked()), m_labelPenTool, SLOT(show()));
181 connect(m_labelPenTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
181 connect(m_labelPenTool, SIGNAL(changed()), this, SLOT(updateSliceSettings()));
182 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
182 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
183 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
183 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
184 connect(m_sliceLabelArmFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
184 connect(m_sliceLabelArmFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
185 connect(m_sliceExploded, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
185 connect(m_sliceExploded, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
186 connect(m_sliceExplodedFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
186 connect(m_sliceExplodedFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
187 connect(removeSlice, SIGNAL(clicked()), this, SLOT(removeSlice()));
187 connect(removeSlice, SIGNAL(clicked()), this, SLOT(removeSlice()));
188
188
189 // create chart view
189 // create chart view
190 m_chartView = new QChartView(chart);
190 m_chartView = new QChartView(chart);
191
191
192 // create main layout
192 // create main layout
193 QVBoxLayout *settingsLayout = new QVBoxLayout();
193 QVBoxLayout *settingsLayout = new QVBoxLayout();
194 settingsLayout->addWidget(chartSettings);
194 settingsLayout->addWidget(chartSettings);
195 settingsLayout->addWidget(seriesSettings);
195 settingsLayout->addWidget(seriesSettings);
196 settingsLayout->addWidget(sliceSettings);
196 settingsLayout->addWidget(sliceSettings);
197 settingsLayout->addStretch();
197 settingsLayout->addStretch();
198
198
199 QGridLayout* baseLayout = new QGridLayout();
199 QGridLayout* baseLayout = new QGridLayout();
200 baseLayout->addLayout(settingsLayout, 0, 0);
200 baseLayout->addLayout(settingsLayout, 0, 0);
201 baseLayout->addWidget(m_chartView, 0, 1);
201 baseLayout->addWidget(m_chartView, 0, 1);
202 setLayout(baseLayout);
202 setLayout(baseLayout);
203
203
204 updateSerieSettings();
204 updateSerieSettings();
205 }
205 }
206
206
207
207
208 void MainWidget::updateChartSettings()
208 void MainWidget::updateChartSettings()
209 {
209 {
210 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
210 QChart::ChartTheme theme = (QChart::ChartTheme) m_themeComboBox->itemData(m_themeComboBox->currentIndex()).toInt();
211 m_chartView->chart()->setTheme(theme);
211 m_chartView->chart()->setTheme(theme);
212 m_chartView->setRenderHint(QPainter::Antialiasing, m_aaCheckBox->isChecked());
212 m_chartView->setRenderHint(QPainter::Antialiasing, m_aaCheckBox->isChecked());
213
213
214 if (m_animationsCheckBox->checkState() == Qt::Checked)
214 if (m_animationsCheckBox->checkState() == Qt::Checked)
215 m_chartView->chart()->setAnimationOptions(QChart::AllAnimations);
215 m_chartView->chart()->setAnimationOptions(QChart::AllAnimations);
216 else
216 else
217 m_chartView->chart()->setAnimationOptions(QChart::NoAnimation);
217 m_chartView->chart()->setAnimationOptions(QChart::NoAnimation);
218
218
219 if (m_legendCheckBox->checkState() == Qt::Checked)
219 if (m_legendCheckBox->checkState() == Qt::Checked)
220 m_chartView->chart()->legend()->show();
220 m_chartView->chart()->legend()->show();
221 else
221 else
222 m_chartView->chart()->legend()->hide();
222 m_chartView->chart()->legend()->hide();
223 }
223 }
224
224
225 void MainWidget::updateSerieSettings()
225 void MainWidget::updateSerieSettings()
226 {
226 {
227 m_series->setHorizontalPosition(m_hPosition->value());
227 m_series->setHorizontalPosition(m_hPosition->value());
228 m_series->setVerticalPosition(m_vPosition->value());
228 m_series->setVerticalPosition(m_vPosition->value());
229 m_series->setPieSize(m_sizeFactor->value());
229 m_series->setPieSize(m_sizeFactor->value());
230 m_series->setPieStartAngle(m_startAngle->value());
230 m_series->setPieStartAngle(m_startAngle->value());
231 m_series->setPieEndAngle(m_endAngle->value());
231 m_series->setPieEndAngle(m_endAngle->value());
232 }
232 }
233
233
234 void MainWidget::updateSliceSettings()
234 void MainWidget::updateSliceSettings()
235 {
235 {
236 if (!m_slice)
236 if (!m_slice)
237 return;
237 return;
238
238
239 m_slice->setValue(m_sliceValue->value());
239 m_slice->setValue(m_sliceValue->value());
240
240
241 m_slice->setPen(m_penTool->pen());
241 m_slice->setPen(m_penTool->pen());
242 m_slice->setBrush(m_brushTool->brush());
242 m_slice->setBrush(m_brushTool->brush());
243
243
244 m_slice->setLabelPen(m_labelPenTool->pen());
244 m_slice->setLabelPen(m_labelPenTool->pen());
245 m_slice->setLabelVisible(m_sliceLabelVisible->isChecked());
245 m_slice->setLabelVisible(m_sliceLabelVisible->isChecked());
246 m_slice->setLabelArmLengthFactor(m_sliceLabelArmFactor->value());
246 m_slice->setLabelArmLengthFactor(m_sliceLabelArmFactor->value());
247
247
248 m_slice->setExploded(m_sliceExploded->isChecked());
248 m_slice->setExploded(m_sliceExploded->isChecked());
249 m_slice->setExplodeDistanceFactor(m_sliceExplodedFactor->value());
249 m_slice->setExplodeDistanceFactor(m_sliceExplodedFactor->value());
250 }
250 }
251
251
252 void MainWidget::handleSliceClicked(QPieSlice* slice)
252 void MainWidget::handleSliceClicked(QPieSlice* slice)
253 {
253 {
254 m_slice = static_cast<CustomSlice*>(slice);
254 m_slice = static_cast<CustomSlice*>(slice);
255
255
256 // name
256 // name
257 m_sliceName->setText(slice->label());
257 m_sliceName->setText(slice->label());
258
258
259 // value
259 // value
260 m_sliceValue->blockSignals(true);
260 m_sliceValue->blockSignals(true);
261 m_sliceValue->setValue(slice->value());
261 m_sliceValue->setValue(slice->value());
262 m_sliceValue->blockSignals(false);
262 m_sliceValue->blockSignals(false);
263
263
264 // pen
264 // pen
265 m_pen->setText(PenTool::name(m_slice->pen()));
265 m_pen->setText(PenTool::name(m_slice->pen()));
266 m_penTool->setPen(m_slice->pen());
266 m_penTool->setPen(m_slice->pen());
267
267
268 // brush
268 // brush
269 m_brush->setText(m_slice->originalBrush().color().name());
269 m_brush->setText(m_slice->originalBrush().color().name());
270 m_brushTool->setBrush(m_slice->originalBrush());
270 m_brushTool->setBrush(m_slice->originalBrush());
271
271
272 // label
272 // label
273 m_labelPen->setText(PenTool::name(m_slice->labelPen()));
273 m_labelPen->setText(PenTool::name(m_slice->labelPen()));
274 m_labelPenTool->setPen(m_slice->labelPen());
274 m_labelPenTool->setPen(m_slice->labelPen());
275 m_font->setText(slice->labelFont().toString());
275 m_font->setText(slice->labelFont().toString());
276 m_sliceLabelVisible->blockSignals(true);
276 m_sliceLabelVisible->blockSignals(true);
277 m_sliceLabelVisible->setChecked(slice->isLabelVisible());
277 m_sliceLabelVisible->setChecked(slice->isLabelVisible());
278 m_sliceLabelVisible->blockSignals(false);
278 m_sliceLabelVisible->blockSignals(false);
279 m_sliceLabelArmFactor->blockSignals(true);
279 m_sliceLabelArmFactor->blockSignals(true);
280 m_sliceLabelArmFactor->setValue(slice->labelArmLengthFactor());
280 m_sliceLabelArmFactor->setValue(slice->labelArmLengthFactor());
281 m_sliceLabelArmFactor->blockSignals(false);
281 m_sliceLabelArmFactor->blockSignals(false);
282
282
283 // exploded
283 // exploded
284 m_sliceExploded->blockSignals(true);
284 m_sliceExploded->blockSignals(true);
285 m_sliceExploded->setChecked(slice->isExploded());
285 m_sliceExploded->setChecked(slice->isExploded());
286 m_sliceExploded->blockSignals(false);
286 m_sliceExploded->blockSignals(false);
287 m_sliceExplodedFactor->blockSignals(true);
287 m_sliceExplodedFactor->blockSignals(true);
288 m_sliceExplodedFactor->setValue(slice->explodeDistanceFactor());
288 m_sliceExplodedFactor->setValue(slice->explodeDistanceFactor());
289 m_sliceExplodedFactor->blockSignals(false);
289 m_sliceExplodedFactor->blockSignals(false);
290 }
290 }
291
291
292 void MainWidget::showFontDialog()
292 void MainWidget::showFontDialog()
293 {
293 {
294 if (!m_slice)
294 if (!m_slice)
295 return;
295 return;
296
296
297 QFontDialog dialog(m_slice->labelFont());
297 QFontDialog dialog(m_slice->labelFont());
298 dialog.show();
298 dialog.show();
299 dialog.exec();
299 dialog.exec();
300
300
301 m_slice->setLabelFont(dialog.currentFont());
301 m_slice->setLabelFont(dialog.currentFont());
302 m_font->setText(dialog.currentFont().toString());
302 m_font->setText(dialog.currentFont().toString());
303 }
303 }
304
304
305 void MainWidget::appendSlice()
305 void MainWidget::appendSlice()
306 {
306 {
307 *m_series << new CustomSlice("Slice " + QString::number(m_series->count()+1), 10.0);
307 *m_series << new CustomSlice("Slice " + QString::number(m_series->count()+1), 10.0);
308 }
308 }
309
309
310 void MainWidget::insertSlice()
310 void MainWidget::insertSlice()
311 {
311 {
312 if (!m_slice)
312 if (!m_slice)
313 return;
313 return;
314
314
315 int i = m_series->slices().indexOf(m_slice);
315 int i = m_series->slices().indexOf(m_slice);
316
316
317 m_series->insert(i, new CustomSlice("Slice " + QString::number(m_series->count()+1), 10.0));
317 m_series->insert(i, new CustomSlice("Slice " + QString::number(m_series->count()+1), 10.0));
318 }
318 }
319
319
320 void MainWidget::removeSlice()
320 void MainWidget::removeSlice()
321 {
321 {
322 if (!m_slice)
322 if (!m_slice)
323 return;
323 return;
324
324
325 m_sliceName->setText("<click a slice>");
325 m_sliceName->setText("<click a slice>");
326
326
327 m_series->remove(m_slice);
327 m_series->remove(m_slice);
328 m_slice = 0;
328 m_slice = 0;
329 }
329 }
330
330
331 #include "moc_mainwidget.cpp"
331 #include "moc_mainwidget.cpp"
@@ -1,813 +1,816
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qpieseries.h"
21 #include "qpieseries.h"
22 #include "qpieseries_p.h"
22 #include "qpieseries_p.h"
23 #include "qpieslice.h"
23 #include "qpieslice.h"
24 #include "pieslicedata_p.h"
24 #include "pieslicedata_p.h"
25 #include "chartdataset_p.h"
25 #include "chartdataset_p.h"
26 #include "charttheme_p.h"
26 #include "charttheme_p.h"
27 #include "chartanimator_p.h"
27 #include "chartanimator_p.h"
28 #include "legendmarker_p.h"
28 #include "legendmarker_p.h"
29 #include <QAbstractItemModel>
29 #include <QAbstractItemModel>
30 #include "qpiemodelmapper.h"
30 #include "qpiemodelmapper.h"
31
31
32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33
33
34 /*!
34 /*!
35 \class QPieSeries
35 \class QPieSeries
36 \brief Pie series API for QtCommercial Charts
36 \brief Pie series API for QtCommercial Charts
37
37
38 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
38 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
39 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
39 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
40 The actual slice size is determined by that relative value.
40 The actual slice size is determined by that relative value.
41
41
42 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
42 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
43 These relate to the actual chart rectangle.
43 These relate to the actual chart rectangle.
44
44
45 By default the pie is defined as a full pie but it can also be a partial pie.
45 By default the pie is defined as a full pie but it can also be a partial pie.
46 This can be done by setting a starting angle and angle span to the series.
46 This can be done by setting a starting angle and angle span to the series.
47 Full pie is 360 degrees where 0 is at 12 a'clock.
47 Full pie is 360 degrees where 0 is at 12 a'clock.
48
48
49 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
49 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
50 \image examples_piechart.png
50 \image examples_piechart.png
51 */
51 */
52
52
53 /*!
53 /*!
54 \property QPieSeries::horizontalPosition
54 \property QPieSeries::horizontalPosition
55 \brief Defines the horizontal position of the pie.
55 \brief Defines the horizontal position of the pie.
56
56
57 The value is a relative value to the chart rectangle where:
57 The value is a relative value to the chart rectangle where:
58
58
59 \list
59 \list
60 \o 0.0 is the absolute left.
60 \o 0.0 is the absolute left.
61 \o 1.0 is the absolute right.
61 \o 1.0 is the absolute right.
62 \endlist
62 \endlist
63
63
64 Default value is 0.5 (center).
64 Default value is 0.5 (center).
65 */
65 */
66
66
67 /*!
67 /*!
68 \property QPieSeries::verticalPosition
68 \property QPieSeries::verticalPosition
69 \brief Defines the vertical position of the pie.
69 \brief Defines the vertical position of the pie.
70
70
71 The value is a relative value to the chart rectangle where:
71 The value is a relative value to the chart rectangle where:
72
72
73 \list
73 \list
74 \o 0.0 is the absolute top.
74 \o 0.0 is the absolute top.
75 \o 1.0 is the absolute bottom.
75 \o 1.0 is the absolute bottom.
76 \endlist
76 \endlist
77
77
78 Default value is 0.5 (center).
78 Default value is 0.5 (center).
79 */
79 */
80
80
81 /*!
81 /*!
82 \property QPieSeries::size
82 \property QPieSeries::size
83 \brief Defines the pie size.
83 \brief Defines the pie size.
84
84
85 The value is a relative value to the chart rectangle where:
85 The value is a relative value to the chart rectangle where:
86
86
87 \list
87 \list
88 \o 0.0 is the minimum size (pie not drawn).
88 \o 0.0 is the minimum size (pie not drawn).
89 \o 1.0 is the maximum size that can fit the chart.
89 \o 1.0 is the maximum size that can fit the chart.
90 \endlist
90 \endlist
91
91
92 Default value is 0.7.
92 Default value is 0.7.
93 */
93 */
94
94
95 /*!
95 /*!
96 \property QPieSeries::startAngle
96 \property QPieSeries::startAngle
97 \brief Defines the starting angle of the pie.
97 \brief Defines the starting angle of the pie.
98
98
99 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
99 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
100
100
101 Default is value is 0.
101 Default is value is 0.
102 */
102 */
103
103
104 /*!
104 /*!
105 \property QPieSeries::endAngle
105 \property QPieSeries::endAngle
106 \brief Defines the ending angle of the pie.
106 \brief Defines the ending angle of the pie.
107
107
108 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
108 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
109
109
110 Default is value is 360.
110 Default is value is 360.
111 */
111 */
112
112
113
113
114 /*!
114 /*!
115 Constructs a series object which is a child of \a parent.
115 Constructs a series object which is a child of \a parent.
116 */
116 */
117 QPieSeries::QPieSeries(QObject *parent) :
117 QPieSeries::QPieSeries(QObject *parent) :
118 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
118 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
119 {
119 {
120
120
121 }
121 }
122
122
123 /*!
123 /*!
124 Destroys the series and its slices.
124 Destroys the series and its slices.
125 */
125 */
126 QPieSeries::~QPieSeries()
126 QPieSeries::~QPieSeries()
127 {
127 {
128 // NOTE: d_prt destroyed by QObject
128 // NOTE: d_prt destroyed by QObject
129 }
129 }
130
130
131 /*!
131 /*!
132 Returns QChartSeries::SeriesTypePie.
132 Returns QChartSeries::SeriesTypePie.
133 */
133 */
134 QAbstractSeries::SeriesType QPieSeries::type() const
134 QAbstractSeries::SeriesType QPieSeries::type() const
135 {
135 {
136 return QAbstractSeries::SeriesTypePie;
136 return QAbstractSeries::SeriesTypePie;
137 }
137 }
138
138
139 /*!
139 /*!
140 Appends an array of \a slices to the series.
140 Appends an array of \a slices to the series.
141 Slice ownership is passed to the series.
141 Slice ownership is passed to the series.
142 */
142 */
143 bool QPieSeries::append(QList<QPieSlice*> slices)
143 bool QPieSeries::append(QList<QPieSlice*> slices)
144 {
144 {
145 Q_D(QPieSeries);
145 Q_D(QPieSeries);
146
146
147 if (slices.count() == 0)
147 if (slices.count() == 0)
148 return false;
148 return false;
149
149
150 foreach (QPieSlice* s, slices) {
150 foreach (QPieSlice* s, slices) {
151 if (!s || d->m_slices.contains(s))
151 if (!s || d->m_slices.contains(s))
152 return false;
152 return false;
153 }
153 }
154
154
155 foreach (QPieSlice* s, slices) {
155 foreach (QPieSlice* s, slices) {
156 s->setParent(this);
156 s->setParent(this);
157 d->m_slices << s;
157 d->m_slices << s;
158 }
158 }
159
159
160 d->updateDerivativeData();
160 d->updateDerivativeData();
161
161
162 foreach (QPieSlice* s, slices) {
162 foreach (QPieSlice* s, slices) {
163 connect(s, SIGNAL(changed()), d, SLOT(sliceChanged()));
163 connect(s, SIGNAL(changed()), d, SLOT(sliceChanged()));
164 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
164 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
165 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
165 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
166 }
166 }
167
167
168 emit d->added(slices);
168 emit d->added(slices);
169
169
170 return true;
170 return true;
171 }
171 }
172
172
173 /*!
173 /*!
174 Appends a single \a slice to the series.
174 Appends a single \a slice to the series.
175 Slice ownership is passed to the series.
175 Slice ownership is passed to the series.
176 */
176 */
177 bool QPieSeries::append(QPieSlice* slice)
177 bool QPieSeries::append(QPieSlice* slice)
178 {
178 {
179 return append(QList<QPieSlice*>() << slice);
179 return append(QList<QPieSlice*>() << slice);
180 }
180 }
181
181
182 /*!
182 /*!
183 Appends a single \a slice to the series and returns a reference to the series.
183 Appends a single \a slice to the series and returns a reference to the series.
184 Slice ownership is passed to the series.
184 Slice ownership is passed to the series.
185 */
185 */
186 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
186 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
187 {
187 {
188 append(slice);
188 append(slice);
189 return *this;
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 label.
194 Appends a single slice to the series with give \a value and \a label.
195 Slice ownership is passed to the series.
195 Slice ownership is passed to the series.
196 */
196 */
197 QPieSlice* QPieSeries::append(QString label, qreal value)
197 QPieSlice* QPieSeries::append(QString label, qreal value)
198 {
198 {
199 QPieSlice* slice = new QPieSlice(label, value);
199 QPieSlice* slice = new QPieSlice(label, value);
200 append(slice);
200 append(slice);
201 return slice;
201 return slice;
202 }
202 }
203
203
204 /*!
204 /*!
205 Inserts a single \a slice to the series before the slice at \a index position.
205 Inserts a single \a slice to the series before the slice at \a index position.
206 Slice ownership is passed to the series.
206 Slice ownership is passed to the series.
207 */
207 */
208 bool QPieSeries::insert(int index, QPieSlice* slice)
208 bool QPieSeries::insert(int index, QPieSlice* slice)
209 {
209 {
210 Q_D(QPieSeries);
210 Q_D(QPieSeries);
211
211
212 if (index < 0 || index > d->m_slices.count())
212 if (index < 0 || index > d->m_slices.count())
213 return false;
213 return false;
214
214
215 if (!slice || d->m_slices.contains(slice))
215 if (!slice || d->m_slices.contains(slice))
216 return false;
216 return false;
217
217
218 slice->setParent(this);
218 slice->setParent(this);
219 d->m_slices.insert(index, slice);
219 d->m_slices.insert(index, slice);
220
220
221 d->updateDerivativeData();
221 d->updateDerivativeData();
222
222
223 connect(slice, SIGNAL(changed()), d, SLOT(sliceChanged()));
223 connect(slice, SIGNAL(changed()), d, SLOT(sliceChanged()));
224 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
224 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
225 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
225 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
226
226
227 emit d->added(QList<QPieSlice*>() << slice);
227 emit d->added(QList<QPieSlice*>() << slice);
228
228
229 return true;
229 return true;
230 }
230 }
231
231
232 /*!
232 /*!
233 Removes a single \a slice from the series and deletes the slice.
233 Removes a single \a slice from the series and deletes the slice.
234
234
235 Do not reference the pointer after this call.
235 Do not reference the pointer after this call.
236 */
236 */
237 bool QPieSeries::remove(QPieSlice* slice)
237 bool QPieSeries::remove(QPieSlice* slice)
238 {
238 {
239 Q_D(QPieSeries);
239 Q_D(QPieSeries);
240
240
241 if (!d->m_slices.removeOne(slice))
241 if (!d->m_slices.removeOne(slice))
242 return false;
242 return false;
243
243
244 d->updateDerivativeData();
244 d->updateDerivativeData();
245
245
246 emit d->removed(QList<QPieSlice*>() << slice);
246 emit d->removed(QList<QPieSlice*>() << slice);
247
247
248 delete slice;
248 delete slice;
249 slice = 0;
249 slice = 0;
250
250
251 return true;
251 return true;
252 }
252 }
253
253
254 /*!
254 /*!
255 Clears all slices from the series.
255 Clears all slices from the series.
256 */
256 */
257 void QPieSeries::clear()
257 void QPieSeries::clear()
258 {
258 {
259 Q_D(QPieSeries);
259 Q_D(QPieSeries);
260 if (d->m_slices.count() == 0)
260 if (d->m_slices.count() == 0)
261 return;
261 return;
262
262
263 QList<QPieSlice*> slices = d->m_slices;
263 QList<QPieSlice*> slices = d->m_slices;
264 foreach (QPieSlice* s, d->m_slices) {
264 foreach (QPieSlice* s, d->m_slices) {
265 d->m_slices.removeOne(s);
265 d->m_slices.removeOne(s);
266 delete s;
266 delete s;
267 }
267 }
268
268
269 d->updateDerivativeData();
269 d->updateDerivativeData();
270
270
271 emit d->removed(slices);
271 emit d->removed(slices);
272 }
272 }
273
273
274 /*!
274 /*!
275 returns the number of the slices in this series.
275 returns the number of the slices in this series.
276 */
276 */
277 int QPieSeries::count() const
277 int QPieSeries::count() const
278 {
278 {
279 Q_D(const QPieSeries);
279 Q_D(const QPieSeries);
280 return d->m_slices.count();
280 return d->m_slices.count();
281 }
281 }
282
282
283 /*!
283 /*!
284 Returns true is the series is empty.
284 Returns true is the series is empty.
285 */
285 */
286 bool QPieSeries::isEmpty() const
286 bool QPieSeries::isEmpty() const
287 {
287 {
288 Q_D(const QPieSeries);
288 Q_D(const QPieSeries);
289 return d->m_slices.isEmpty();
289 return d->m_slices.isEmpty();
290 }
290 }
291
291
292 /*!
292 /*!
293 Returns a list of slices that belong to this series.
293 Returns a list of slices that belong to this series.
294 */
294 */
295 QList<QPieSlice*> QPieSeries::slices() const
295 QList<QPieSlice*> QPieSeries::slices() const
296 {
296 {
297 Q_D(const QPieSeries);
297 Q_D(const QPieSeries);
298 return d->m_slices;
298 return d->m_slices;
299 }
299 }
300
300
301 void QPieSeries::setHorizontalPosition(qreal relativePosition)
301 void QPieSeries::setHorizontalPosition(qreal relativePosition)
302 {
302 {
303 Q_D(QPieSeries);
303 Q_D(QPieSeries);
304 if (d->setRealValue(d->m_pieRelativeHorPos, relativePosition, 1.0))
304 if (d->setRealValue(d->m_pieRelativeHorPos, relativePosition, 1.0))
305 emit d->piePositionChanged();
305 emit d->piePositionChanged();
306 }
306 }
307
307
308 void QPieSeries::setVerticalPosition(qreal relativePosition)
308 void QPieSeries::setVerticalPosition(qreal relativePosition)
309 {
309 {
310 Q_D(QPieSeries);
310 Q_D(QPieSeries);
311 if (d->setRealValue(d->m_pieRelativeVerPos, relativePosition, 1.0))
311 if (d->setRealValue(d->m_pieRelativeVerPos, relativePosition, 1.0))
312 emit d->piePositionChanged();
312 emit d->piePositionChanged();
313 }
313 }
314
314
315 qreal QPieSeries::horizontalPosition() const
315 qreal QPieSeries::horizontalPosition() const
316 {
316 {
317 Q_D(const QPieSeries);
317 Q_D(const QPieSeries);
318 return d->m_pieRelativeHorPos;
318 return d->m_pieRelativeHorPos;
319 }
319 }
320
320
321 qreal QPieSeries::verticalPosition() const
321 qreal QPieSeries::verticalPosition() const
322 {
322 {
323 Q_D(const QPieSeries);
323 Q_D(const QPieSeries);
324 return d->m_pieRelativeVerPos;
324 return d->m_pieRelativeVerPos;
325 }
325 }
326
326
327 void QPieSeries::setPieSize(qreal relativeSize)
327 void QPieSeries::setPieSize(qreal relativeSize)
328 {
328 {
329 Q_D(QPieSeries);
329 Q_D(QPieSeries);
330 if (d->setRealValue(d->m_pieRelativeSize, relativeSize, 1.0))
330 if (d->setRealValue(d->m_pieRelativeSize, relativeSize, 1.0))
331 emit d->pieSizeChanged();
331 emit d->pieSizeChanged();
332 }
332 }
333
333
334 qreal QPieSeries::pieSize() const
334 qreal QPieSeries::pieSize() const
335 {
335 {
336 Q_D(const QPieSeries);
336 Q_D(const QPieSeries);
337 return d->m_pieRelativeSize;
337 return d->m_pieRelativeSize;
338 }
338 }
339
339
340
340
341 void QPieSeries::setPieStartAngle(qreal angle)
341 void QPieSeries::setPieStartAngle(qreal angle)
342 {
342 {
343 Q_D(QPieSeries);
343 Q_D(QPieSeries);
344 if (d->setRealValue(d->m_pieStartAngle, angle, d->m_pieEndAngle))
344 if (qFuzzyIsNull(d->m_pieStartAngle - angle))
345 d->updateDerivativeData();
345 return;
346 d->m_pieStartAngle = angle;
347 d->updateDerivativeData();
346 }
348 }
347
349
348 qreal QPieSeries::pieStartAngle() const
350 qreal QPieSeries::pieStartAngle() const
349 {
351 {
350 Q_D(const QPieSeries);
352 Q_D(const QPieSeries);
351 return d->m_pieStartAngle;
353 return d->m_pieStartAngle;
352 }
354 }
353
355
354 /*!
356 /*!
355 Sets the end angle of the pie.
357 Sets the end angle of the pie.
356
358
357 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
359 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
358
360
359 \a angle must be greater than start angle.
361 \a angle must be greater than start angle.
360
362
361 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
363 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
362 */
364 */
363 void QPieSeries::setPieEndAngle(qreal angle)
365 void QPieSeries::setPieEndAngle(qreal angle)
364 {
366 {
365 Q_D(QPieSeries);
367 Q_D(QPieSeries);
366
368 if (qFuzzyIsNull(d->m_pieEndAngle - angle))
367 if (d->setRealValue(d->m_pieEndAngle, angle, 360.0, d->m_pieStartAngle))
369 return;
368 d->updateDerivativeData();
370 d->m_pieEndAngle = angle;
371 d->updateDerivativeData();
369 }
372 }
370
373
371 /*!
374 /*!
372 Returns the end angle of the pie.
375 Returns the end angle of the pie.
373
376
374 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
377 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
375
378
376 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
379 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
377 */
380 */
378 qreal QPieSeries::pieEndAngle() const
381 qreal QPieSeries::pieEndAngle() const
379 {
382 {
380 Q_D(const QPieSeries);
383 Q_D(const QPieSeries);
381 return d->m_pieEndAngle;
384 return d->m_pieEndAngle;
382 }
385 }
383
386
384 /*!
387 /*!
385 Sets the all the slice labels \a visible or invisible.
388 Sets the all the slice labels \a visible or invisible.
386
389
387 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
390 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
388 */
391 */
389 void QPieSeries::setLabelsVisible(bool visible)
392 void QPieSeries::setLabelsVisible(bool visible)
390 {
393 {
391 Q_D(QPieSeries);
394 Q_D(QPieSeries);
392 foreach (QPieSlice* s, d->m_slices)
395 foreach (QPieSlice* s, d->m_slices)
393 s->setLabelVisible(visible);
396 s->setLabelVisible(visible);
394 }
397 }
395
398
396 /*!
399 /*!
397 Returns the sum of all slice values in this series.
400 Returns the sum of all slice values in this series.
398
401
399 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
402 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
400 */
403 */
401 qreal QPieSeries::sum() const
404 qreal QPieSeries::sum() const
402 {
405 {
403 Q_D(const QPieSeries);
406 Q_D(const QPieSeries);
404 return d->m_sum;
407 return d->m_sum;
405 }
408 }
406
409
407 /*!
410 /*!
408 \fn void QPieSeries::clicked(QPieSlice* slice)
411 \fn void QPieSeries::clicked(QPieSlice* slice)
409
412
410 This signal is emitted when a \a slice has been clicked.
413 This signal is emitted when a \a slice has been clicked.
411
414
412 \sa QPieSlice::clicked()
415 \sa QPieSlice::clicked()
413 */
416 */
414
417
415 /*!
418 /*!
416 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
419 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
417
420
418 This signal is emitted when user has hovered over or away from the \a slice.
421 This signal is emitted when user has hovered over or away from the \a slice.
419
422
420 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
423 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
421
424
422 \sa QPieSlice::hovered()
425 \sa QPieSlice::hovered()
423 */
426 */
424
427
425 /*!
428 /*!
426 \fn bool QPieSeries::setModel(QAbstractItemModel *model)
429 \fn bool QPieSeries::setModel(QAbstractItemModel *model)
427 Sets the \a model to be used as a data source
430 Sets the \a model to be used as a data source
428 */
431 */
429 void QPieSeries::setModel(QAbstractItemModel* model)
432 void QPieSeries::setModel(QAbstractItemModel* model)
430 {
433 {
431 Q_D(QPieSeries);
434 Q_D(QPieSeries);
432 // disconnect signals from old model
435 // disconnect signals from old model
433 if(d->m_model)
436 if(d->m_model)
434 {
437 {
435 disconnect(d->m_model, 0, this, 0);
438 disconnect(d->m_model, 0, this, 0);
436 }
439 }
437
440
438 // set new model
441 // set new model
439 if(model)
442 if(model)
440 {
443 {
441 d->m_model = model;
444 d->m_model = model;
442 // connect signals from the model
445 // connect signals from the model
443 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
446 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
444 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
447 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
445 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
448 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
446 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
449 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
447 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
450 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
448
451
449 if (d->m_mapper)
452 if (d->m_mapper)
450 d->initializePieFromModel();
453 d->initializePieFromModel();
451 }
454 }
452 else
455 else
453 {
456 {
454 d->m_model = 0;
457 d->m_model = 0;
455 }
458 }
456 }
459 }
457
460
458 void QPieSeries::setModelMapper(QPieModelMapper *mapper)
461 void QPieSeries::setModelMapper(QPieModelMapper *mapper)
459 {
462 {
460 Q_D(QPieSeries);
463 Q_D(QPieSeries);
461 // disconnect signals from old mapper
464 // disconnect signals from old mapper
462 if (d->m_mapper) {
465 if (d->m_mapper) {
463 QObject::disconnect(d->m_mapper, 0, this, 0);
466 QObject::disconnect(d->m_mapper, 0, this, 0);
464 }
467 }
465
468
466 if (mapper) {
469 if (mapper) {
467 d->m_mapper = mapper;
470 d->m_mapper = mapper;
468 // connect the signal from the mapper
471 // connect the signal from the mapper
469 connect(d->m_mapper, SIGNAL(updated()), d, SLOT(initializePieFromModel()));
472 connect(d->m_mapper, SIGNAL(updated()), d, SLOT(initializePieFromModel()));
470
473
471 if (d->m_model)
474 if (d->m_model)
472 d->initializePieFromModel();
475 d->initializePieFromModel();
473 } else {
476 } else {
474 d->m_mapper = 0;
477 d->m_mapper = 0;
475 }
478 }
476 }
479 }
477
480
478 QPieModelMapper* QPieSeries::modelMapper() const
481 QPieModelMapper* QPieSeries::modelMapper() const
479 {
482 {
480 Q_D(const QPieSeries);
483 Q_D(const QPieSeries);
481 return d->m_mapper;
484 return d->m_mapper;
482 }
485 }
483
486
484 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
487 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
485
488
486
489
487 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
490 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
488 QAbstractSeriesPrivate(parent),
491 QAbstractSeriesPrivate(parent),
489 m_pieRelativeHorPos(0.5),
492 m_pieRelativeHorPos(0.5),
490 m_pieRelativeVerPos(0.5),
493 m_pieRelativeVerPos(0.5),
491 m_pieRelativeSize(0.7),
494 m_pieRelativeSize(0.7),
492 m_pieStartAngle(0),
495 m_pieStartAngle(0),
493 m_pieEndAngle(360),
496 m_pieEndAngle(360),
494 m_sum(0),
497 m_sum(0),
495 m_mapper(0)
498 m_mapper(0)
496 {
499 {
497
500
498 }
501 }
499
502
500 QPieSeriesPrivate::~QPieSeriesPrivate()
503 QPieSeriesPrivate::~QPieSeriesPrivate()
501 {
504 {
502
505
503 }
506 }
504
507
505 void QPieSeriesPrivate::updateDerivativeData()
508 void QPieSeriesPrivate::updateDerivativeData()
506 {
509 {
507 m_sum = 0;
510 m_sum = 0;
508
511
509 // nothing to do?
512 // nothing to do?
510 if (m_slices.count() == 0)
513 if (m_slices.count() == 0)
511 return;
514 return;
512
515
513 // calculate sum of all slices
516 // calculate sum of all slices
514 foreach (QPieSlice* s, m_slices)
517 foreach (QPieSlice* s, m_slices)
515 m_sum += s->value();
518 m_sum += s->value();
516
519
517 // nothing to show..
520 // nothing to show..
518 if (qFuzzyIsNull(m_sum))
521 if (qFuzzyIsNull(m_sum))
519 return;
522 return;
520
523
521 // update slice attributes
524 // update slice attributes
522 qreal sliceAngle = m_pieStartAngle;
525 qreal sliceAngle = m_pieStartAngle;
523 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
526 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
524 QVector<QPieSlice*> changed;
527 QVector<QPieSlice*> changed;
525 foreach (QPieSlice* s, m_slices) {
528 foreach (QPieSlice* s, m_slices) {
526
529
527 PieSliceData data = PieSliceData::data(s);
530 PieSliceData data = PieSliceData::data(s);
528 data.m_percentage = s->value() / m_sum;
531 data.m_percentage = s->value() / m_sum;
529 data.m_angleSpan = pieSpan * data.m_percentage;
532 data.m_angleSpan = pieSpan * data.m_percentage;
530 data.m_startAngle = sliceAngle;
533 data.m_startAngle = sliceAngle;
531 sliceAngle += data.m_angleSpan;
534 sliceAngle += data.m_angleSpan;
532
535
533 if (PieSliceData::data(s) != data) {
536 if (PieSliceData::data(s) != data) {
534 PieSliceData::data(s) = data;
537 PieSliceData::data(s) = data;
535 changed << s;
538 changed << s;
536 }
539 }
537 }
540 }
538
541
539 // emit signals
542 // emit signals
540 foreach (QPieSlice* s, changed)
543 foreach (QPieSlice* s, changed)
541 PieSliceData::data(s).emitChangedSignal(s);
544 PieSliceData::data(s).emitChangedSignal(s);
542 }
545 }
543
546
544 QPieSeriesPrivate* QPieSeriesPrivate::seriesData(QPieSeries &series)
547 QPieSeriesPrivate* QPieSeriesPrivate::seriesData(QPieSeries &series)
545 {
548 {
546 return series.d_func();
549 return series.d_func();
547 }
550 }
548
551
549 void QPieSeriesPrivate::sliceChanged()
552 void QPieSeriesPrivate::sliceChanged()
550 {
553 {
551 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
554 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
552 updateDerivativeData();
555 updateDerivativeData();
553 }
556 }
554
557
555 void QPieSeriesPrivate::sliceClicked()
558 void QPieSeriesPrivate::sliceClicked()
556 {
559 {
557 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
560 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
558 Q_ASSERT(m_slices.contains(slice));
561 Q_ASSERT(m_slices.contains(slice));
559 Q_Q(QPieSeries);
562 Q_Q(QPieSeries);
560 emit q->clicked(slice);
563 emit q->clicked(slice);
561 }
564 }
562
565
563 void QPieSeriesPrivate::sliceHovered(bool state)
566 void QPieSeriesPrivate::sliceHovered(bool state)
564 {
567 {
565 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
568 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
566 Q_ASSERT(m_slices.contains(slice));
569 Q_ASSERT(m_slices.contains(slice));
567 Q_Q(QPieSeries);
570 Q_Q(QPieSeries);
568 emit q->hovered(slice, state);
571 emit q->hovered(slice, state);
569 }
572 }
570
573
571 void QPieSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
574 void QPieSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
572 {
575 {
573 if (m_mapper) {
576 if (m_mapper) {
574 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
577 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
575 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
578 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
576 if (m_mapper->orientation() == Qt::Vertical)
579 if (m_mapper->orientation() == Qt::Vertical)
577 {
580 {
578 if ( topLeft.row() >= m_mapper->first() && (m_mapper->count() == - 1 || topLeft.row() < m_mapper->first() + m_mapper->count())) {
581 if ( topLeft.row() >= m_mapper->first() && (m_mapper->count() == - 1 || topLeft.row() < m_mapper->first() + m_mapper->count())) {
579 if (topLeft.column() == m_mapper->mapValues())
582 if (topLeft.column() == m_mapper->mapValues())
580 m_slices.at(topLeft.row() - m_mapper->first())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
583 m_slices.at(topLeft.row() - m_mapper->first())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
581 if (topLeft.column() == m_mapper->mapLabels())
584 if (topLeft.column() == m_mapper->mapLabels())
582 m_slices.at(topLeft.row() - m_mapper->first())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
585 m_slices.at(topLeft.row() - m_mapper->first())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
583 }
586 }
584 }
587 }
585 else
588 else
586 {
589 {
587 if (topLeft.column() >= m_mapper->first() && (m_mapper->count() == - 1 || topLeft.column() < m_mapper->first() + m_mapper->count())) {
590 if (topLeft.column() >= m_mapper->first() && (m_mapper->count() == - 1 || topLeft.column() < m_mapper->first() + m_mapper->count())) {
588 if (topLeft.row() == m_mapper->mapValues())
591 if (topLeft.row() == m_mapper->mapValues())
589 m_slices.at(topLeft.column() - m_mapper->first())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
592 m_slices.at(topLeft.column() - m_mapper->first())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
590 if (topLeft.row() == m_mapper->mapLabels())
593 if (topLeft.row() == m_mapper->mapLabels())
591 m_slices.at(topLeft.column() - m_mapper->first())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
594 m_slices.at(topLeft.column() - m_mapper->first())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
592 }
595 }
593 }
596 }
594 }
597 }
595 }
598 }
596 }
599 }
597 }
600 }
598
601
599
602
600 void QPieSeriesPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
603 void QPieSeriesPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
601 {
604 {
602 Q_UNUSED(parent);
605 Q_UNUSED(parent);
603 if (m_mapper) {
606 if (m_mapper) {
604 if (m_mapper->orientation() == Qt::Vertical)
607 if (m_mapper->orientation() == Qt::Vertical)
605 insertData(start, end);
608 insertData(start, end);
606 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
609 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
607 initializePieFromModel();
610 initializePieFromModel();
608 }
611 }
609 }
612 }
610
613
611 void QPieSeriesPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
614 void QPieSeriesPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
612 {
615 {
613 Q_UNUSED(parent);
616 Q_UNUSED(parent);
614 if (m_mapper) {
617 if (m_mapper) {
615 if (m_mapper->orientation() == Qt::Vertical)
618 if (m_mapper->orientation() == Qt::Vertical)
616 removeData(start, end);
619 removeData(start, end);
617 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
620 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
618 initializePieFromModel();
621 initializePieFromModel();
619 }
622 }
620 }
623 }
621
624
622 void QPieSeriesPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
625 void QPieSeriesPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
623 {
626 {
624 Q_UNUSED(parent);
627 Q_UNUSED(parent);
625 if (m_mapper) {
628 if (m_mapper) {
626 if (m_mapper->orientation() == Qt::Horizontal)
629 if (m_mapper->orientation() == Qt::Horizontal)
627 insertData(start, end);
630 insertData(start, end);
628 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
631 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
629 initializePieFromModel();
632 initializePieFromModel();
630 }
633 }
631 }
634 }
632
635
633 void QPieSeriesPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
636 void QPieSeriesPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
634 {
637 {
635 Q_UNUSED(parent);
638 Q_UNUSED(parent);
636 if (m_mapper) {
639 if (m_mapper) {
637 if (m_mapper->orientation() == Qt::Horizontal)
640 if (m_mapper->orientation() == Qt::Horizontal)
638 removeData(start, end);
641 removeData(start, end);
639 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
642 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
640 initializePieFromModel();
643 initializePieFromModel();
641 }
644 }
642 }
645 }
643
646
644 void QPieSeriesPrivate::insertData(int start, int end)
647 void QPieSeriesPrivate::insertData(int start, int end)
645 {
648 {
646 Q_Q(QPieSeries);
649 Q_Q(QPieSeries);
647 if (m_mapper) {
650 if (m_mapper) {
648 if (m_mapper->count() != -1 && start >= m_mapper->first() + m_mapper->count()) {
651 if (m_mapper->count() != -1 && start >= m_mapper->first() + m_mapper->count()) {
649 return;
652 return;
650 } else {
653 } else {
651 int addedCount = end - start + 1;
654 int addedCount = end - start + 1;
652 if (m_mapper->count() != -1 && addedCount > m_mapper->count())
655 if (m_mapper->count() != -1 && addedCount > m_mapper->count())
653 addedCount = m_mapper->count();
656 addedCount = m_mapper->count();
654 int first = qMax(start, m_mapper->first());
657 int first = qMax(start, m_mapper->first());
655 int last = qMin(first + addedCount - 1, m_mapper->orientation() == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
658 int last = qMin(first + addedCount - 1, m_mapper->orientation() == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
656 for (int i = first; i <= last; i++) {
659 for (int i = first; i <= last; i++) {
657 QPieSlice *slice = new QPieSlice;
660 QPieSlice *slice = new QPieSlice;
658 if (m_mapper->orientation() == Qt::Vertical) {
661 if (m_mapper->orientation() == Qt::Vertical) {
659 slice->setValue(m_model->data(m_model->index(i, m_mapper->mapValues()), Qt::DisplayRole).toDouble());
662 slice->setValue(m_model->data(m_model->index(i, m_mapper->mapValues()), Qt::DisplayRole).toDouble());
660 slice->setLabel(m_model->data(m_model->index(i, m_mapper->mapLabels()), Qt::DisplayRole).toString());
663 slice->setLabel(m_model->data(m_model->index(i, m_mapper->mapLabels()), Qt::DisplayRole).toString());
661 } else {
664 } else {
662 slice->setValue(m_model->data(m_model->index(m_mapper->mapValues(), i), Qt::DisplayRole).toDouble());
665 slice->setValue(m_model->data(m_model->index(m_mapper->mapValues(), i), Qt::DisplayRole).toDouble());
663 slice->setLabel(m_model->data(m_model->index(m_mapper->mapLabels(), i), Qt::DisplayRole).toString());
666 slice->setLabel(m_model->data(m_model->index(m_mapper->mapLabels(), i), Qt::DisplayRole).toString());
664 }
667 }
665 slice->setLabelVisible();
668 slice->setLabelVisible();
666 q->insert(i - m_mapper->first(), slice);
669 q->insert(i - m_mapper->first(), slice);
667 }
670 }
668 if (m_mapper->count() != -1 && m_slices.size() > m_mapper->count())
671 if (m_mapper->count() != -1 && m_slices.size() > m_mapper->count())
669 for (int i = m_slices.size() - 1; i >= m_mapper->count(); i--)
672 for (int i = m_slices.size() - 1; i >= m_mapper->count(); i--)
670 q->remove(q->slices().at(i));
673 q->remove(q->slices().at(i));
671 }
674 }
672 }
675 }
673 }
676 }
674
677
675 void QPieSeriesPrivate::removeData(int start, int end)
678 void QPieSeriesPrivate::removeData(int start, int end)
676 {
679 {
677 Q_Q(QPieSeries);
680 Q_Q(QPieSeries);
678 if (m_mapper) {
681 if (m_mapper) {
679 int removedCount = end - start + 1;
682 int removedCount = end - start + 1;
680 if (m_mapper->count() != -1 && start >= m_mapper->first() + m_mapper->count()) {
683 if (m_mapper->count() != -1 && start >= m_mapper->first() + m_mapper->count()) {
681 return;
684 return;
682 } else {
685 } else {
683 int toRemove = qMin(m_slices.size(), removedCount); // first find how many items can actually be removed
686 int toRemove = qMin(m_slices.size(), removedCount); // first find how many items can actually be removed
684 int first = qMax(start, m_mapper->first()); // get the index of the first item that will be removed.
687 int first = qMax(start, m_mapper->first()); // get the index of the first item that will be removed.
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.
688 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 for (int i = last; i >= first; i--)
689 for (int i = last; i >= first; i--)
687 q->remove(q->slices().at(i - m_mapper->first()));
690 q->remove(q->slices().at(i - m_mapper->first()));
688
691
689 if (m_mapper->count() != -1) {
692 if (m_mapper->count() != -1) {
690 int itemsAvailable; // check how many are available to be added
693 int itemsAvailable; // check how many are available to be added
691 if (m_mapper->orientation() == Qt::Vertical)
694 if (m_mapper->orientation() == Qt::Vertical)
692 itemsAvailable = m_model->rowCount() - m_mapper->first() - m_slices.size();
695 itemsAvailable = m_model->rowCount() - m_mapper->first() - m_slices.size();
693 else
696 else
694 itemsAvailable = m_model->columnCount() - m_mapper->first() - m_slices.size();
697 itemsAvailable = m_model->columnCount() - m_mapper->first() - m_slices.size();
695 int toBeAdded = qMin(itemsAvailable, m_mapper->count() - m_slices.size()); // add not more items than there is space left to be filled.
698 int toBeAdded = qMin(itemsAvailable, m_mapper->count() - m_slices.size()); // add not more items than there is space left to be filled.
696 int currentSize = m_slices.size();
699 int currentSize = m_slices.size();
697 if (toBeAdded > 0)
700 if (toBeAdded > 0)
698 for (int i = m_slices.size(); i < currentSize + toBeAdded; i++) {
701 for (int i = m_slices.size(); i < currentSize + toBeAdded; i++) {
699 QPieSlice *slice = new QPieSlice;
702 QPieSlice *slice = new QPieSlice;
700 if (m_mapper->orientation() == Qt::Vertical) {
703 if (m_mapper->orientation() == Qt::Vertical) {
701 slice->setValue(m_model->data(m_model->index(i + m_mapper->first(), m_mapper->mapValues()), Qt::DisplayRole).toDouble());
704 slice->setValue(m_model->data(m_model->index(i + m_mapper->first(), m_mapper->mapValues()), Qt::DisplayRole).toDouble());
702 slice->setLabel(m_model->data(m_model->index(i + m_mapper->first(), m_mapper->mapLabels()), Qt::DisplayRole).toString());
705 slice->setLabel(m_model->data(m_model->index(i + m_mapper->first(), m_mapper->mapLabels()), Qt::DisplayRole).toString());
703 } else {
706 } else {
704 slice->setValue(m_model->data(m_model->index(m_mapper->mapValues(), i + m_mapper->first()), Qt::DisplayRole).toDouble());
707 slice->setValue(m_model->data(m_model->index(m_mapper->mapValues(), i + m_mapper->first()), Qt::DisplayRole).toDouble());
705 slice->setLabel(m_model->data(m_model->index(m_mapper->mapLabels(), i + m_mapper->first()), Qt::DisplayRole).toString());
708 slice->setLabel(m_model->data(m_model->index(m_mapper->mapLabels(), i + m_mapper->first()), Qt::DisplayRole).toString());
706 }
709 }
707 slice->setLabelVisible();
710 slice->setLabelVisible();
708 q->insert(i, slice);
711 q->insert(i, slice);
709 }
712 }
710 }
713 }
711 }
714 }
712 }
715 }
713 }
716 }
714
717
715 void QPieSeriesPrivate::initializePieFromModel()
718 void QPieSeriesPrivate::initializePieFromModel()
716 {
719 {
717 Q_Q(QPieSeries);
720 Q_Q(QPieSeries);
718
721
719 // clear current content
722 // clear current content
720 q->clear();
723 q->clear();
721
724
722 if (m_model == 0 || m_mapper == 0)
725 if (m_model == 0 || m_mapper == 0)
723 return;
726 return;
724
727
725 // check if mappings are set
728 // check if mappings are set
726 if (m_mapper->mapValues() == -1 || m_mapper->mapLabels() == -1)
729 if (m_mapper->mapValues() == -1 || m_mapper->mapLabels() == -1)
727 return;
730 return;
728
731
729 // create the initial slices set
732 // create the initial slices set
730 if (m_mapper->orientation() == Qt::Vertical) {
733 if (m_mapper->orientation() == Qt::Vertical) {
731 if (m_mapper->mapValues() >= m_model->columnCount() || m_mapper->mapLabels() >= m_model->columnCount())
734 if (m_mapper->mapValues() >= m_model->columnCount() || m_mapper->mapLabels() >= m_model->columnCount())
732 return; // mapped columns are not existing
735 return; // mapped columns are not existing
733
736
734 int sliceCount = 0;
737 int sliceCount = 0;
735 if(m_mapper->count() == -1)
738 if(m_mapper->count() == -1)
736 sliceCount = m_model->rowCount() - m_mapper->first();
739 sliceCount = m_model->rowCount() - m_mapper->first();
737 else
740 else
738 sliceCount = qMin(m_mapper->count(), m_model->rowCount() - m_mapper->first());
741 sliceCount = qMin(m_mapper->count(), m_model->rowCount() - m_mapper->first());
739 for (int i = m_mapper->first(); i < m_mapper->first() + sliceCount; i++)
742 for (int i = m_mapper->first(); i < m_mapper->first() + sliceCount; i++)
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());
743 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 } else {
744 } else {
742 if (m_mapper->mapValues() >= m_model->rowCount() || m_mapper->mapLabels() >= m_model->rowCount())
745 if (m_mapper->mapValues() >= m_model->rowCount() || m_mapper->mapLabels() >= m_model->rowCount())
743 return; // mapped columns are not existing
746 return; // mapped columns are not existing
744
747
745 int sliceCount = 0;
748 int sliceCount = 0;
746 if(m_mapper->count() == -1)
749 if(m_mapper->count() == -1)
747 sliceCount = m_model->columnCount() - m_mapper->first();
750 sliceCount = m_model->columnCount() - m_mapper->first();
748 else
751 else
749 sliceCount = qMin(m_mapper->count(), m_model->columnCount() - m_mapper->first());
752 sliceCount = qMin(m_mapper->count(), m_model->columnCount() - m_mapper->first());
750 for (int i = m_mapper->first(); i < m_mapper->first() + sliceCount; i++)
753 for (int i = m_mapper->first(); i < m_mapper->first() + sliceCount; i++)
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());
754 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 }
755 }
753 q->setLabelsVisible(true);
756 q->setLabelsVisible(true);
754 }
757 }
755
758
756 bool QPieSeriesPrivate::setRealValue(qreal &value, qreal newValue, qreal max, qreal min)
759 bool QPieSeriesPrivate::setRealValue(qreal &value, qreal newValue, qreal max, qreal min)
757 {
760 {
758 // Remove rounding errors
761 // Remove rounding errors
759 qreal roundedValue = newValue;
762 qreal roundedValue = newValue;
760 if (qFuzzyIsNull(min) && qFuzzyIsNull(newValue))
763 if (qFuzzyIsNull(min) && qFuzzyIsNull(newValue))
761 roundedValue = 0.0;
764 roundedValue = 0.0;
762 else if (qFuzzyCompare(newValue, max))
765 else if (qFuzzyCompare(newValue, max))
763 roundedValue = max;
766 roundedValue = max;
764 else if (qFuzzyCompare(newValue, min))
767 else if (qFuzzyCompare(newValue, min))
765 roundedValue = min;
768 roundedValue = min;
766
769
767 // Check if the position is valid after removing the rounding errors
770 // Check if the position is valid after removing the rounding errors
768 if (roundedValue < min || roundedValue > max) {
771 if (roundedValue < min || roundedValue > max) {
769 qWarning("QPieSeries: Illegal value");
772 qWarning("QPieSeries: Illegal value");
770 return false;
773 return false;
771 }
774 }
772
775
773 if (!qFuzzyIsNull(value - roundedValue)) {
776 if (!qFuzzyIsNull(value - roundedValue)) {
774 value = roundedValue;
777 value = roundedValue;
775 return true;
778 return true;
776 }
779 }
777
780
778 // The change was so small it is considered a rounding error
781 // The change was so small it is considered a rounding error
779 return false;
782 return false;
780 }
783 }
781
784
782 void QPieSeriesPrivate::scaleDomain(Domain& domain)
785 void QPieSeriesPrivate::scaleDomain(Domain& domain)
783 {
786 {
784 Q_UNUSED(domain);
787 Q_UNUSED(domain);
785 // does not apply to pie
788 // does not apply to pie
786 }
789 }
787
790
788 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
791 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
789 {
792 {
790 Q_Q(QPieSeries);
793 Q_Q(QPieSeries);
791 PieChartItem* pie = new PieChartItem(q,presenter);
794 PieChartItem* pie = new PieChartItem(q,presenter);
792 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
795 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
793 presenter->animator()->addAnimation(pie);
796 presenter->animator()->addAnimation(pie);
794 }
797 }
795 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
798 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
796 return pie;
799 return pie;
797 }
800 }
798
801
799 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
802 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
800 {
803 {
801 Q_Q(QPieSeries);
804 Q_Q(QPieSeries);
802 QList<LegendMarker*> markers;
805 QList<LegendMarker*> markers;
803 foreach(QPieSlice* slice, q->slices()) {
806 foreach(QPieSlice* slice, q->slices()) {
804 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
807 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
805 markers << marker;
808 markers << marker;
806 }
809 }
807 return markers;
810 return markers;
808 }
811 }
809
812
810 #include "moc_qpieseries.cpp"
813 #include "moc_qpieseries.cpp"
811 #include "moc_qpieseries_p.cpp"
814 #include "moc_qpieseries_p.cpp"
812
815
813 QTCOMMERCIALCHART_END_NAMESPACE
816 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,484 +1,491
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include <QtTest/QtTest>
21 #include <QtTest/QtTest>
22 #include <qchartview.h>
22 #include <qchartview.h>
23 #include <qchart.h>
23 #include <qchart.h>
24 #include <qpieseries.h>
24 #include <qpieseries.h>
25 #include <qpieslice.h>
25 #include <qpieslice.h>
26 #include <qpiemodelmapper.h>
26 #include <qpiemodelmapper.h>
27 #include <QStandardItemModel>
27 #include <QStandardItemModel>
28 #include <tst_definitions.h>
28 #include <tst_definitions.h>
29
29
30 QTCOMMERCIALCHART_USE_NAMESPACE
30 QTCOMMERCIALCHART_USE_NAMESPACE
31
31
32 Q_DECLARE_METATYPE(QPieSlice*)
32 Q_DECLARE_METATYPE(QPieSlice*)
33
33
34 class tst_qpieseries : public QObject
34 class tst_qpieseries : public QObject
35 {
35 {
36 Q_OBJECT
36 Q_OBJECT
37
37
38 public slots:
38 public slots:
39 void initTestCase();
39 void initTestCase();
40 void cleanupTestCase();
40 void cleanupTestCase();
41 void init();
41 void init();
42 void cleanup();
42 void cleanup();
43
43
44 private slots:
44 private slots:
45 void construction();
45 void construction();
46 void append();
46 void append();
47 void insert();
47 void insert();
48 void remove();
48 void remove();
49 void calculatedValues();
49 void calculatedValues();
50 void clickedSignal();
50 void clickedSignal();
51 void hoverSignal();
51 void hoverSignal();
52 void model();
52 void model();
53 void modelCustomMap();
53 void modelCustomMap();
54 void modelUpdate();
54 void modelUpdate();
55
55
56 private:
56 private:
57 void verifyCalculatedData(const QPieSeries &series, bool *ok);
57 void verifyCalculatedData(const QPieSeries &series, bool *ok);
58
58
59 private:
59 private:
60
60
61 };
61 };
62
62
63 void tst_qpieseries::initTestCase()
63 void tst_qpieseries::initTestCase()
64 {
64 {
65 qRegisterMetaType<QPieSlice*>("QPieSlice*");
65 qRegisterMetaType<QPieSlice*>("QPieSlice*");
66 }
66 }
67
67
68 void tst_qpieseries::cleanupTestCase()
68 void tst_qpieseries::cleanupTestCase()
69 {
69 {
70 }
70 }
71
71
72 void tst_qpieseries::init()
72 void tst_qpieseries::init()
73 {
73 {
74
74
75 }
75 }
76
76
77 void tst_qpieseries::cleanup()
77 void tst_qpieseries::cleanup()
78 {
78 {
79
79
80 }
80 }
81
81
82 void tst_qpieseries::construction()
82 void tst_qpieseries::construction()
83 {
83 {
84 // verify default values
84 // verify default values
85 QPieSeries s;
85 QPieSeries s;
86 QVERIFY(s.type() == QAbstractSeries::SeriesTypePie);
86 QVERIFY(s.type() == QAbstractSeries::SeriesTypePie);
87 QVERIFY(s.count() == 0);
87 QVERIFY(s.count() == 0);
88 QVERIFY(s.isEmpty());
88 QVERIFY(s.isEmpty());
89 QCOMPARE(s.sum(), 0.0);
89 QCOMPARE(s.sum(), 0.0);
90 QCOMPARE(s.horizontalPosition(), 0.5);
90 QCOMPARE(s.horizontalPosition(), 0.5);
91 QCOMPARE(s.verticalPosition(), 0.5);
91 QCOMPARE(s.verticalPosition(), 0.5);
92 QCOMPARE(s.pieSize(), 0.7);
92 QCOMPARE(s.pieSize(), 0.7);
93 QCOMPARE(s.pieStartAngle(), 0.0);
93 QCOMPARE(s.pieStartAngle(), 0.0);
94 QCOMPARE(s.pieEndAngle(), 360.0);
94 QCOMPARE(s.pieEndAngle(), 360.0);
95 }
95 }
96
96
97 void tst_qpieseries::append()
97 void tst_qpieseries::append()
98 {
98 {
99 QPieSeries s;
99 QPieSeries s;
100
100
101 // append pointer
101 // append pointer
102 QPieSlice *slice1 = 0;
102 QPieSlice *slice1 = 0;
103 QVERIFY(!s.append(slice1));
103 QVERIFY(!s.append(slice1));
104 slice1 = new QPieSlice("slice 1", 1);
104 slice1 = new QPieSlice("slice 1", 1);
105 QVERIFY(s.append(slice1));
105 QVERIFY(s.append(slice1));
106 QVERIFY(!s.append(slice1));
106 QVERIFY(!s.append(slice1));
107 QCOMPARE(s.count(), 1);
107 QCOMPARE(s.count(), 1);
108
108
109 // append pointer list
109 // append pointer list
110 QList<QPieSlice *> list;
110 QList<QPieSlice *> list;
111 QVERIFY(!s.append(list));
111 QVERIFY(!s.append(list));
112 list << (QPieSlice *) 0;
112 list << (QPieSlice *) 0;
113 QVERIFY(!s.append(list));
113 QVERIFY(!s.append(list));
114 list.clear();
114 list.clear();
115 list << new QPieSlice("slice 2", 2);
115 list << new QPieSlice("slice 2", 2);
116 list << new QPieSlice("slice 3", 3);
116 list << new QPieSlice("slice 3", 3);
117 QVERIFY(s.append(list));
117 QVERIFY(s.append(list));
118 QVERIFY(!s.append(list));
118 QVERIFY(!s.append(list));
119 QCOMPARE(s.count(), 3);
119 QCOMPARE(s.count(), 3);
120
120
121 // append operator
121 // append operator
122 s << new QPieSlice("slice 4", 4);
122 s << new QPieSlice("slice 4", 4);
123 s << slice1; // fails because already added
123 s << slice1; // fails because already added
124 QCOMPARE(s.count(), 4);
124 QCOMPARE(s.count(), 4);
125
125
126 // append with params
126 // append with params
127 QPieSlice *slice5 = s.append("slice 5", 5);
127 QPieSlice *slice5 = s.append("slice 5", 5);
128 QVERIFY(slice5 != 0);
128 QVERIFY(slice5 != 0);
129 QCOMPARE(slice5->value(), 5.0);
129 QCOMPARE(slice5->value(), 5.0);
130 QCOMPARE(slice5->label(), QString("slice 5"));
130 QCOMPARE(slice5->label(), QString("slice 5"));
131 QCOMPARE(s.count(), 5);
131 QCOMPARE(s.count(), 5);
132
132
133 // check slices
133 // check slices
134 QVERIFY(!s.isEmpty());
134 QVERIFY(!s.isEmpty());
135 for (int i=0; i<s.count(); i++) {
135 for (int i=0; i<s.count(); i++) {
136 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
136 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
137 QCOMPARE(s.slices().at(i)->label(), QString("slice ") + QString::number(i+1));
137 QCOMPARE(s.slices().at(i)->label(), QString("slice ") + QString::number(i+1));
138 }
138 }
139 }
139 }
140
140
141 void tst_qpieseries::insert()
141 void tst_qpieseries::insert()
142 {
142 {
143 QPieSeries s;
143 QPieSeries s;
144
144
145 // insert one slice
145 // insert one slice
146 QPieSlice *slice1 = 0;
146 QPieSlice *slice1 = 0;
147 QVERIFY(!s.insert(0, slice1));
147 QVERIFY(!s.insert(0, slice1));
148 slice1 = new QPieSlice("slice 1", 1);
148 slice1 = new QPieSlice("slice 1", 1);
149 QVERIFY(!s.insert(-1, slice1));
149 QVERIFY(!s.insert(-1, slice1));
150 QVERIFY(!s.insert(5, slice1));
150 QVERIFY(!s.insert(5, slice1));
151 QVERIFY(s.insert(0, slice1));
151 QVERIFY(s.insert(0, slice1));
152 QVERIFY(!s.insert(0, slice1));
152 QVERIFY(!s.insert(0, slice1));
153 QCOMPARE(s.count(), 1);
153 QCOMPARE(s.count(), 1);
154
154
155 // add some more slices
155 // add some more slices
156 s.append("slice 2", 2);
156 s.append("slice 2", 2);
157 s.append("slice 4", 4);
157 s.append("slice 4", 4);
158 QCOMPARE(s.count(), 3);
158 QCOMPARE(s.count(), 3);
159
159
160 // insert between slices
160 // insert between slices
161 s.insert(2, new QPieSlice("slice 3", 3));
161 s.insert(2, new QPieSlice("slice 3", 3));
162 QCOMPARE(s.count(), 4);
162 QCOMPARE(s.count(), 4);
163
163
164 // check slices
164 // check slices
165 for (int i=0; i<s.count(); i++) {
165 for (int i=0; i<s.count(); i++) {
166 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
166 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
167 QCOMPARE(s.slices().at(i)->label(), QString("slice ") + QString::number(i+1));
167 QCOMPARE(s.slices().at(i)->label(), QString("slice ") + QString::number(i+1));
168 }
168 }
169 }
169 }
170
170
171 void tst_qpieseries::remove()
171 void tst_qpieseries::remove()
172 {
172 {
173 QPieSeries s;
173 QPieSeries s;
174
174
175 // add some slices
175 // add some slices
176 QPieSlice *slice1 = s.append("slice 1", 1);
176 QPieSlice *slice1 = s.append("slice 1", 1);
177 QPieSlice *slice2 = s.append("slice 2", 2);
177 QPieSlice *slice2 = s.append("slice 2", 2);
178 QPieSlice *slice3 = s.append("slice 3", 3);
178 QPieSlice *slice3 = s.append("slice 3", 3);
179 QSignalSpy spy1(slice1, SIGNAL(destroyed()));
179 QSignalSpy spy1(slice1, SIGNAL(destroyed()));
180 QSignalSpy spy2(slice2, SIGNAL(destroyed()));
180 QSignalSpy spy2(slice2, SIGNAL(destroyed()));
181 QSignalSpy spy3(slice3, SIGNAL(destroyed()));
181 QSignalSpy spy3(slice3, SIGNAL(destroyed()));
182 QCOMPARE(s.count(), 3);
182 QCOMPARE(s.count(), 3);
183
183
184 // null pointer remove
184 // null pointer remove
185 QVERIFY(!s.remove(0));
185 QVERIFY(!s.remove(0));
186
186
187 // remove first
187 // remove first
188 QVERIFY(s.remove(slice1));
188 QVERIFY(s.remove(slice1));
189 QVERIFY(!s.remove(slice1));
189 QVERIFY(!s.remove(slice1));
190 QCOMPARE(s.count(), 2);
190 QCOMPARE(s.count(), 2);
191 QCOMPARE(s.slices().at(0)->label(), slice2->label());
191 QCOMPARE(s.slices().at(0)->label(), slice2->label());
192
192
193 // remove all
193 // remove all
194 s.clear();
194 s.clear();
195 QVERIFY(s.isEmpty());
195 QVERIFY(s.isEmpty());
196 QVERIFY(s.slices().isEmpty());
196 QVERIFY(s.slices().isEmpty());
197 QCOMPARE(s.count(), 0);
197 QCOMPARE(s.count(), 0);
198
198
199 // check that slices were actually destroyed
199 // check that slices were actually destroyed
200 TRY_COMPARE(spy1.count(), 1);
200 TRY_COMPARE(spy1.count(), 1);
201 TRY_COMPARE(spy2.count(), 1);
201 TRY_COMPARE(spy2.count(), 1);
202 TRY_COMPARE(spy3.count(), 1);
202 TRY_COMPARE(spy3.count(), 1);
203 }
203 }
204
204
205 void tst_qpieseries::calculatedValues()
205 void tst_qpieseries::calculatedValues()
206 {
206 {
207 bool ok;
207 bool ok;
208 QPieSeries s;
208 QPieSeries s;
209
209
210 // add a slice
210 // add a slice
211 QPieSlice *slice1 = s.append("slice 1", 1);
211 QPieSlice *slice1 = s.append("slice 1", 1);
212 verifyCalculatedData(s, &ok);
212 verifyCalculatedData(s, &ok);
213 if (!ok)
213 if (!ok)
214 return;
214 return;
215
215
216 // add some more slices
216 // add some more slices
217 QList<QPieSlice *> list;
217 QList<QPieSlice *> list;
218 list << new QPieSlice("slice 2", 2);
218 list << new QPieSlice("slice 2", 2);
219 list << new QPieSlice("slice 3", 3);
219 list << new QPieSlice("slice 3", 3);
220 s.append(list);
220 s.append(list);
221 verifyCalculatedData(s, &ok);
221 verifyCalculatedData(s, &ok);
222 if (!ok)
222 if (!ok)
223 return;
223 return;
224
224
225 // remove a slice
225 // remove a slice
226 s.remove(slice1);
226 s.remove(slice1);
227 verifyCalculatedData(s, &ok);
227 verifyCalculatedData(s, &ok);
228 if (!ok)
228 if (!ok)
229 return;
229 return;
230
230
231 // insert a slice
231 // insert a slice
232 s.insert(0, new QPieSlice("Slice 4", 4));
232 s.insert(0, new QPieSlice("Slice 4", 4));
233 verifyCalculatedData(s, &ok);
233 verifyCalculatedData(s, &ok);
234 if (!ok)
234 if (!ok)
235 return;
235 return;
236
236
237 // modify pie angles
238 s.setPieStartAngle(-90);
239 s.setPieEndAngle(90);
240 verifyCalculatedData(s, &ok);
241 if (!ok)
242 return;
243
237 // clear all
244 // clear all
238 s.clear();
245 s.clear();
239 verifyCalculatedData(s, &ok);
246 verifyCalculatedData(s, &ok);
240 }
247 }
241
248
242 void tst_qpieseries::verifyCalculatedData(const QPieSeries &series, bool *ok)
249 void tst_qpieseries::verifyCalculatedData(const QPieSeries &series, bool *ok)
243 {
250 {
244 *ok = false;
251 *ok = false;
245
252
246 qreal sum = 0;
253 qreal sum = 0;
247 foreach (const QPieSlice *slice, series.slices())
254 foreach (const QPieSlice *slice, series.slices())
248 sum += slice->value();
255 sum += slice->value();
249 QCOMPARE(series.sum(), sum);
256 QCOMPARE(series.sum(), sum);
250
257
251 qreal startAngle = series.pieStartAngle();
258 qreal startAngle = series.pieStartAngle();
252 qreal pieAngleSpan = series.pieEndAngle() - series.pieStartAngle();
259 qreal pieAngleSpan = series.pieEndAngle() - series.pieStartAngle();
253 foreach (const QPieSlice *slice, series.slices()) {
260 foreach (const QPieSlice *slice, series.slices()) {
254 qreal ratio = slice->value() / sum;
261 qreal ratio = slice->value() / sum;
255 qreal sliceSpan = pieAngleSpan * ratio;
262 qreal sliceSpan = pieAngleSpan * ratio;
256 QCOMPARE(slice->startAngle(), startAngle);
263 QCOMPARE(slice->startAngle(), startAngle);
257 QCOMPARE(slice->endAngle(), startAngle + sliceSpan);
264 QCOMPARE(slice->endAngle(), startAngle + sliceSpan);
258 QCOMPARE(slice->percentage(), ratio);
265 QCOMPARE(slice->percentage(), ratio);
259 startAngle += sliceSpan;
266 startAngle += sliceSpan;
260 }
267 }
261
268
262 if (!series.isEmpty())
269 if (!series.isEmpty())
263 QCOMPARE(series.slices().last()->endAngle(), series.pieEndAngle());
270 QCOMPARE(series.slices().last()->endAngle(), series.pieEndAngle());
264
271
265 *ok = true;
272 *ok = true;
266 }
273 }
267
274
268
275
269 void tst_qpieseries::clickedSignal()
276 void tst_qpieseries::clickedSignal()
270 {
277 {
271 // create a pie series
278 // create a pie series
272 QPieSeries *series = new QPieSeries();
279 QPieSeries *series = new QPieSeries();
273 series->setPieSize(1.0);
280 series->setPieSize(1.0);
274 QPieSlice *s1 = series->append("slice 1", 1);
281 QPieSlice *s1 = series->append("slice 1", 1);
275 series->append("slice 2", 2);
282 series->append("slice 2", 2);
276 series->append("slice 3", 3);
283 series->append("slice 3", 3);
277 QSignalSpy clickSpy1(series, SIGNAL(clicked(QPieSlice*)));
284 QSignalSpy clickSpy1(series, SIGNAL(clicked(QPieSlice*)));
278
285
279 // add series to the chart
286 // add series to the chart
280 QChartView view(new QChart());
287 QChartView view(new QChart());
281 view.chart()->legend()->setVisible(false);
288 view.chart()->legend()->setVisible(false);
282 view.resize(200, 200);
289 view.resize(200, 200);
283 view.chart()->addSeries(series);
290 view.chart()->addSeries(series);
284 view.show();
291 view.show();
285 QTest::qWaitForWindowShown(&view);
292 QTest::qWaitForWindowShown(&view);
286
293
287 // simulate clicks
294 // simulate clicks
288 // pie rectangle: QRectF(60,60 121x121)
295 // pie rectangle: QRectF(60,60 121x121)
289 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(146, 90)); // inside slice 1
296 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(146, 90)); // inside slice 1
290 TRY_COMPARE(clickSpy1.count(), 1);
297 TRY_COMPARE(clickSpy1.count(), 1);
291 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy1.at(0).at(0)), s1);
298 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy1.at(0).at(0)), s1);
292 }
299 }
293
300
294 void tst_qpieseries::hoverSignal()
301 void tst_qpieseries::hoverSignal()
295 {
302 {
296 // create a pie series
303 // create a pie series
297 QPieSeries *series = new QPieSeries();
304 QPieSeries *series = new QPieSeries();
298 series->setPieSize(1.0);
305 series->setPieSize(1.0);
299 QPieSlice *s1 = series->append("slice 1", 1);
306 QPieSlice *s1 = series->append("slice 1", 1);
300 series->append("slice 2", 2);
307 series->append("slice 2", 2);
301 series->append("slice 3", 3);
308 series->append("slice 3", 3);
302
309
303 // add series to the chart
310 // add series to the chart
304 QChartView view(new QChart());
311 QChartView view(new QChart());
305 view.chart()->legend()->setVisible(false);
312 view.chart()->legend()->setVisible(false);
306 view.resize(200, 200);
313 view.resize(200, 200);
307 view.chart()->addSeries(series);
314 view.chart()->addSeries(series);
308 view.show();
315 view.show();
309 QTest::qWaitForWindowShown(&view);
316 QTest::qWaitForWindowShown(&view);
310
317
311 // first move to right top corner
318 // first move to right top corner
312 QTest::mouseMove(view.viewport(), QPoint(200, 0));
319 QTest::mouseMove(view.viewport(), QPoint(200, 0));
313 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
320 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
314
321
315 // move inside the slice
322 // move inside the slice
316 // pie rectangle: QRectF(60,60 121x121)
323 // pie rectangle: QRectF(60,60 121x121)
317 QSignalSpy hoverSpy(series, SIGNAL(hovered(QPieSlice*,bool)));
324 QSignalSpy hoverSpy(series, SIGNAL(hovered(QPieSlice*,bool)));
318 QTest::mouseMove(view.viewport(), QPoint(139, 85));
325 QTest::mouseMove(view.viewport(), QPoint(139, 85));
319 TRY_COMPARE(hoverSpy.count(), 1);
326 TRY_COMPARE(hoverSpy.count(), 1);
320 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(0).at(0)), s1);
327 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(0).at(0)), s1);
321 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(0).at(1)), true);
328 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(0).at(1)), true);
322
329
323 // move outside the slice
330 // move outside the slice
324 QTest::mouseMove(view.viewport(), QPoint(200, 0));
331 QTest::mouseMove(view.viewport(), QPoint(200, 0));
325 TRY_COMPARE(hoverSpy.count(), 2);
332 TRY_COMPARE(hoverSpy.count(), 2);
326 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(1).at(0)), s1);
333 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(1).at(0)), s1);
327 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(1).at(1)), false);
334 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(1).at(1)), false);
328 }
335 }
329
336
330 void tst_qpieseries::model()
337 void tst_qpieseries::model()
331 {
338 {
332 QSKIP("Needs to be checked again. Model implementation changed", SkipAll);
339 QSKIP("Needs to be checked again. Model implementation changed", SkipAll);
333
340
334 QPieSeries *series = new QPieSeries;
341 QPieSeries *series = new QPieSeries;
335 QChart *chart = new QChart;
342 QChart *chart = new QChart;
336 chart->addSeries(series);
343 chart->addSeries(series);
337 QChartView *chartView = new QChartView(chart);
344 QChartView *chartView = new QChartView(chart);
338 chartView->show();
345 chartView->show();
339
346
340 QStandardItemModel *stdModel = new QStandardItemModel(0, 2);
347 QStandardItemModel *stdModel = new QStandardItemModel(0, 2);
341 series->setModel(stdModel);
348 series->setModel(stdModel);
342
349
343 int rowCount = 3;
350 int rowCount = 3;
344 for (int row = 0; row < rowCount; ++row) {
351 for (int row = 0; row < rowCount; ++row) {
345 for (int column = 0; column < 2; column++) {
352 for (int column = 0; column < 2; column++) {
346 QStandardItem *item = new QStandardItem(row * column);
353 QStandardItem *item = new QStandardItem(row * column);
347 stdModel->setItem(row, column, item);
354 stdModel->setItem(row, column, item);
348 }
355 }
349 }
356 }
350
357
351 // data has been added to the model, but mapper is not set the number of slices should still be 0
358 // data has been added to the model, but mapper is not set the number of slices should still be 0
352 QVERIFY2(series->slices().count() == 0, "Mapper has not been set, so the number of slices should be 0");
359 QVERIFY2(series->slices().count() == 0, "Mapper has not been set, so the number of slices should be 0");
353
360
354 // set the mapper
361 // set the mapper
355 QPieModelMapper *mapper = series->modelMapper();//new QPieModelMapper;
362 QPieModelMapper *mapper = series->modelMapper();//new QPieModelMapper;
356 mapper->setMapValues(0);
363 mapper->setMapValues(0);
357 mapper->setMapLabels(0);
364 mapper->setMapLabels(0);
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
365 // 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 QCOMPARE(series->slices().count(), rowCount);
366 QCOMPARE(series->slices().count(), rowCount);
360
367
361 // set the mappings to be outside of the model
368 // set the mappings to be outside of the model
362 mapper->setMapLabels(5);
369 mapper->setMapLabels(5);
363 mapper->setMapValues(4);
370 mapper->setMapValues(4);
364 QCOMPARE(series->slices().count(), 0); // Mappings are invalid, so the number of slices should be 0
371 QCOMPARE(series->slices().count(), 0); // Mappings are invalid, so the number of slices should be 0
365
372
366 // set back to correct ones
373 // set back to correct ones
367 mapper->setMapValues(0);
374 mapper->setMapValues(0);
368 mapper->setMapLabels(0);
375 mapper->setMapLabels(0);
369 QCOMPARE(series->slices().count(), rowCount);
376 QCOMPARE(series->slices().count(), rowCount);
370
377
371 // reset the mappings
378 // reset the mappings
372 mapper->reset();
379 mapper->reset();
373 QCOMPARE(series->slices().count(), 0); // Mappings have been reset and are invalid, so the number of slices should be 0
380 QCOMPARE(series->slices().count(), 0); // Mappings have been reset and are invalid, so the number of slices should be 0
374
381
375 // unset the model and the mapper
382 // unset the model and the mapper
376 series->setModel(0);
383 series->setModel(0);
377 // series->setModelMapper(0);
384 // series->setModelMapper(0);
378 QVERIFY(series->model() == 0); // Model should be unset
385 QVERIFY(series->model() == 0); // Model should be unset
379 // QVERIFY(series->modelMapper() == 0); // Model mapper should be unset
386 // QVERIFY(series->modelMapper() == 0); // Model mapper should be unset
380 }
387 }
381
388
382 void tst_qpieseries::modelCustomMap()
389 void tst_qpieseries::modelCustomMap()
383 {
390 {
384 QSKIP("Needs to be checked again. Model implementation changed", SkipAll);
391 QSKIP("Needs to be checked again. Model implementation changed", SkipAll);
385
392
386 int rowCount = 12;
393 int rowCount = 12;
387 int columnCount = 3;
394 int columnCount = 3;
388 QStandardItemModel *stdModel = new QStandardItemModel(0, 3);
395 QStandardItemModel *stdModel = new QStandardItemModel(0, 3);
389 for (int row = 0; row < rowCount; ++row) {
396 for (int row = 0; row < rowCount; ++row) {
390 for (int column = 0; column < 2; column++) {
397 for (int column = 0; column < 2; column++) {
391 QStandardItem *item = new QStandardItem(row * column);
398 QStandardItem *item = new QStandardItem(row * column);
392 stdModel->setItem(row, column, item);
399 stdModel->setItem(row, column, item);
393 }
400 }
394 }
401 }
395
402
396 QPieSeries *series = new QPieSeries;
403 QPieSeries *series = new QPieSeries;
397 QChart *chart = new QChart;
404 QChart *chart = new QChart;
398 chart->addSeries(series);
405 chart->addSeries(series);
399 QChartView *chartView = new QChartView(chart);
406 QChartView *chartView = new QChartView(chart);
400 chartView->show();
407 chartView->show();
401 series->setModel(stdModel);
408 series->setModel(stdModel);
402
409
403 QPieModelMapper *mapper = series->modelMapper();//new QPieModelMapper;
410 QPieModelMapper *mapper = series->modelMapper();//new QPieModelMapper;
404 mapper->setMapValues(0);
411 mapper->setMapValues(0);
405 mapper->setMapLabels(0);
412 mapper->setMapLabels(0);
406 // series->setModelMapper(mapper);
413 // series->setModelMapper(mapper);
407 QCOMPARE(series->slices().count(), rowCount);
414 QCOMPARE(series->slices().count(), rowCount);
408
415
409 // lets change the orientation to horizontal
416 // lets change the orientation to horizontal
410 mapper->setOrientation(Qt::Horizontal);
417 mapper->setOrientation(Qt::Horizontal);
411 QCOMPARE(series->slices().count(), columnCount);
418 QCOMPARE(series->slices().count(), columnCount);
412
419
413 // change it back to vertical
420 // change it back to vertical
414 mapper->setOrientation(Qt::Vertical);
421 mapper->setOrientation(Qt::Vertical);
415 QCOMPARE(series->slices().count(), rowCount);
422 QCOMPARE(series->slices().count(), rowCount);
416
423
417 // lets customize the mapping
424 // lets customize the mapping
418 int first = 3;
425 int first = 3;
419 mapper->setFirst(first);
426 mapper->setFirst(first);
420 QCOMPARE(series->slices().count(), rowCount - first);
427 QCOMPARE(series->slices().count(), rowCount - first);
421 int count = 7;
428 int count = 7;
422 mapper->setCount(count);
429 mapper->setCount(count);
423 QCOMPARE(series->slices().count(), count);
430 QCOMPARE(series->slices().count(), count);
424 first = 9;
431 first = 9;
425 mapper->setFirst(first);
432 mapper->setFirst(first);
426 QCOMPARE(series->slices().count(), qMin(count, rowCount - first));
433 QCOMPARE(series->slices().count(), qMin(count, rowCount - first));
427 }
434 }
428
435
429 void tst_qpieseries::modelUpdate()
436 void tst_qpieseries::modelUpdate()
430 {
437 {
431 QSKIP("Needs to be checked again. Model implementation changed", SkipAll);
438 QSKIP("Needs to be checked again. Model implementation changed", SkipAll);
432
439
433 int rowCount = 12;
440 int rowCount = 12;
434 int columnCount = 7;
441 int columnCount = 7;
435 QStandardItemModel *stdModel = new QStandardItemModel(rowCount, columnCount);
442 QStandardItemModel *stdModel = new QStandardItemModel(rowCount, columnCount);
436 for (int row = 0; row < rowCount; ++row) {
443 for (int row = 0; row < rowCount; ++row) {
437 for (int column = 0; column < columnCount; column++) {
444 for (int column = 0; column < columnCount; column++) {
438 QStandardItem *item = new QStandardItem(row * column);
445 QStandardItem *item = new QStandardItem(row * column);
439 stdModel->setItem(row, column, item);
446 stdModel->setItem(row, column, item);
440 }
447 }
441 }
448 }
442
449
443 QPieSeries *series = new QPieSeries;
450 QPieSeries *series = new QPieSeries;
444 QChart *chart = new QChart;
451 QChart *chart = new QChart;
445 chart->addSeries(series);
452 chart->addSeries(series);
446 QChartView *chartView = new QChartView(chart);
453 QChartView *chartView = new QChartView(chart);
447 chartView->show();
454 chartView->show();
448 series->setModel(stdModel);
455 series->setModel(stdModel);
449
456
450 QPieModelMapper *mapper = series->modelMapper();//new QPieModelMapper;
457 QPieModelMapper *mapper = series->modelMapper();//new QPieModelMapper;
451 mapper->setMapValues(0);
458 mapper->setMapValues(0);
452 mapper->setMapLabels(0);
459 mapper->setMapLabels(0);
453 // series->setModelMapper(mapper);
460 // series->setModelMapper(mapper);
454
461
455 stdModel->insertRows(3, 5);
462 stdModel->insertRows(3, 5);
456 QCOMPARE(series->slices().count(), rowCount + 5);
463 QCOMPARE(series->slices().count(), rowCount + 5);
457
464
458 stdModel->removeRows(10, 5);
465 stdModel->removeRows(10, 5);
459 QCOMPARE(series->slices().count(), rowCount);
466 QCOMPARE(series->slices().count(), rowCount);
460
467
461 // limit the number of slices taken from the model to 12
468 // limit the number of slices taken from the model to 12
462 mapper->setCount(rowCount);
469 mapper->setCount(rowCount);
463 stdModel->insertRows(3, 5);
470 stdModel->insertRows(3, 5);
464 QCOMPARE(series->slices().count(), rowCount);
471 QCOMPARE(series->slices().count(), rowCount);
465
472
466 stdModel->removeRows(0, 10);
473 stdModel->removeRows(0, 10);
467 QCOMPARE(series->slices().count(), rowCount - 5);
474 QCOMPARE(series->slices().count(), rowCount - 5);
468
475
469 // change the orientation to horizontal
476 // change the orientation to horizontal
470 mapper->setOrientation(Qt::Horizontal);
477 mapper->setOrientation(Qt::Horizontal);
471 QCOMPARE(series->slices().count(), columnCount);
478 QCOMPARE(series->slices().count(), columnCount);
472
479
473 stdModel->insertColumns(3, 10);
480 stdModel->insertColumns(3, 10);
474 QCOMPARE(series->slices().count(), rowCount); // count is limited to rowCount (12)
481 QCOMPARE(series->slices().count(), rowCount); // count is limited to rowCount (12)
475
482
476 stdModel->removeColumns(5, 10);
483 stdModel->removeColumns(5, 10);
477 QCOMPARE(series->slices().count(), columnCount);
484 QCOMPARE(series->slices().count(), columnCount);
478
485
479 }
486 }
480
487
481 QTEST_MAIN(tst_qpieseries)
488 QTEST_MAIN(tst_qpieseries)
482
489
483 #include "tst_qpieseries.moc"
490 #include "tst_qpieseries.moc"
484
491
General Comments 0
You need to be logged in to leave comments. Login now