##// END OF EJS Templates
Introducing vertical and horizontal factors to control the position of the pie.
Jani Honkonen -
r454:06980850b7dd
parent child
Show More
@@ -1,224 +1,236
1 #include <QtGui/QApplication>
1 #include <QtGui/QApplication>
2 #include <QMainWindow>
2 #include <QMainWindow>
3 #include <qchartglobal.h>
3 #include <qchartglobal.h>
4 #include <qchartview.h>
4 #include <qchartview.h>
5 #include <qpieseries.h>
5 #include <qpieseries.h>
6 #include <qpieslice.h>
6 #include <qpieslice.h>
7 #include <QGridLayout>
7 #include <QGridLayout>
8 #include <QFormLayout>
8 #include <QFormLayout>
9 #include <QComboBox>
9 #include <QComboBox>
10 #include <QSpinBox>
10 #include <QSpinBox>
11 #include <QCheckBox>
11 #include <QCheckBox>
12 #include <QGroupBox>
12 #include <QGroupBox>
13 #include <QLabel>
13 #include <QLabel>
14
14
15 QTCOMMERCIALCHART_USE_NAMESPACE
15 QTCOMMERCIALCHART_USE_NAMESPACE
16
16
17 Q_DECLARE_METATYPE(QPieSeries::PiePosition)
18
19 class CustomSlice : public QPieSlice
17 class CustomSlice : public QPieSlice
20 {
18 {
21 Q_OBJECT
19 Q_OBJECT
22 public:
20 public:
23 CustomSlice(qreal value, QString label)
21 CustomSlice(qreal value, QString label)
24 :QPieSlice(value, label)
22 :QPieSlice(value, label)
25 {
23 {
26 connect(this, SIGNAL(hoverEnter()), this, SLOT(handleHoverEnter()));
24 connect(this, SIGNAL(hoverEnter()), this, SLOT(handleHoverEnter()));
27 connect(this, SIGNAL(hoverLeave()), this, SLOT(handleHoverLeave()));
25 connect(this, SIGNAL(hoverLeave()), this, SLOT(handleHoverLeave()));
28 }
26 }
29
27
30 public Q_SLOTS:
28 public Q_SLOTS:
31
29
32 void handleHoverEnter()
30 void handleHoverEnter()
33 {
31 {
34 QBrush brush = this->brush();
32 QBrush brush = this->brush();
35 m_originalBrush = brush;
33 m_originalBrush = brush;
36 brush.setColor(brush.color().lighter());
34 brush.setColor(brush.color().lighter());
37 setBrush(brush);
35 setBrush(brush);
38 }
36 }
39
37
40 void handleHoverLeave()
38 void handleHoverLeave()
41 {
39 {
42 setBrush(m_originalBrush);
40 setBrush(m_originalBrush);
43 }
41 }
44
42
45 private:
43 private:
46 QBrush m_originalBrush;
44 QBrush m_originalBrush;
47 };
45 };
48
46
49 class MainWidget : public QWidget
47 class MainWidget : public QWidget
50 {
48 {
51 Q_OBJECT
49 Q_OBJECT
52
50
53 public:
51 public:
54 explicit MainWidget(QWidget* parent = 0)
52 explicit MainWidget(QWidget* parent = 0)
55 :QWidget(parent)
53 :QWidget(parent),
54 m_slice(0)
56 {
55 {
57 m_chartView = new QChartView();
56 m_chartView = new QChartView();
58 m_chartView->setChartTitle("Piechart customization");
57 m_chartView->setChartTitle("Piechart customization");
59 //m_chartView->setRenderHint(QPainter::Antialiasing);
58 m_chartView->setRenderHint(QPainter::Antialiasing);
59 m_chartView->setChartTheme(QChart::ChartThemeIcy);
60
60
61 m_series = new QPieSeries();
61 m_series = new QPieSeries();
62 *m_series << new CustomSlice(10.0, "Slice 1");
62 *m_series << new CustomSlice(10.0, "Slice 1");
63 *m_series << new CustomSlice(20.0, "Slice 2");
63 *m_series << new CustomSlice(20.0, "Slice 2");
64 *m_series << new CustomSlice(30.0, "Slice 3");
64 *m_series << new CustomSlice(30.0, "Slice 3");
65 *m_series << new CustomSlice(40.0, "Slice 4");
65 *m_series << new CustomSlice(40.0, "Slice 4");
66 *m_series << new CustomSlice(50.0, "Slice 5");
66 *m_series << new CustomSlice(50.0, "Slice 5");
67 m_chartView->addSeries(m_series);
67 m_chartView->addSeries(m_series);
68
68
69 m_vPosition = new QComboBox();
69 m_hPosition = new QDoubleSpinBox();
70 m_vPosition->addItem("Top", QPieSeries::PiePositionTop);
70 m_hPosition->setMinimum(0.0);
71 m_vPosition->addItem("Bottom", QPieSeries::PiePositionBottom);
71 m_hPosition->setMaximum(1.0);
72 m_vPosition->addItem("Center", QPieSeries::PiePositionVCenter);
72 m_hPosition->setSingleStep(0.1);
73
73 m_hPosition->setValue(m_series->horizontalPositionFactor());
74 m_hPosition = new QComboBox();
75 m_hPosition->addItem("Left", QPieSeries::PiePositionLeft);
76 m_hPosition->addItem("Right", QPieSeries::PiePositionRight);
77 m_hPosition->addItem("Center", QPieSeries::PiePositionHCenter);
78
74
79 m_sizePolicy = new QComboBox();
75 m_vPosition = new QDoubleSpinBox();
80 m_sizePolicy->addItem("Maximized", QPieSeries::PieSizePolicyMaximized);
76 m_vPosition->setMinimum(0.0);
81 m_sizePolicy->addItem("Space for labels", QPieSeries::PieSizePolicyReserveSpaceForLabels);
77 m_vPosition->setMaximum(1.0);
82 m_sizePolicy->addItem("Space for exploding", QPieSeries::PieSizePolicyReserveSpaceForExploding);
78 m_vPosition->setSingleStep(0.1);
83 m_sizePolicy->addItem("Space for all", QPieSeries::PieSizePolicyReserveSpaceForAll);
79 m_vPosition->setValue(m_series->verticalPositionFactor());
84
80
85 m_sizeFactor = new QDoubleSpinBox();
81 m_sizeFactor = new QDoubleSpinBox();
86 m_sizeFactor->setMinimum(0.0);
82 m_sizeFactor->setMinimum(0.0);
87 m_sizeFactor->setMaximum(1.0);
83 m_sizeFactor->setMaximum(1.0);
88 m_sizeFactor->setValue(m_series->sizeFactor());
89 m_sizeFactor->setSingleStep(0.1);
84 m_sizeFactor->setSingleStep(0.1);
85 m_sizeFactor->setValue(m_series->sizeFactor());
90
86
91 m_startAngle = new QDoubleSpinBox();
87 m_startAngle = new QDoubleSpinBox();
92 m_startAngle->setMinimum(0.0);
88 m_startAngle->setMinimum(0.0);
93 m_startAngle->setMaximum(360);
89 m_startAngle->setMaximum(360);
94 m_startAngle->setValue(m_series->startAngle());
90 m_startAngle->setValue(m_series->startAngle());
95 m_startAngle->setSingleStep(1);
91 m_startAngle->setSingleStep(1);
96
92
97 m_endAngle = new QDoubleSpinBox();
93 m_endAngle = new QDoubleSpinBox();
98 m_endAngle->setMinimum(0.0);
94 m_endAngle->setMinimum(0.0);
99 m_endAngle->setMaximum(360);
95 m_endAngle->setMaximum(360);
100 m_endAngle->setValue(m_series->endAngle());
96 m_endAngle->setValue(m_series->endAngle());
101 m_endAngle->setSingleStep(1);
97 m_endAngle->setSingleStep(1);
102
98
103 QFormLayout* seriesSettingsLayout = new QFormLayout();
99 QFormLayout* seriesSettingsLayout = new QFormLayout();
104 seriesSettingsLayout->addRow("Vertical position", m_vPosition);
105 seriesSettingsLayout->addRow("Horizontal position", m_hPosition);
100 seriesSettingsLayout->addRow("Horizontal position", m_hPosition);
106 seriesSettingsLayout->addRow("Size policy", m_sizePolicy);
101 seriesSettingsLayout->addRow("Vertical position", m_vPosition);
107 seriesSettingsLayout->addRow("Size factor", m_sizeFactor);
102 seriesSettingsLayout->addRow("Size factor", m_sizeFactor);
108 seriesSettingsLayout->addRow("Start angle", m_startAngle);
103 seriesSettingsLayout->addRow("Start angle", m_startAngle);
109 seriesSettingsLayout->addRow("End angle", m_endAngle);
104 seriesSettingsLayout->addRow("End angle", m_endAngle);
110 QGroupBox* seriesSettings = new QGroupBox("Series");
105 QGroupBox* seriesSettings = new QGroupBox("Series");
111 seriesSettings->setLayout(seriesSettingsLayout);
106 seriesSettings->setLayout(seriesSettingsLayout);
112
107
113 m_sliceName = new QLabel("<click a slice>");
108 m_sliceName = new QLabel("<click a slice>");
114 m_sliceValue = new QDoubleSpinBox();
109 m_sliceValue = new QDoubleSpinBox();
115 m_sliceValue->setMaximum(1000);
110 m_sliceValue->setMaximum(1000);
116 m_sliceLabelVisible = new QCheckBox();
111 m_sliceLabelVisible = new QCheckBox();
112 m_sliceLabelArmFactor = new QDoubleSpinBox();
113 m_sliceLabelArmFactor->setSingleStep(0.01);
117 m_sliceExploded = new QCheckBox();
114 m_sliceExploded = new QCheckBox();
115 m_sliceExplodedFactor = new QDoubleSpinBox();
116 m_sliceExplodedFactor->setSingleStep(0.01);
118
117
119 QFormLayout* sliceSettingsLayout = new QFormLayout();
118 QFormLayout* sliceSettingsLayout = new QFormLayout();
120 sliceSettingsLayout->addRow("Selected", m_sliceName);
119 sliceSettingsLayout->addRow("Selected", m_sliceName);
121 sliceSettingsLayout->addRow("Value", m_sliceValue);
120 sliceSettingsLayout->addRow("Value", m_sliceValue);
122 sliceSettingsLayout->addRow("Label visible", m_sliceLabelVisible);
121 sliceSettingsLayout->addRow("Label visible", m_sliceLabelVisible);
122 sliceSettingsLayout->addRow("Label arm length", m_sliceLabelArmFactor);
123 sliceSettingsLayout->addRow("Exploded", m_sliceExploded);
123 sliceSettingsLayout->addRow("Exploded", m_sliceExploded);
124 sliceSettingsLayout->addRow("Explode distance", m_sliceExplodedFactor);
125
124 QGroupBox* sliceSettings = new QGroupBox("Slice");
126 QGroupBox* sliceSettings = new QGroupBox("Slice");
125 sliceSettings->setLayout(sliceSettingsLayout);
127 sliceSettings->setLayout(sliceSettingsLayout);
126
128
127 QGridLayout* baseLayout = new QGridLayout();
129 QGridLayout* baseLayout = new QGridLayout();
128 baseLayout->addWidget(seriesSettings, 0, 0);
130 baseLayout->addWidget(seriesSettings, 0, 0);
129 baseLayout->addWidget(sliceSettings, 1, 0);
131 baseLayout->addWidget(sliceSettings, 1, 0);
130 baseLayout->addWidget(m_chartView, 0, 1, 2, 1);
132 baseLayout->addWidget(m_chartView, 0, 1, 2, 1);
131 setLayout(baseLayout);
133 setLayout(baseLayout);
132
134
133 connect(m_vPosition, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSerieSettings()));
135 connect(m_vPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
134 connect(m_hPosition, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSerieSettings()));
136 connect(m_hPosition, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
135 connect(m_sizePolicy, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSerieSettings()));
136 connect(m_sizeFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
137 connect(m_sizeFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
137 connect(m_startAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
138 connect(m_startAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
138 connect(m_endAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
139 connect(m_endAngle, SIGNAL(valueChanged(double)), this, SLOT(updateSerieSettings()));
139
140
140 connect(m_sliceValue, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
141 connect(m_sliceValue, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
141 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
142 connect(m_sliceLabelVisible, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
143 connect(m_sliceLabelArmFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
142 connect(m_sliceExploded, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
144 connect(m_sliceExploded, SIGNAL(toggled(bool)), this, SLOT(updateSliceSettings()));
145 connect(m_sliceExplodedFactor, SIGNAL(valueChanged(double)), this, SLOT(updateSliceSettings()));
143
146
144 connect(m_series, SIGNAL(clicked(QPieSlice*)), this, SLOT(handleSliceClicked(QPieSlice*)));
147 connect(m_series, SIGNAL(clicked(QPieSlice*)), this, SLOT(handleSliceClicked(QPieSlice*)));
145
148
146 updateSerieSettings();
149 updateSerieSettings();
147 }
150 }
148
151
149 public Q_SLOTS:
152 public Q_SLOTS:
150
153
151 void updateSerieSettings()
154 void updateSerieSettings()
152 {
155 {
153 QPieSeries::PiePosition vPos(m_vPosition->itemData(m_vPosition->currentIndex()).toInt());
156 m_series->setPositionFactors(m_vPosition->value(), m_hPosition->value());
154 QPieSeries::PiePosition hPos(m_hPosition->itemData(m_hPosition->currentIndex()).toInt());
155 m_series->setPosition(vPos | hPos);
156
157 QPieSeries::PieSizePolicy policy(m_sizePolicy->itemData(m_sizePolicy->currentIndex()).toInt());
158 m_series->setSizePolicy(policy);
159
157
160 m_series->setSizeFactor(m_sizeFactor->value());
158 m_series->setSizeFactor(m_sizeFactor->value());
161
159
162 m_series->setStartAngle(m_startAngle->value());
160 m_series->setStartAngle(m_startAngle->value());
163 m_series->setEndAngle(m_endAngle->value());
161 m_series->setEndAngle(m_endAngle->value());
164 }
162 }
165
163
166 void updateSliceSettings()
164 void updateSliceSettings()
167 {
165 {
166 if (!m_slice)
167 return;
168
168 m_slice->setValue(m_sliceValue->value());
169 m_slice->setValue(m_sliceValue->value());
169 m_slice->setLabelVisible(m_sliceLabelVisible->isChecked());
170 m_slice->setLabelVisible(m_sliceLabelVisible->isChecked());
171 m_slice->setLabelArmLengthFactor(m_sliceLabelArmFactor->value());
170 m_slice->setExploded(m_sliceExploded->isChecked());
172 m_slice->setExploded(m_sliceExploded->isChecked());
173 m_slice->setExplodeDistanceFactor(m_sliceExplodedFactor->value());
171 }
174 }
172
175
173 void handleSliceClicked(QPieSlice* slice)
176 void handleSliceClicked(QPieSlice* slice)
174 {
177 {
175 m_slice = slice;
178 m_slice = slice;
176 m_sliceName->setText(slice->label());
179 m_sliceName->setText(slice->label());
177
180
178 m_sliceValue->blockSignals(true);
181 m_sliceValue->blockSignals(true);
179 m_sliceValue->setValue(slice->value());
182 m_sliceValue->setValue(slice->value());
180 m_sliceValue->blockSignals(false);
183 m_sliceValue->blockSignals(false);
181
184
182 m_sliceLabelVisible->blockSignals(true);
185 m_sliceLabelVisible->blockSignals(true);
183 m_sliceLabelVisible->setChecked(slice->isLabelVisible());
186 m_sliceLabelVisible->setChecked(slice->isLabelVisible());
184 m_sliceLabelVisible->blockSignals(false);
187 m_sliceLabelVisible->blockSignals(false);
185
188
189 m_sliceLabelArmFactor->blockSignals(true);
190 m_sliceLabelArmFactor->setValue(slice->labelArmLengthFactor());
191 m_sliceLabelArmFactor->blockSignals(false);
192
186 m_sliceExploded->blockSignals(true);
193 m_sliceExploded->blockSignals(true);
187 m_sliceExploded->setChecked(slice->isExploded());
194 m_sliceExploded->setChecked(slice->isExploded());
188 m_sliceExploded->blockSignals(false);
195 m_sliceExploded->blockSignals(false);
196
197 m_sliceExplodedFactor->blockSignals(true);
198 m_sliceExplodedFactor->setValue(slice->explodeDistanceFactor());
199 m_sliceExplodedFactor->blockSignals(false);
189 }
200 }
190
201
191 private:
202 private:
192 QChartView* m_chartView;
203 QChartView* m_chartView;
193 QPieSeries* m_series;
204 QPieSeries* m_series;
194 QPieSlice* m_slice;
205 QPieSlice* m_slice;
195
206
196 QComboBox* m_vPosition;
207 QDoubleSpinBox* m_hPosition;
197 QComboBox* m_hPosition;
208 QDoubleSpinBox* m_vPosition;
198 QComboBox* m_sizePolicy;
199 QDoubleSpinBox* m_sizeFactor;
209 QDoubleSpinBox* m_sizeFactor;
200 QDoubleSpinBox* m_startAngle;
210 QDoubleSpinBox* m_startAngle;
201 QDoubleSpinBox* m_endAngle;
211 QDoubleSpinBox* m_endAngle;
202
212
203 QLabel* m_sliceName;
213 QLabel* m_sliceName;
204 QDoubleSpinBox* m_sliceValue;
214 QDoubleSpinBox* m_sliceValue;
205 QCheckBox* m_sliceLabelVisible;
215 QCheckBox* m_sliceLabelVisible;
216 QDoubleSpinBox* m_sliceLabelArmFactor;
206 QCheckBox* m_sliceExploded;
217 QCheckBox* m_sliceExploded;
218 QDoubleSpinBox* m_sliceExplodedFactor;
207 };
219 };
208
220
209 int main(int argc, char *argv[])
221 int main(int argc, char *argv[])
210 {
222 {
211 QApplication a(argc, argv);
223 QApplication a(argc, argv);
212
224
213 QMainWindow window;
225 QMainWindow window;
214
226
215 MainWidget* widget = new MainWidget();
227 MainWidget* widget = new MainWidget();
216
228
217 window.setCentralWidget(widget);
229 window.setCentralWidget(widget);
218 window.resize(900, 600);
230 window.resize(900, 600);
219 window.show();
231 window.show();
220
232
221 return a.exec();
233 return a.exec();
222 }
234 }
223
235
224 #include "main.moc"
236 #include "main.moc"
@@ -1,242 +1,154
1 #include "piepresenter_p.h"
1 #include "piepresenter_p.h"
2 #include "pieslice_p.h"
2 #include "pieslice_p.h"
3 #include "qpieslice.h"
3 #include "qpieslice.h"
4 #include "qpieseries.h"
4 #include "qpieseries.h"
5 #include <QDebug>
5 #include <QDebug>
6 #include <QPainter>
6 #include <QPainter>
7
7
8
8
9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10
10
11 PiePresenter::PiePresenter(QGraphicsItem *parent, QPieSeries *series)
11 PiePresenter::PiePresenter(QGraphicsItem *parent, QPieSeries *series)
12 :ChartItem(parent),
12 :ChartItem(parent),
13 m_series(series)
13 m_series(series)
14 {
14 {
15 Q_ASSERT(series);
15 Q_ASSERT(series);
16 connect(series, SIGNAL(changed(const QPieSeries::ChangeSet&)), this, SLOT(handleSeriesChanged(const QPieSeries::ChangeSet&)));
16 connect(series, SIGNAL(changed(const QPieSeries::ChangeSet&)), this, SLOT(handleSeriesChanged(const QPieSeries::ChangeSet&)));
17 connect(series, SIGNAL(sizeFactorChanged()), this, SLOT(updateGeometry()));
17 connect(series, SIGNAL(sizeFactorChanged()), this, SLOT(updateGeometry()));
18 connect(series, SIGNAL(positionChanged()), this, SLOT(updateGeometry()));
18 connect(series, SIGNAL(positionChanged()), this, SLOT(updateGeometry()));
19 connect(series, SIGNAL(sizePolicyChanged()), this, SLOT(updateGeometry()));
20
19
21 if (m_series->count()) {
20 if (m_series->count()) {
22 QPieSeries::ChangeSet changeSet;
21 QPieSeries::ChangeSet changeSet;
23 changeSet.appendAdded(m_series->m_slices);
22 changeSet.appendAdded(m_series->m_slices);
24 handleSeriesChanged(changeSet);
23 handleSeriesChanged(changeSet);
25 }
24 }
26 }
25 }
27
26
28 PiePresenter::~PiePresenter()
27 PiePresenter::~PiePresenter()
29 {
28 {
30 // slices deleted automatically through QGraphicsItem
29 // slices deleted automatically through QGraphicsItem
31 }
30 }
32
31
33 void PiePresenter::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
32 void PiePresenter::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
34 {
33 {
35 // TODO: paint shadows for all components
34 // TODO: paint shadows for all components
36 // - get paths from items & merge & offset and draw with shadow color?
35 // - get paths from items & merge & offset and draw with shadow color?
37 //painter->setBrush(QBrush(Qt::red));
36 //painter->setBrush(QBrush(Qt::red));
38 //painter->drawRect(m_debugRect);
37 //painter->drawRect(m_debugRect);
39 }
38 }
40
39
41 void PiePresenter::handleSeriesChanged(const QPieSeries::ChangeSet& changeSet)
40 void PiePresenter::handleSeriesChanged(const QPieSeries::ChangeSet& changeSet)
42 {
41 {
43 //qDebug() << "PiePresenter::handleSeriesChanged()";
42 //qDebug() << "PiePresenter::handleSeriesChanged()";
44 //qDebug() << " added : " << changeSet.added();
43 //qDebug() << " added : " << changeSet.added();
45 //qDebug() << " changed: " << changeSet.changed();
44 //qDebug() << " changed: " << changeSet.changed();
46 //qDebug() << " removed: " << changeSet.removed();
45 //qDebug() << " removed: " << changeSet.removed();
47
46
48 foreach (QPieSlice* s, changeSet.added())
47 foreach (QPieSlice* s, changeSet.added())
49 addSlice(s);
48 addSlice(s);
50
49
51 foreach (QPieSlice* s, changeSet.changed())
50 foreach (QPieSlice* s, changeSet.changed())
52 updateSlice(s);
51 updateSlice(s);
53
52
54 foreach (QPieSlice* s, changeSet.removed())
53 foreach (QPieSlice* s, changeSet.removed())
55 deleteSlice(s);
54 deleteSlice(s);
56
55
57 // every change possibly changes the actual pie size
56 // every change possibly changes the actual pie size
58 updateGeometry();
57 updateGeometry();
59 }
58 }
60
59
61 void PiePresenter::handleDomainChanged(const Domain& domain)
60 void PiePresenter::handleDomainChanged(const Domain& domain)
62 {
61 {
63 // TODO
62 // TODO
64 }
63 }
65
64
66 void PiePresenter::handleGeometryChanged(const QRectF& rect)
65 void PiePresenter::handleGeometryChanged(const QRectF& rect)
67 {
66 {
68 m_rect = rect;
67 m_rect = rect;
69 prepareGeometryChange();
68 prepareGeometryChange();
70 updateGeometry();
69 updateGeometry();
71 }
70 }
72
71
73 void PiePresenter::updateGeometry()
72 void PiePresenter::updateGeometry()
74 {
73 {
75 if (!m_rect.isValid() || m_rect.isEmpty())
74 if (!m_rect.isValid() || m_rect.isEmpty())
76 return;
75 return;
77
76
78 // calculate maximum rectangle for pie
77 // find pie center coordinates
79 QRectF pieRect = m_rect;
78 QPointF center;
80 if (pieRect.width() < pieRect.height()) {
79 center.setX(m_rect.left() + (m_rect.width() * m_series->m_hPositionFactor));
81 pieRect.setHeight(pieRect.width());
80 center.setY(m_rect.top() + (m_rect.height() * m_series->m_vPositionFactor));
82 } else {
83 pieRect.setWidth(pieRect.height());
84 }
85
86 // position the pie rectangle
87 QPointF center = m_rect.center(); // default position is center
88 qreal dx = pieRect.width() / 2;
89 qreal dy = pieRect.height() / 2;
90 if (m_series->position() & QPieSeries::PiePositionLeft)
91 center.setX(m_rect.left() + dx);
92 if (m_series->position() & QPieSeries::PiePositionRight)
93 center.setX(m_rect.right() - dx);
94 if (m_series->position() & QPieSeries::PiePositionHCenter)
95 center.setX(m_rect.center().x());
96 if (m_series->position() & QPieSeries::PiePositionTop)
97 center.setY(m_rect.top() + dy);
98 if (m_series->position() & QPieSeries::PiePositionBottom)
99 center.setY(m_rect.bottom() - dy);
100 if (m_series->position() & QPieSeries::PiePositionVCenter)
101 center.setY(m_rect.center().y());
102 pieRect.moveCenter(center);
103
104 // calculate how much space we need around the pie rectangle (labels & exploding)
105 qreal delta = 0;
106 qreal pieRadius = pieRect.height() / 2;
107 foreach (QPieSlice* s, m_series->m_slices) {
108
109 bool exploded = s->isExploded();
110 if (m_series->sizePolicy() & QPieSeries::PieSizePolicyReserveSpaceForExploding)
111 exploded = true;
112
113 bool labelVisible = s->isLabelVisible();
114 if (m_series->sizePolicy() & QPieSeries::PieSizePolicyReserveSpaceForLabels)
115 labelVisible = true;
116
117 qreal centerAngle;
118 QPointF armStart;
119 QRectF sliceRect = PieSlice::slicePath(center, pieRadius, s->m_startAngle, s->m_angleSpan, exploded, s->explodeDistance(), &centerAngle, &armStart).boundingRect();
120
121 if (labelVisible) {
122 QRectF textRect = PieSlice::labelTextRect(s->labelFont(), s->label());
123 QPointF textStart;
124 QRectF armRect = PieSlice::labelArmPath(armStart, centerAngle, s->labelArmLength(), textRect.width(), &textStart).boundingRect();
125 textRect.moveBottomLeft(textStart);
126 sliceRect = sliceRect.united(armRect);
127 sliceRect = sliceRect.united(textRect);
128 }
129
81
82 // find maximum radius for pie
83 qreal radius = m_rect.height() / 2;
84 if (m_rect.width() < m_rect.height())
85 radius = m_rect.width() / 2;
130
86
131 qreal dt = m_rect.top() - sliceRect.top();
87 // apply size factor
132 if (dt > delta)
88 radius *= m_series->m_pieSizeFactor;
133 delta = dt;
134 qreal dl = m_rect.left() - sliceRect.left();
135 if (dl > delta)
136 delta = dl;
137 qreal dr = sliceRect.right() - m_rect.right();
138 if (dr > delta)
139 delta = dr;
140 qreal db = sliceRect.bottom() - m_rect.bottom();
141 if (db > delta)
142 delta = db;
143
144 /*
145 if (s->label() == "Slice 5") {
146 m_debugRect = sliceRect;
147 qDebug() << "dt:" << dt << ", dl:" << dl << ", dr:" << dr << ", db:" << db << ", delta:" << delta;
148 }
149 */
150 }
151
152 // shrink the pie rectangle so that everything outside it fits the base rectangle
153 pieRect.adjust(delta, delta, -delta, -delta);
154
155 /*
156 // apply size factor (range 0.0 ... 1.0)
157 pieRect.setWidth(pieRect.width() * m_series->sizeFactor());
158 pieRect.setHeight(pieRect.height() * m_series->sizeFactor());
159
160 // position the pie rectangle (again)
161 center = m_rect.center(); // default position is center
162 dx = pieRect.width() / 2;
163 dy = pieRect.height() / 2;
164 if (m_series->position() & QPieSeries::PiePositionLeft)
165 center.setX(m_rect.left() + dx);
166 if (m_series->position() & QPieSeries::PiePositionRight)
167 center.setX(m_rect.right() - dx);
168 if (m_series->position() & QPieSeries::PiePositionHCenter)
169 center.setX(m_rect.center().x());
170 if (m_series->position() & QPieSeries::PiePositionTop)
171 center.setY(m_rect.top() + dy);
172 if (m_series->position() & QPieSeries::PiePositionBottom)
173 center.setY(m_rect.bottom() - dy);
174 if (m_series->position() & QPieSeries::PiePositionVCenter)
175 center.setY(m_rect.center().y());
176 pieRect.moveCenter(center);
177 */
178
89
179 // update slices
90 // update slices
180 if (m_pieRect != pieRect) {
91 if (m_pieCenter != center || m_pieRadius != radius) {
181 m_pieRect = pieRect;
92 m_pieCenter = center;
182 //qDebug() << "PiePresenter::updateGeometry()" << m_rect << m_pieRect;
93 m_pieRadius = radius;
94 //qDebug() << "PiePresenter::updateGeometry()" << m_rect << m_pieCenter << m_pieRadius;
183 foreach (PieSlice* s, m_slices.values()) {
95 foreach (PieSlice* s, m_slices.values()) {
184 s->setPieRect(m_pieRect);
96 s->setPieCenterAndRadius(center, radius);
185 s->updateGeometry();
97 s->updateGeometry();
186 s->update();
98 s->update();
187 }
99 }
188 }
100 }
189
101
190 update();
102 update();
191 }
103 }
192
104
193 void PiePresenter::addSlice(QPieSlice* sliceData)
105 void PiePresenter::addSlice(QPieSlice* sliceData)
194 {
106 {
195 //qDebug() << "PiePresenter::addSlice()" << sliceData;
107 //qDebug() << "PiePresenter::addSlice()" << sliceData;
196
108
197 if (m_slices.keys().contains(sliceData)) {
109 if (m_slices.keys().contains(sliceData)) {
198 Q_ASSERT(0); // TODO: how to handle this nicely?
110 Q_ASSERT(0); // TODO: how to handle this nicely?
199 return;
111 return;
200 }
112 }
201
113
202 // create slice
114 // create slice
203 PieSlice *slice = new PieSlice(this);
115 PieSlice *slice = new PieSlice(this);
204 slice->setPieRect(m_pieRect);
116 slice->setPieCenterAndRadius(m_pieCenter, m_pieRadius);
205 slice->updateData(sliceData);
117 slice->updateData(sliceData);
206 slice->updateGeometry();
118 slice->updateGeometry();
207 slice->update();
119 slice->update();
208 m_slices.insert(sliceData, slice);
120 m_slices.insert(sliceData, slice);
209
121
210 // connect signals
122 // connect signals
211 connect(slice, SIGNAL(clicked()), sliceData, SIGNAL(clicked()));
123 connect(slice, SIGNAL(clicked()), sliceData, SIGNAL(clicked()));
212 connect(slice, SIGNAL(hoverEnter()), sliceData, SIGNAL(hoverEnter()));
124 connect(slice, SIGNAL(hoverEnter()), sliceData, SIGNAL(hoverEnter()));
213 connect(slice, SIGNAL(hoverLeave()), sliceData, SIGNAL(hoverLeave()));
125 connect(slice, SIGNAL(hoverLeave()), sliceData, SIGNAL(hoverLeave()));
214 }
126 }
215
127
216 void PiePresenter::updateSlice(QPieSlice* sliceData)
128 void PiePresenter::updateSlice(QPieSlice* sliceData)
217 {
129 {
218 //qDebug() << "PiePresenter::updateSlice()" << sliceData;
130 //qDebug() << "PiePresenter::updateSlice()" << sliceData;
219
131
220 if (!m_slices.contains(sliceData)) {
132 if (!m_slices.contains(sliceData)) {
221 Q_ASSERT(0); // TODO: how to handle this nicely?
133 Q_ASSERT(0); // TODO: how to handle this nicely?
222 return;
134 return;
223 }
135 }
224
136
225 m_slices[sliceData]->updateData(sliceData);
137 m_slices[sliceData]->updateData(sliceData);
226 }
138 }
227
139
228 void PiePresenter::deleteSlice(QPieSlice* sliceData)
140 void PiePresenter::deleteSlice(QPieSlice* sliceData)
229 {
141 {
230 //qDebug() << "PiePresenter::deleteSlice()" << sliceData;
142 //qDebug() << "PiePresenter::deleteSlice()" << sliceData;
231
143
232 if (!m_slices.contains(sliceData)) {
144 if (!m_slices.contains(sliceData)) {
233 Q_ASSERT(0); // TODO: how to handle this nicely?
145 Q_ASSERT(0); // TODO: how to handle this nicely?
234 return;
146 return;
235 }
147 }
236
148
237 delete m_slices.take(sliceData);
149 delete m_slices.take(sliceData);
238 }
150 }
239
151
240 #include "moc_piepresenter_p.cpp"
152 #include "moc_piepresenter_p.cpp"
241
153
242 QTCOMMERCIALCHART_END_NAMESPACE
154 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,52 +1,48
1 #ifndef PIEPRESENTER_H
1 #ifndef PIEPRESENTER_H
2 #define PIEPRESENTER_H
2 #define PIEPRESENTER_H
3
3
4 #include "chartitem_p.h"
4 #include "chartitem_p.h"
5 #include "qpieseries.h"
5 #include "qpieseries.h"
6 #include <QSignalMapper>
6 #include <QSignalMapper>
7
7
8 class QGraphicsItem;
8 class QGraphicsItem;
9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 class PieSlice;
10 class PieSlice;
11
11
12 #define PI 3.14159265 // TODO: is this defined in some header?
13
14 class PiePresenter : public QObject, public ChartItem
12 class PiePresenter : public QObject, public ChartItem
15 {
13 {
16 Q_OBJECT
14 Q_OBJECT
17
15
18 public:
16 public:
19 // TODO: use a generic data class instead of x and y
17 // TODO: use a generic data class instead of x and y
20 PiePresenter(QGraphicsItem *parent, QPieSeries *series);
18 PiePresenter(QGraphicsItem *parent, QPieSeries *series);
21 ~PiePresenter();
19 ~PiePresenter();
22
20
23 public: // from QGraphicsItem
21 public: // from QGraphicsItem
24 QRectF boundingRect() const { return m_rect; }
22 QRectF boundingRect() const { return m_rect; }
25 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
23 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
26
24
27 public:
28 QRectF pieRect() const { return m_pieRect; }
29
30 public Q_SLOTS:
25 public Q_SLOTS:
31 void handleSeriesChanged(const QPieSeries::ChangeSet& changeSet);
26 void handleSeriesChanged(const QPieSeries::ChangeSet& changeSet);
32 void handleDomainChanged(const Domain& domain);
27 void handleDomainChanged(const Domain& domain);
33 void handleGeometryChanged(const QRectF& rect);
28 void handleGeometryChanged(const QRectF& rect);
34 void updateGeometry();
29 void updateGeometry();
35
30
36 private:
31 private:
37 void addSlice(QPieSlice* sliceData);
32 void addSlice(QPieSlice* sliceData);
38 void updateSlice(QPieSlice* sliceData);
33 void updateSlice(QPieSlice* sliceData);
39 void deleteSlice(QPieSlice* sliceData);
34 void deleteSlice(QPieSlice* sliceData);
40
35
41 private:
36 private:
42 friend class PieSlice;
37 friend class PieSlice;
43 QHash<QPieSlice*, PieSlice*> m_slices;
38 QHash<QPieSlice*, PieSlice*> m_slices;
44 QPieSeries *m_series;
39 QPieSeries *m_series;
45 QRectF m_rect;
40 QRectF m_rect;
46 QRectF m_pieRect;
41 QPointF m_pieCenter;
42 qreal m_pieRadius;
47 QRectF m_debugRect;
43 QRectF m_debugRect;
48 };
44 };
49
45
50 QTCOMMERCIALCHART_END_NAMESPACE
46 QTCOMMERCIALCHART_END_NAMESPACE
51
47
52 #endif // PIEPRESENTER_H
48 #endif // PIEPRESENTER_H
@@ -1,201 +1,208
1 #include "pieslice_p.h"
1 #include "pieslice_p.h"
2 #include "piepresenter_p.h"
2 #include "piepresenter_p.h"
3 #include "qpieseries.h"
3 #include "qpieseries.h"
4 #include "qpieslice.h"
4 #include "qpieslice.h"
5 #include <QPainter>
5 #include <QPainter>
6 #include <QDebug>
6 #include <QDebug>
7 #include <qmath.h>
7 #include <qmath.h>
8 #include <QGraphicsSceneEvent>
8 #include <QGraphicsSceneEvent>
9 #include <QTime>
9 #include <QTime>
10
10
11 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 QTCOMMERCIALCHART_BEGIN_NAMESPACE
12
12
13 #define PI 3.14159265 // TODO: is this defined in some header?
14
13 QPointF offset(qreal angle, qreal length)
15 QPointF offset(qreal angle, qreal length)
14 {
16 {
15 qreal dx = qSin(angle*(PI/180)) * length;
17 qreal dx = qSin(angle*(PI/180)) * length;
16 qreal dy = qCos(angle*(PI/180)) * length;
18 qreal dy = qCos(angle*(PI/180)) * length;
17 return QPointF(dx, -dy);
19 return QPointF(dx, -dy);
18 }
20 }
19
21
20 PieSlice::PieSlice(QGraphicsItem* parent)
22 PieSlice::PieSlice(QGraphicsItem* parent)
21 :QGraphicsObject(parent),
23 :QGraphicsObject(parent),
24 m_pieRadius(0),
22 m_startAngle(0),
25 m_startAngle(0),
23 m_angleSpan(0),
26 m_angleSpan(0),
24 m_isExploded(false),
27 m_isExploded(false),
25 m_explodeDistance(0),
28 m_explodeDistanceFactor(0),
26 m_labelVisible(false)
29 m_labelVisible(false),
30 m_labelArmLengthFactor(0)
27 {
31 {
28 setAcceptHoverEvents(true);
32 setAcceptHoverEvents(true);
29 setAcceptedMouseButtons(Qt::LeftButton);
33 setAcceptedMouseButtons(Qt::LeftButton);
30 }
34 }
31
35
32 PieSlice::~PieSlice()
36 PieSlice::~PieSlice()
33 {
37 {
34
38
35 }
39 }
36
40
37 QRectF PieSlice::boundingRect() const
41 QRectF PieSlice::boundingRect() const
38 {
42 {
39 return m_slicePath.boundingRect();
43 return m_slicePath.boundingRect();
40 }
44 }
41
45
42 QPainterPath PieSlice::shape() const
46 QPainterPath PieSlice::shape() const
43 {
47 {
48 // Don't include the label and label arm.
49 // This is used to detect a mouse clicks. We do not want clicks from label.
44 return m_slicePath;
50 return m_slicePath;
45 }
51 }
46
52
47 void PieSlice::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
53 void PieSlice::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
48 {
54 {
55 painter->setClipRect(parentItem()->boundingRect());
56
49 painter->save();
57 painter->save();
50 painter->setPen(m_pen);
58 painter->setPen(m_pen);
51 painter->setBrush(m_brush);
59 painter->setBrush(m_brush);
52 painter->drawPath(m_slicePath);
60 painter->drawPath(m_slicePath);
53 painter->restore();
61 painter->restore();
54
62
55 if (m_labelVisible) {
63 if (m_labelVisible) {
56 painter->save();
64 painter->save();
57 painter->setPen(m_labelArmPen);
65 painter->setPen(m_labelArmPen);
58 painter->drawPath(m_labelArmPath);
66 painter->drawPath(m_labelArmPath);
59 painter->restore();
67 painter->restore();
60
68
61 painter->setFont(m_labelFont);
69 painter->setFont(m_labelFont);
62 painter->drawText(m_labelTextRect.bottomLeft(), m_labelText);
70 painter->drawText(m_labelTextRect.bottomLeft(), m_labelText);
63 }
71 }
64 }
72 }
65
73
66 void PieSlice::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
74 void PieSlice::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
67 {
75 {
68 emit hoverEnter();
76 emit hoverEnter();
69 }
77 }
70
78
71 void PieSlice::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
79 void PieSlice::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
72 {
80 {
73 emit hoverLeave();
81 emit hoverLeave();
74 }
82 }
75
83
76 void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/)
84 void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/)
77 {
85 {
78 emit clicked();
86 emit clicked();
79 }
87 }
80
88
81 void PieSlice::setPieRect(QRectF rect)
89 void PieSlice::setPieCenterAndRadius(QPointF center, qreal radius)
82 {
90 {
83 m_pieRect = rect;
91 m_pieCenter = center;
92 m_pieRadius = radius;
84 }
93 }
85
94
86 void PieSlice::updateGeometry()
95 void PieSlice::updateGeometry()
87 {
96 {
88 if (!m_pieRect.isValid() || m_pieRect.isEmpty())
97 if (m_pieRadius <= 0)
89 return;
98 return;
90
99
91 prepareGeometryChange();
100 prepareGeometryChange();
92
101
93 // update slice path
102 // update slice path
94 QPointF center = m_pieRect.center();
95 qreal radius = m_pieRect.height() / 2;
96 qreal centerAngle;
103 qreal centerAngle;
97 QPointF armStart;
104 QPointF armStart;
98 m_slicePath = slicePath(center, radius, m_startAngle, m_angleSpan, m_isExploded, m_explodeDistance, &centerAngle, &armStart);
105 m_slicePath = slicePath(m_pieCenter, m_pieRadius, m_startAngle, m_angleSpan, m_isExploded, m_pieRadius * m_explodeDistanceFactor, &centerAngle, &armStart);
99
106
100 // update text rect
107 // update text rect
101 m_labelTextRect = labelTextRect(m_labelFont, m_labelText);
108 m_labelTextRect = labelTextRect(m_labelFont, m_labelText);
102
109
103 // update label arm path
110 // update label arm path
104 QPointF labelTextStart;
111 QPointF labelTextStart;
105 m_labelArmPath = labelArmPath(armStart, centerAngle, m_labelArmLength, m_labelTextRect.width(), &labelTextStart);
112 m_labelArmPath = labelArmPath(armStart, centerAngle, m_pieRadius * m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
106
113
107 // update text position
114 // update text position
108 m_labelTextRect.moveBottomLeft(labelTextStart);
115 m_labelTextRect.moveBottomLeft(labelTextStart);
109
116
110 //qDebug() << "PieSlice::updateGeometry" << m_slicelabel->text() << boundingRect() << m_angle << m_span;
117 //qDebug() << "PieSlice::updateGeometry" << m_labelText << boundingRect() << m_startAngle << m_startAngle + m_angleSpan;
111 }
118 }
112
119
113 void PieSlice::updateData(const QPieSlice* sliceData)
120 void PieSlice::updateData(const QPieSlice* sliceData)
114 {
121 {
115 // TODO: compare what has changes to avoid unneccesary geometry updates
122 // TODO: compare what has changes to avoid unneccesary geometry updates
116
123
117 m_startAngle = sliceData->startAngle();
124 m_startAngle = sliceData->startAngle();
118 m_angleSpan = sliceData->m_angleSpan;
125 m_angleSpan = sliceData->m_angleSpan;
119 m_isExploded = sliceData->isExploded();
126 m_isExploded = sliceData->isExploded();
120 m_explodeDistance = sliceData->explodeDistance();
127 m_explodeDistanceFactor = sliceData->explodeDistanceFactor();
121 m_pen = sliceData->pen();
128 m_pen = sliceData->pen();
122 m_brush = sliceData->brush();
129 m_brush = sliceData->brush();
123
130
124 m_labelVisible = sliceData->isLabelVisible();
131 m_labelVisible = sliceData->isLabelVisible();
125 m_labelText = sliceData->label();
132 m_labelText = sliceData->label();
126 m_labelFont = sliceData->labelFont();
133 m_labelFont = sliceData->labelFont();
127 m_labelArmLength = sliceData->labelArmLength();
134 m_labelArmLengthFactor = sliceData->labelArmLengthFactor();
128 m_labelArmPen = sliceData->labelPen();
135 m_labelArmPen = sliceData->labelPen();
129
136
130 updateGeometry();
137 updateGeometry();
131 update();
138 update();
132 }
139 }
133
140
134 QPainterPath PieSlice::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, bool exploded, qreal explodeDistance, qreal* centerAngle, QPointF* armStart)
141 QPainterPath PieSlice::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, bool exploded, qreal explodeDistance, qreal* centerAngle, QPointF* armStart)
135 {
142 {
136 // calculate center angle
143 // calculate center angle
137 *centerAngle = startAngle + (angleSpan/2);
144 *centerAngle = startAngle + (angleSpan/2);
138
145
139 // calculate slice rectangle
146 // calculate slice rectangle
140 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
147 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
141
148
142 // adjust rect for exploding
149 // adjust rect for exploding
143 if (exploded) {
150 if (exploded) {
144 qreal dx = qSin(*centerAngle*(PI/180)) * explodeDistance;
151 qreal dx = qSin(*centerAngle*(PI/180)) * explodeDistance;
145 qreal dy = -qCos(*centerAngle*(PI/180)) * explodeDistance;
152 qreal dy = -qCos(*centerAngle*(PI/180)) * explodeDistance;
146 rect.translate(dx, dy);
153 rect.translate(dx, dy);
147 }
154 }
148
155
149 // slice path
156 // slice path
150 // TODO: draw the shape so that it might have a hole in the center
157 // TODO: draw the shape so that it might have a hole in the center
151 QPainterPath path;
158 QPainterPath path;
152 path.moveTo(rect.center());
159 path.moveTo(rect.center());
153 path.arcTo(rect, -startAngle + 90, -angleSpan);
160 path.arcTo(rect, -startAngle + 90, -angleSpan);
154 path.closeSubpath();
161 path.closeSubpath();
155
162
156 // calculate label arm start point
163 // calculate label arm start point
157 *armStart = center;
164 *armStart = center;
158 if (exploded)
165 if (exploded)
159 *armStart += offset(*centerAngle, explodeDistance + radius + PIESLICE_LABEL_GAP);
166 *armStart += offset(*centerAngle, explodeDistance + radius + PIESLICE_LABEL_GAP);
160 else
167 else
161 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
168 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
162
169
163 return path;
170 return path;
164 }
171 }
165
172
166 QPainterPath PieSlice::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart)
173 QPainterPath PieSlice::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart)
167 {
174 {
168 qreal dx = qSin(angle*(PI/180)) * length;
175 qreal dx = qSin(angle*(PI/180)) * length;
169 qreal dy = -qCos(angle*(PI/180)) * length;
176 qreal dy = -qCos(angle*(PI/180)) * length;
170 QPointF parm1 = start + QPointF(dx, dy);
177 QPointF parm1 = start + QPointF(dx, dy);
171
178
172 QPointF parm2 = parm1;
179 QPointF parm2 = parm1;
173 if (angle < 180) { // arm swings the other way on the left side
180 if (angle < 180) { // arm swings the other way on the left side
174 parm2 += QPointF(textWidth, 0);
181 parm2 += QPointF(textWidth, 0);
175 *textStart = parm1;
182 *textStart = parm1;
176 }
183 }
177 else {
184 else {
178 parm2 += QPointF(-textWidth,0);
185 parm2 += QPointF(-textWidth,0);
179 *textStart = parm2;
186 *textStart = parm2;
180 }
187 }
181
188
182 // elevate the text position a bit so that it does not hit the line
189 // elevate the text position a bit so that it does not hit the line
183 *textStart += QPointF(0, -5);
190 *textStart += QPointF(0, -5);
184
191
185 QPainterPath path;
192 QPainterPath path;
186 path.moveTo(start);
193 path.moveTo(start);
187 path.lineTo(parm1);
194 path.lineTo(parm1);
188 path.lineTo(parm2);
195 path.lineTo(parm2);
189
196
190 return path;
197 return path;
191 }
198 }
192
199
193 QRectF PieSlice::labelTextRect(QFont font, QString text)
200 QRectF PieSlice::labelTextRect(QFont font, QString text)
194 {
201 {
195 QFontMetricsF fm(font);
202 QFontMetricsF fm(font);
196 return fm.boundingRect(text);
203 return fm.boundingRect(text);
197 }
204 }
198
205
199 #include "moc_pieslice_p.cpp"
206 #include "moc_pieslice_p.cpp"
200
207
201 QTCOMMERCIALCHART_END_NAMESPACE
208 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,73 +1,74
1 #ifndef PIESLICE_H
1 #ifndef PIESLICE_H
2 #define PIESLICE_H
2 #define PIESLICE_H
3
3
4 #include "qchartglobal.h"
4 #include "qchartglobal.h"
5 #include "charttheme_p.h"
5 #include "charttheme_p.h"
6 #include "qpieseries.h"
6 #include "qpieseries.h"
7 #include <QGraphicsItem>
7 #include <QGraphicsItem>
8 #include <QRectF>
8 #include <QRectF>
9 #include <QColor>
9 #include <QColor>
10 #include <QPen>
10 #include <QPen>
11
11
12 #define PIESLICE_LABEL_GAP 5
12 #define PIESLICE_LABEL_GAP 5
13
13
14 QTCOMMERCIALCHART_BEGIN_NAMESPACE
14 QTCOMMERCIALCHART_BEGIN_NAMESPACE
15 class PiePresenter;
15 class PiePresenter;
16 class PieSliceLabel;
16 class PieSliceLabel;
17 class QPieSlice;
17 class QPieSlice;
18
18
19 class PieSlice : public QGraphicsObject
19 class PieSlice : public QGraphicsObject
20 {
20 {
21 Q_OBJECT
21 Q_OBJECT
22
22
23 public:
23 public:
24 PieSlice(QGraphicsItem* parent = 0);
24 PieSlice(QGraphicsItem* parent = 0);
25 ~PieSlice();
25 ~PieSlice();
26
26
27 public: // from QGraphicsItem
27 public: // from QGraphicsItem
28 QRectF boundingRect() const;
28 QRectF boundingRect() const;
29 QPainterPath shape() const;
29 QPainterPath shape() const;
30 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
30 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
31 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
31 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
32 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
32 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
33 void mousePressEvent(QGraphicsSceneMouseEvent *event);
33 void mousePressEvent(QGraphicsSceneMouseEvent *event);
34
34
35 Q_SIGNALS:
35 Q_SIGNALS:
36 void clicked();
36 void clicked();
37 void hoverEnter();
37 void hoverEnter();
38 void hoverLeave();
38 void hoverLeave();
39
39
40 public Q_SLOTS:
40 public Q_SLOTS:
41 void setPieRect(QRectF rect);
41 void setPieCenterAndRadius(QPointF center, qreal radius);
42 void updateGeometry();
42 void updateGeometry();
43 void updateData(const QPieSlice *sliceData);
43 void updateData(const QPieSlice *sliceData);
44
44
45 public:
45 public:
46 static QPainterPath slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, bool exploded, qreal explodeDistance, qreal* centerAngle, QPointF* armStart);
46 static QPainterPath slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, bool exploded, qreal explodeDistance, qreal* centerAngle, QPointF* armStart);
47 static QPainterPath labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart);
47 static QPainterPath labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart);
48 static QRectF labelTextRect(QFont font, QString text);
48 static QRectF labelTextRect(QFont font, QString text);
49
49
50 private:
50 private:
51 QRectF m_pieRect;
51 QPointF m_pieCenter;
52 qreal m_pieRadius;
52
53
53 QPainterPath m_slicePath;
54 QPainterPath m_slicePath;
54 qreal m_startAngle;
55 qreal m_startAngle;
55 qreal m_angleSpan;
56 qreal m_angleSpan;
56 bool m_isExploded;
57 bool m_isExploded;
57 qreal m_explodeDistance;
58 qreal m_explodeDistanceFactor;
58 bool m_labelVisible;
59 bool m_labelVisible;
59 QPen m_pen;
60 QPen m_pen;
60 QBrush m_brush;
61 QBrush m_brush;
61
62
62 QPainterPath m_labelArmPath;
63 QPainterPath m_labelArmPath;
63 qreal m_labelArmLength;
64 qreal m_labelArmLengthFactor;
64 QPen m_labelArmPen;
65 QPen m_labelArmPen;
65
66
66 QRectF m_labelTextRect;
67 QRectF m_labelTextRect;
67 QFont m_labelFont;
68 QFont m_labelFont;
68 QString m_labelText;
69 QString m_labelText;
69 };
70 };
70
71
71 QTCOMMERCIALCHART_END_NAMESPACE
72 QTCOMMERCIALCHART_END_NAMESPACE
72
73
73 #endif // PIESLICE_H
74 #endif // PIESLICE_H
@@ -1,517 +1,562
1 #include "qpieseries.h"
1 #include "qpieseries.h"
2 #include "qpieslice.h"
2 #include "qpieslice.h"
3 #include <QDebug>
3 #include <QDebug>
4
4
5 QTCOMMERCIALCHART_BEGIN_NAMESPACE
5 QTCOMMERCIALCHART_BEGIN_NAMESPACE
6
6
7
7
8 /*!
8 /*!
9 \class QPieSeries::ChangeSet
9 \class QPieSeries::ChangeSet
10 \brief Defines the changes in the series.
10 \brief Defines the changes in the series.
11
11
12 Contains the changes that have occurred in the series. Lists of added, changed and removed slices.
12 Contains the changes that have occurred in the series. Lists of added, changed and removed slices.
13
13
14 \sa QPieSeries::changed()
14 \sa QPieSeries::changed()
15 */
15 */
16
16
17 /*!
17 /*!
18 \internal
18 \internal
19 */
19 */
20 void QPieSeries::ChangeSet::appendAdded(QPieSlice* slice)
20 void QPieSeries::ChangeSet::appendAdded(QPieSlice* slice)
21 {
21 {
22 if (!m_added.contains(slice))
22 if (!m_added.contains(slice))
23 m_added << slice;
23 m_added << slice;
24 }
24 }
25
25
26 /*!
26 /*!
27 \internal
27 \internal
28 */
28 */
29 void QPieSeries::ChangeSet::appendAdded(QList<QPieSlice*> slices)
29 void QPieSeries::ChangeSet::appendAdded(QList<QPieSlice*> slices)
30 {
30 {
31 foreach (QPieSlice* s, slices)
31 foreach (QPieSlice* s, slices)
32 appendAdded(s);
32 appendAdded(s);
33 }
33 }
34
34
35 /*!
35 /*!
36 \internal
36 \internal
37 */
37 */
38 void QPieSeries::ChangeSet::appendChanged(QPieSlice* slice)
38 void QPieSeries::ChangeSet::appendChanged(QPieSlice* slice)
39 {
39 {
40 if (!m_changed.contains(slice))
40 if (!m_changed.contains(slice))
41 m_changed << slice;
41 m_changed << slice;
42 }
42 }
43
43
44 /*!
44 /*!
45 \internal
45 \internal
46 */
46 */
47 void QPieSeries::ChangeSet::appendRemoved(QPieSlice* slice)
47 void QPieSeries::ChangeSet::appendRemoved(QPieSlice* slice)
48 {
48 {
49 if (!m_removed.contains(slice))
49 if (!m_removed.contains(slice))
50 m_removed << slice;
50 m_removed << slice;
51 }
51 }
52
52
53 /*!
53 /*!
54 Returns a list of slices that have been added to the series.
54 Returns a list of slices that have been added to the series.
55 \sa QPieSeries::changed()
55 \sa QPieSeries::changed()
56 */
56 */
57 QList<QPieSlice*> QPieSeries::ChangeSet::added() const
57 QList<QPieSlice*> QPieSeries::ChangeSet::added() const
58 {
58 {
59 return m_added;
59 return m_added;
60 }
60 }
61
61
62 /*!
62 /*!
63 Returns a list of slices that have been changed in the series.
63 Returns a list of slices that have been changed in the series.
64 \sa QPieSeries::changed()
64 \sa QPieSeries::changed()
65 */
65 */
66 QList<QPieSlice*> QPieSeries::ChangeSet::changed() const
66 QList<QPieSlice*> QPieSeries::ChangeSet::changed() const
67 {
67 {
68 return m_changed;
68 return m_changed;
69 }
69 }
70
70
71 /*!
71 /*!
72 Returns a list of slices that have been removed from the series.
72 Returns a list of slices that have been removed from the series.
73 \sa QPieSeries::changed()
73 \sa QPieSeries::changed()
74 */
74 */
75 QList<QPieSlice*> QPieSeries::ChangeSet::removed() const
75 QList<QPieSlice*> QPieSeries::ChangeSet::removed() const
76 {
76 {
77 return m_removed;
77 return m_removed;
78 }
78 }
79
79
80
80
81 /*!
81 /*!
82 Returns true if there are no added/changed or removed slices in the change set.
82 Returns true if there are no added/changed or removed slices in the change set.
83 */
83 */
84 bool QPieSeries::ChangeSet::isEmpty() const
84 bool QPieSeries::ChangeSet::isEmpty() const
85 {
85 {
86 if (m_added.count() || m_changed.count() || m_removed.count())
86 if (m_added.count() || m_changed.count() || m_removed.count())
87 return false;
87 return false;
88 return true;
88 return true;
89 }
89 }
90
90
91 /*!
91 /*!
92 \enum QPieSeries::PiePosition
93
94 This enum describes pie position within its bounding rectangle
95
96 \value PiePositionMaximized
97 \value PiePositionTopLeft
98 \value PiePositionTopRight
99 \value PiePositionBottomLeft
100 \value PiePositionBottomRight
101 */
102
103 /*!
104 \class QPieSeries
92 \class QPieSeries
105 \brief Pie series API for QtCommercial Charts
93 \brief Pie series API for QtCommercial Charts
106
94
107 The pie series defines a pie chart which consists of pie slices which are QPieSlice objects.
95 The pie series defines a pie chart which consists of pie slices which are QPieSlice objects.
108 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
96 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
109 The actual slice size is determined by that relative value.
97 The actual slice size is determined by that relative value.
110
98
111 By default the pie is defined as a full pie but it can be a partial pie.
99 By default the pie is defined as a full pie but it can be a partial pie.
112 This can be done by setting a starting angle and angle span to the series.
100 This can be done by setting a starting angle and angle span to the series.
113 */
101 */
114
102
115 /*!
103 /*!
116 Constructs a series object which is a child of \a parent.
104 Constructs a series object which is a child of \a parent.
117 */
105 */
118 QPieSeries::QPieSeries(QObject *parent) :
106 QPieSeries::QPieSeries(QObject *parent) :
119 QSeries(parent),
107 QSeries(parent),
120 m_sizeFactor(1.0),
108 m_hPositionFactor(0.5),
121 m_position(PiePositionCenter),
109 m_vPositionFactor(0.5),
122 m_sizePolicy(PieSizePolicyMaximized),
110 m_pieSizeFactor(0.7),
123 m_pieStartAngle(0),
111 m_pieStartAngle(0),
124 m_pieEndAngle(360)
112 m_pieEndAngle(360),
113 m_total(0)
125 {
114 {
126
115
127 }
116 }
128
117
129 /*!
118 /*!
130 Destroys the object. Note that adding series to QChart transfers the ownership to the chart.
119 Destroys the object. Note that adding series to QChart transfers the ownership to the chart.
131 */
120 */
132 QPieSeries::~QPieSeries()
121 QPieSeries::~QPieSeries()
133 {
122 {
134
123
135 }
124 }
136
125
137 /*!
126 /*!
138 Returns QChartSeries::SeriesTypePie.
127 Returns QChartSeries::SeriesTypePie.
139 */
128 */
140 QSeries::QSeriesType QPieSeries::type() const
129 QSeries::QSeriesType QPieSeries::type() const
141 {
130 {
142 return QSeries::SeriesTypePie;
131 return QSeries::SeriesTypePie;
143 }
132 }
144
133
145 /*!
134 /*!
146 Sets an array of \a slices to the series replacing the existing slices.
135 Sets an array of \a slices to the series replacing the existing slices.
147 Slice ownership is passed to the series.
136 Slice ownership is passed to the series.
148 */
137 */
149 void QPieSeries::replace(QList<QPieSlice*> slices)
138 void QPieSeries::replace(QList<QPieSlice*> slices)
150 {
139 {
151 clear();
140 clear();
152 add(slices);
141 add(slices);
153 }
142 }
154
143
155 /*!
144 /*!
156 Adds an array of \a slices to the series.
145 Adds an array of \a slices to the series.
157 Slice ownership is passed to the series.
146 Slice ownership is passed to the series.
158 */
147 */
159 void QPieSeries::add(QList<QPieSlice*> slices)
148 void QPieSeries::add(QList<QPieSlice*> slices)
160 {
149 {
161 ChangeSet changeSet;
150 ChangeSet changeSet;
162 foreach (QPieSlice* s, slices) {
151 foreach (QPieSlice* s, slices) {
163 s->setParent(this);
152 s->setParent(this);
164 m_slices << s;
153 m_slices << s;
165 changeSet.appendAdded(s);
154 changeSet.appendAdded(s);
166 }
155 }
167
156
168 updateDerivativeData();
157 updateDerivativeData();
169
158
170 foreach (QPieSlice* s, slices) {
159 foreach (QPieSlice* s, slices) {
171 connect(s, SIGNAL(changed()), this, SLOT(sliceChanged()));
160 connect(s, SIGNAL(changed()), this, SLOT(sliceChanged()));
172 connect(s, SIGNAL(clicked()), this, SLOT(sliceClicked()));
161 connect(s, SIGNAL(clicked()), this, SLOT(sliceClicked()));
173 connect(s, SIGNAL(hoverEnter()), this, SLOT(sliceHoverEnter()));
162 connect(s, SIGNAL(hoverEnter()), this, SLOT(sliceHoverEnter()));
174 connect(s, SIGNAL(hoverLeave()), this, SLOT(sliceHoverLeave()));
163 connect(s, SIGNAL(hoverLeave()), this, SLOT(sliceHoverLeave()));
175 }
164 }
176
165
177 emit changed(changeSet);
166 emit changed(changeSet);
178 }
167 }
179
168
180 /*!
169 /*!
181 Adds a single \a slice to the series.
170 Adds a single \a slice to the series.
182 Slice ownership is passed to the series.
171 Slice ownership is passed to the series.
183 */
172 */
184 void QPieSeries::add(QPieSlice* slice)
173 void QPieSeries::add(QPieSlice* slice)
185 {
174 {
186 add(QList<QPieSlice*>() << slice);
175 add(QList<QPieSlice*>() << slice);
187 }
176 }
188
177
189 /*!
178 /*!
190 Adds a single \a slice to the series and returns a reference to the series.
179 Adds a single \a slice to the series and returns a reference to the series.
191 Slice ownership is passed to the series.
180 Slice ownership is passed to the series.
192 */
181 */
193 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
182 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
194 {
183 {
195 add(slice);
184 add(slice);
196 return *this;
185 return *this;
197 }
186 }
198
187
199
188
200 /*!
189 /*!
201 Adds a single slice to the series with give \a value and \a name.
190 Adds a single slice to the series with give \a value and \a name.
202 Slice ownership is passed to the series.
191 Slice ownership is passed to the series.
203 */
192 */
204 QPieSlice* QPieSeries::add(qreal value, QString name)
193 QPieSlice* QPieSeries::add(qreal value, QString name)
205 {
194 {
206 QPieSlice* slice = new QPieSlice(value, name);
195 QPieSlice* slice = new QPieSlice(value, name);
207 add(slice);
196 add(slice);
208 return slice;
197 return slice;
209 }
198 }
210
199
211 /*!
200 /*!
212 Removes a single \a slice from the series and deletes the slice.
201 Removes a single \a slice from the series and deletes the slice.
213
202
214 Do not reference this pointer after this call.
203 Do not reference this pointer after this call.
215 */
204 */
216 void QPieSeries::remove(QPieSlice* slice)
205 void QPieSeries::remove(QPieSlice* slice)
217 {
206 {
218 if (!m_slices.removeOne(slice)) {
207 if (!m_slices.removeOne(slice)) {
219 Q_ASSERT(0); // TODO: how should this be reported?
208 Q_ASSERT(0); // TODO: how should this be reported?
220 return;
209 return;
221 }
210 }
222
211
223 ChangeSet changeSet;
212 ChangeSet changeSet;
224 changeSet.appendRemoved(slice);
213 changeSet.appendRemoved(slice);
225 emit changed(changeSet);
214 emit changed(changeSet);
226
215
227 delete slice;
216 delete slice;
228 slice = NULL;
217 slice = NULL;
229
218
230 updateDerivativeData();
219 updateDerivativeData();
231 }
220 }
232
221
233 /*!
222 /*!
234 Clears all slices from the series.
223 Clears all slices from the series.
235 */
224 */
236 void QPieSeries::clear()
225 void QPieSeries::clear()
237 {
226 {
238 if (m_slices.count() == 0)
227 if (m_slices.count() == 0)
239 return;
228 return;
240
229
241 ChangeSet changeSet;
230 ChangeSet changeSet;
242 foreach (QPieSlice* s, m_slices) {
231 foreach (QPieSlice* s, m_slices) {
243 changeSet.appendRemoved(s);
232 changeSet.appendRemoved(s);
244 m_slices.removeOne(s);
233 m_slices.removeOne(s);
245 delete s;
234 delete s;
246 }
235 }
247 emit changed(changeSet);
236 emit changed(changeSet);
248 updateDerivativeData();
237 updateDerivativeData();
249 }
238 }
250
239
251 /*!
240 /*!
252 Counts the number of the slices in this series.
241 Counts the number of the slices in this series.
253 */
242 */
254 int QPieSeries::count() const
243 int QPieSeries::count() const
255 {
244 {
256 return m_slices.count();
245 return m_slices.count();
257 }
246 }
258
247
259 /*!
248 /*!
260 Returns a list of slices that belong to this series.
249 Returns a list of slices that belong to this series.
261 */
250 */
262 QList<QPieSlice*> QPieSeries::slices() const
251 QList<QPieSlice*> QPieSeries::slices() const
263 {
252 {
264 return m_slices;
253 return m_slices;
265 }
254 }
266
255
267 /*!
256 /*!
268 Sets the size \a factor of the pie. 1.0 is the default value.
257 Sets the center position of the pie by \a horizontalFactor and \a verticalFactor.
269 Note that the pie will not grow beyond its absolute maximum size.
258
270 In practice its use is to make the pie appear smaller.
259 The factors are relative to the chart rectangle where:
271 \sa sizeFactor()
260
261 \a horizontalFactor 0.0 means the absolute left.
262 \a horizontalFactor 1.0 means the absolute right.
263 \a verticalFactor 0.0 means the absolute top.
264 \a verticalFactor 1.0 means the absolute bottom.
265
266 By default \a horizontalFactor and \a verticalFactor are 0.5 which puts the pie in the middle of the chart rectangle.
267
268 \sa horizontalPositionFactor(), verticalPositionFactor(), setSizeFactor()
272 */
269 */
273 void QPieSeries::setSizeFactor(qreal factor)
270 void QPieSeries::setPositionFactors(qreal horizontalFactor, qreal verticalFactor)
274 {
271 {
275 if (factor < 0.0)
272 if (horizontalFactor < 0.0 || horizontalFactor > 1.0 || verticalFactor < 0.0 || verticalFactor > 1.0)
276 return;
273 return;
277
274
278 if (m_sizeFactor != factor) {
275 if (m_hPositionFactor != horizontalFactor || m_vPositionFactor != verticalFactor) {
279 m_sizeFactor = factor;
276 m_hPositionFactor = horizontalFactor;
280 emit sizeFactorChanged();
277 m_vPositionFactor = verticalFactor;
278 emit positionChanged();
281 }
279 }
282 }
280 }
283
281
284 /*!
282 /*!
285 Gets the size factor of the pie.
283 Gets the horizontal position factor of the pie.
286 \sa setSizeFactor()
287 */
288 qreal QPieSeries::sizeFactor() const
289 {
290 return m_sizeFactor;
291 }
292
284
293 /*!
285 The factors are relative to the chart rectangle where:
294 Sets the \a position of the pie within its bounding rectangle.
286
295 \sa PiePosition, position()
287 Horizontal factor 0.0 means the absolute left.
288 Horizontal factor 1.0 means the absolute right.
289
290 By default horizontal factor is 0.5 which puts the pie in the horizontal middle of the chart rectangle.
291
292 \sa setPositionFactors(), verticalPositionFactor(), setSizeFactor()
296 */
293 */
297 void QPieSeries::setPosition(PiePosition position)
294 qreal QPieSeries::horizontalPositionFactor() const
298 {
295 {
299 // TODO: sanity check
296 return m_hPositionFactor;
300 if (m_position != position) {
301 m_position = position;
302 emit positionChanged();
303 }
304 }
297 }
305
298
306 /*!
299 /*!
307 Gets the position of the pie within its bounding rectangle.
300 Gets the vertical position factor of the pie.
308 \sa PiePosition, setPosition()
301
302 The factors are relative to the chart rectangle where:
303
304 Vertical factor 0.0 means the absolute top.
305 Vertical factor 1.0 means the absolute bottom.
306
307 By default vertical factor is 0.5 which puts the pie in the vertical middle of the chart rectangle.
308
309 \sa setPositionFactors(), horizontalPositionFactor(), setSizeFactor()
309 */
310 */
310 QPieSeries::PiePosition QPieSeries::position() const
311 qreal QPieSeries::verticalPositionFactor() const
311 {
312 {
312 return m_position;
313 return m_vPositionFactor;
313 }
314 }
314
315
315 /*!
316 /*!
316 Sets the \a sizePolicy of the pie.
317 Sets the size \a sizeFactor of the pie.
317 \sa PieSizePolicy, sizePolicy()
318
319 The size factor is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
320
321 Default value is 0.7.
322
323 \sa sizeFactor(), setPositionFactors(), verticalPositionFactor(), horizontalPositionFactor()
318 */
324 */
319 void QPieSeries::setSizePolicy(PieSizePolicy sizePolicy)
325 void QPieSeries::setSizeFactor(qreal sizeFactor)
320 {
326 {
321 // TODO: sanity check
327 if (sizeFactor < 0.0)
322 if (m_sizePolicy != sizePolicy) {
328 return;
323 m_sizePolicy = sizePolicy;
329
324 emit sizePolicyChanged();
330 if (m_pieSizeFactor != sizeFactor) {
331 m_pieSizeFactor = sizeFactor;
332 emit sizeFactorChanged();
325 }
333 }
326 }
334 }
327
335
328 /*!
336 /*!
329 Gets the size policy of the pie.
337 Gets the size factor of the pie.
330 \sa PieSizePolicy, setSizePolicy()
338
339 The size factor is defined so that the 1.0 is the maximum that can fit the given chart rectangle.
340
341 Default value is 0.7.
342
343 \sa setSizeFactor(), setPositionFactors(), verticalPositionFactor(), horizontalPositionFactor()
331 */
344 */
332 QPieSeries::PieSizePolicy QPieSeries::sizePolicy() const
345 qreal QPieSeries::sizeFactor() const
333 {
346 {
334 return m_sizePolicy;
347 return m_pieSizeFactor;
335 }
348 }
336
349
337
350
351 /*!
352 Sets the end angle of the pie.
353
354 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
355
356 \a startAngle must be less than end angle. Default value is 0.
357
358 \sa startAngle(), endAngle(), setEndAngle()
359 */
338 void QPieSeries::setStartAngle(qreal startAngle)
360 void QPieSeries::setStartAngle(qreal startAngle)
339 {
361 {
340 if (startAngle >= 0 && startAngle <= 360 && startAngle != m_pieStartAngle && startAngle <= m_pieEndAngle) {
362 if (startAngle >= 0 && startAngle <= 360 && startAngle != m_pieStartAngle && startAngle <= m_pieEndAngle) {
341 m_pieStartAngle = startAngle;
363 m_pieStartAngle = startAngle;
342 updateDerivativeData();
364 updateDerivativeData();
343 }
365 }
344 }
366 }
345
367
368 /*!
369 Gets the start angle of the pie.
370
371 Full pie is 360 degrees where 0 degrees is at 12 a'clock. Default value is 360.
372
373 \sa setStartAngle(), endAngle(), setEndAngle()
374 */
346 qreal QPieSeries::startAngle() const
375 qreal QPieSeries::startAngle() const
347 {
376 {
348 return m_pieStartAngle;
377 return m_pieStartAngle;
349 }
378 }
350
379
380 /*!
381 Sets the end angle of the pie.
382
383 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
384
385 \a endAngle must be greater than start angle.
386
387 \sa endAngle(), startAngle(), setStartAngle()
388 */
351 void QPieSeries::setEndAngle(qreal endAngle)
389 void QPieSeries::setEndAngle(qreal endAngle)
352 {
390 {
353 if (endAngle >= 0 && endAngle <= 360 && endAngle != m_pieEndAngle && endAngle >= m_pieStartAngle) {
391 if (endAngle >= 0 && endAngle <= 360 && endAngle != m_pieEndAngle && endAngle >= m_pieStartAngle) {
354 m_pieEndAngle = endAngle;
392 m_pieEndAngle = endAngle;
355 updateDerivativeData();
393 updateDerivativeData();
356 }
394 }
357 }
395 }
358
396
397 /*!
398 Returns the end angle of the pie.
399
400 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
401
402 \sa setEndAngle(), startAngle(), setStartAngle()
403 */
359 qreal QPieSeries::endAngle() const
404 qreal QPieSeries::endAngle() const
360 {
405 {
361 return m_pieEndAngle;
406 return m_pieEndAngle;
362 }
407 }
363
408
364 /*!
409 /*!
365 Sets the all the slice labels \a visible or invisible.
410 Sets the all the slice labels \a visible or invisible.
366
411
367 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
412 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
368 */
413 */
369 void QPieSeries::setLabelsVisible(bool visible)
414 void QPieSeries::setLabelsVisible(bool visible)
370 {
415 {
371 foreach (QPieSlice* s, m_slices)
416 foreach (QPieSlice* s, m_slices)
372 s->setLabelVisible(visible);
417 s->setLabelVisible(visible);
373 }
418 }
374
419
375 /*!
420 /*!
376 Returns the sum of all slice values in this series.
421 Returns the sum of all slice values in this series.
377
422
378 \sa QPieSlice::value(), QPieSlice::setValue()
423 \sa QPieSlice::value(), QPieSlice::setValue()
379 */
424 */
380 qreal QPieSeries::total() const
425 qreal QPieSeries::total() const
381 {
426 {
382 return m_total;
427 return m_total;
383 }
428 }
384
429
385 /*!
430 /*!
386 \fn void QPieSeries::changed(const QPieSeries::ChangeSet& changeSet)
431 \fn void QPieSeries::changed(const QPieSeries::ChangeSet& changeSet)
387
432
388 This signal emitted when something has changed in the series.
433 This signal emitted when something has changed in the series.
389 The \a changeSet contains the details of which slices have been added, changed or removed.
434 The \a changeSet contains the details of which slices have been added, changed or removed.
390
435
391 \sa QPieSeries::ChangeSet, QPieSlice::changed()
436 \sa QPieSeries::ChangeSet, QPieSlice::changed()
392 */
437 */
393
438
394 /*!
439 /*!
395 \fn void QPieSeries::clicked(QPieSlice* slice)
440 \fn void QPieSeries::clicked(QPieSlice* slice)
396
441
397 This signal is emitted when a \a slice has been clicked.
442 This signal is emitted when a \a slice has been clicked.
398
443
399 \sa QPieSlice::clicked()
444 \sa QPieSlice::clicked()
400 */
445 */
401
446
402 /*!
447 /*!
403 \fn void QPieSeries::hoverEnter(QPieSlice* slice)
448 \fn void QPieSeries::hoverEnter(QPieSlice* slice)
404
449
405 This signal is emitted when user has hovered over a \a slice.
450 This signal is emitted when user has hovered over a \a slice.
406
451
407 \sa QPieSlice::hoverEnter()
452 \sa QPieSlice::hoverEnter()
408 */
453 */
409
454
410 /*!
455 /*!
411 \fn void QPieSeries::hoverLeave(QPieSlice* slice)
456 \fn void QPieSeries::hoverLeave(QPieSlice* slice)
412
457
413 This signal is emitted when user has hovered away from a \a slice.
458 This signal is emitted when user has hovered away from a \a slice.
414
459
415 \sa QPieSlice::hoverLeave()
460 \sa QPieSlice::hoverLeave()
416 */
461 */
417
462
418 /*!
463 /*!
419 \fn void QPieSeries::sizeFactorChanged()
464 \fn void QPieSeries::sizeFactorChanged()
420
465
421 This signal is emitted when size factor has been changed.
466 This signal is emitted when size factor has been changed.
422
467
423 \sa sizeFactor(), setSizeFactor()
468 \sa sizeFactor(), setSizeFactor()
424 */
469 */
425
470
426 /*!
471 /*!
427 \fn void QPieSeries::positionChanged()
472 \fn void QPieSeries::positionChanged()
428
473
429 This signal is emitted when position of the pie has been changed.
474 This signal is emitted when position of the pie has been changed.
430
475
431 \sa position(), setPosition()
476 \sa horizontalPositionFactor(), verticalPositionFactor(), setPositionFactors()
432 */
477 */
433
478
434 void QPieSeries::sliceChanged()
479 void QPieSeries::sliceChanged()
435 {
480 {
436 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
481 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
437 Q_ASSERT(m_slices.contains(slice));
482 Q_ASSERT(m_slices.contains(slice));
438
483
439 ChangeSet changeSet;
484 ChangeSet changeSet;
440 changeSet.appendChanged(slice);
485 changeSet.appendChanged(slice);
441 emit changed(changeSet);
486 emit changed(changeSet);
442
487
443 updateDerivativeData();
488 updateDerivativeData();
444 }
489 }
445
490
446 void QPieSeries::sliceClicked()
491 void QPieSeries::sliceClicked()
447 {
492 {
448 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
493 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
449 Q_ASSERT(m_slices.contains(slice));
494 Q_ASSERT(m_slices.contains(slice));
450 emit clicked(slice);
495 emit clicked(slice);
451 }
496 }
452
497
453 void QPieSeries::sliceHoverEnter()
498 void QPieSeries::sliceHoverEnter()
454 {
499 {
455 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
500 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
456 Q_ASSERT(m_slices.contains(slice));
501 Q_ASSERT(m_slices.contains(slice));
457 emit hoverEnter(slice);
502 emit hoverEnter(slice);
458 }
503 }
459
504
460 void QPieSeries::sliceHoverLeave()
505 void QPieSeries::sliceHoverLeave()
461 {
506 {
462 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
507 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
463 Q_ASSERT(m_slices.contains(slice));
508 Q_ASSERT(m_slices.contains(slice));
464 emit hoverLeave(slice);
509 emit hoverLeave(slice);
465 }
510 }
466
511
467 void QPieSeries::updateDerivativeData()
512 void QPieSeries::updateDerivativeData()
468 {
513 {
469 m_total = 0;
514 m_total = 0;
470
515
471 // nothing to do?
516 // nothing to do?
472 if (m_slices.count() == 0)
517 if (m_slices.count() == 0)
473 return;
518 return;
474
519
475 // calculate total
520 // calculate total
476 foreach (QPieSlice* s, m_slices)
521 foreach (QPieSlice* s, m_slices)
477 m_total += s->value();
522 m_total += s->value();
478
523
479 // we must have some values
524 // we must have some values
480 if (m_total == 0) {
525 if (m_total == 0) {
481 qDebug() << "QPieSeries::updateDerivativeData() total == 0";
526 qDebug() << "QPieSeries::updateDerivativeData() total == 0";
482 Q_ASSERT(m_total > 0); // TODO: is this the correct way to handle this?
527 Q_ASSERT(m_total > 0); // TODO: is this the correct way to handle this?
483 }
528 }
484
529
485 // update slice attributes
530 // update slice attributes
486 qreal sliceAngle = m_pieStartAngle;
531 qreal sliceAngle = m_pieStartAngle;
487 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
532 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
488 foreach (QPieSlice* s, m_slices) {
533 foreach (QPieSlice* s, m_slices) {
489
534
490 bool changed = false;
535 bool changed = false;
491
536
492 qreal percentage = s->value() / m_total;
537 qreal percentage = s->value() / m_total;
493 if (s->m_percentage != percentage) {
538 if (s->m_percentage != percentage) {
494 s->m_percentage = percentage;
539 s->m_percentage = percentage;
495 changed = true;
540 changed = true;
496 }
541 }
497
542
498 qreal sliceSpan = pieSpan * percentage;
543 qreal sliceSpan = pieSpan * percentage;
499 if (s->m_angleSpan != sliceSpan) {
544 if (s->m_angleSpan != sliceSpan) {
500 s->m_angleSpan = sliceSpan;
545 s->m_angleSpan = sliceSpan;
501 changed = true;
546 changed = true;
502 }
547 }
503
548
504 if (s->m_startAngle != sliceAngle) {
549 if (s->m_startAngle != sliceAngle) {
505 s->m_startAngle = sliceAngle;
550 s->m_startAngle = sliceAngle;
506 changed = true;
551 changed = true;
507 }
552 }
508 sliceAngle += sliceSpan;
553 sliceAngle += sliceSpan;
509
554
510 if (changed)
555 if (changed)
511 emit s->changed();
556 emit s->changed();
512 }
557 }
513 }
558 }
514
559
515 #include "moc_qpieseries.cpp"
560 #include "moc_qpieseries.cpp"
516
561
517 QTCOMMERCIALCHART_END_NAMESPACE
562 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,157 +1,134
1 #ifndef PIESERIES_H
1 #ifndef PIESERIES_H
2 #define PIESERIES_H
2 #define PIESERIES_H
3
3
4 #include "qseries.h"
4 #include "qseries.h"
5 #include <QObject>
5 #include <QObject>
6 #include <QRectF>
6 #include <QRectF>
7 #include <QColor>
7 #include <QColor>
8 #include <QPen>
8 #include <QPen>
9 #include <QBrush>
9 #include <QBrush>
10 #include <QSignalMapper>
10 #include <QSignalMapper>
11
11
12 class QGraphicsObject;
12 class QGraphicsObject;
13 QTCOMMERCIALCHART_BEGIN_NAMESPACE
13 QTCOMMERCIALCHART_BEGIN_NAMESPACE
14 class PiePresenter;
14 class PiePresenter;
15 class PieSlice;
15 class PieSlice;
16 class QPieSlice;
16 class QPieSlice;
17
17
18 class QTCOMMERCIALCHART_EXPORT QPieSeries : public QSeries
18 class QTCOMMERCIALCHART_EXPORT QPieSeries : public QSeries
19 {
19 {
20 Q_OBJECT
20 Q_OBJECT
21
21
22 public:
22 public:
23
23
24 enum PiePositionFlag {
25 PiePositionLeft = 0x1,
26 PiePositionRight = 0x2,
27 PiePositionHCenter = 0x4,
28 PiePositionTop = 0x10,
29 PiePositionBottom = 0x20,
30 PiePositionVCenter = 0x40,
31 PiePositionCenter = PiePositionHCenter | PiePositionVCenter
32 };
33
34 Q_DECLARE_FLAGS(PiePosition, PiePositionFlag)
35
36 enum PieSizePolicyFlag {
37 PieSizePolicyMaximized = 0,
38 PieSizePolicyReserveSpaceForLabels = 0x1,
39 PieSizePolicyReserveSpaceForExploding = 0x2,
40 PieSizePolicyReserveSpaceForAll = PieSizePolicyReserveSpaceForLabels | PieSizePolicyReserveSpaceForExploding
41 };
42
43 Q_DECLARE_FLAGS(PieSizePolicy, PieSizePolicyFlag)
44
45 class ChangeSet
24 class ChangeSet
46 {
25 {
47 public:
26 public:
48
27
49 // TODO: these should not really be exposed to the public API
28 // TODO: these should not really be exposed to the public API
50 void appendAdded(QPieSlice* slice);
29 void appendAdded(QPieSlice* slice);
51 void appendAdded(QList<QPieSlice*> slices);
30 void appendAdded(QList<QPieSlice*> slices);
52 void appendChanged(QPieSlice* slice);
31 void appendChanged(QPieSlice* slice);
53 void appendRemoved(QPieSlice* slice);
32 void appendRemoved(QPieSlice* slice);
54
33
55 QList<QPieSlice*> added() const;
34 QList<QPieSlice*> added() const;
56 QList<QPieSlice*> changed() const;
35 QList<QPieSlice*> changed() const;
57 QList<QPieSlice*> removed() const;
36 QList<QPieSlice*> removed() const;
58
37
59 bool isEmpty() const;
38 bool isEmpty() const;
60
39
61 private:
40 private:
62 QList<QPieSlice*> m_added;
41 QList<QPieSlice*> m_added;
63 QList<QPieSlice*> m_changed;
42 QList<QPieSlice*> m_changed;
64 QList<QPieSlice*> m_removed;
43 QList<QPieSlice*> m_removed;
65 };
44 };
66
45
67 public:
46 public:
68 QPieSeries(QObject *parent = 0);
47 QPieSeries(QObject *parent = 0);
69 virtual ~QPieSeries();
48 virtual ~QPieSeries();
70
49
71 public: // from QChartSeries
50 public: // from QChartSeries
72 QSeriesType type() const;
51 QSeriesType type() const;
73
52
74 public:
53 public:
75
54
76 // slice setters
55 // slice setters
77 void add(QPieSlice* slice);
56 void add(QPieSlice* slice);
78 void add(QList<QPieSlice*> slices);
57 void add(QList<QPieSlice*> slices);
79 void replace(QList<QPieSlice*> slices);
58 void replace(QList<QPieSlice*> slices);
80 void remove(QPieSlice* slice);
59 void remove(QPieSlice* slice);
81 void clear();
60 void clear();
82
61
83 // sluce getters
62 // sluce getters
84 QList<QPieSlice*> slices() const;
63 QList<QPieSlice*> slices() const;
85
64
86 // calculated data
65 // calculated data
87 int count() const;
66 int count() const;
88 qreal total() const;
67 qreal total() const;
89
68
90 // pie customization
69 // pie customization
91 void setPosition(PiePosition position);
70 void setPositionFactors(qreal horizontalFactor, qreal verticalFactor);
92 PiePosition position() const;
71 qreal horizontalPositionFactor() const;
93 void setSizePolicy(PieSizePolicy policy);
72 qreal verticalPositionFactor() const;
94 PieSizePolicy sizePolicy() const;
95 void setSizeFactor(qreal sizeFactor);
73 void setSizeFactor(qreal sizeFactor);
96 qreal sizeFactor() const;
74 qreal sizeFactor() const;
97 void setStartAngle(qreal startAngle);
75 void setStartAngle(qreal startAngle);
98 qreal startAngle() const;
76 qreal startAngle() const;
99 void setEndAngle(qreal endAngle);
77 void setEndAngle(qreal endAngle);
100 qreal endAngle() const;
78 qreal endAngle() const;
101
79
102 // convenience function
80 // convenience function
103 QPieSeries& operator << (QPieSlice* slice);
81 QPieSeries& operator << (QPieSlice* slice);
104 QPieSlice* add(qreal value, QString name);
82 QPieSlice* add(qreal value, QString name);
105 void setLabelsVisible(bool visible = true);
83 void setLabelsVisible(bool visible = true);
106
84
107 // TODO: find slices?
85 // TODO: find slices?
108 // QList<QPieSlice*> findByValue(qreal value);
86 // QList<QPieSlice*> findByValue(qreal value);
109 // ...
87 // ...
110
88
111 // TODO: sorting slices?
89 // TODO: sorting slices?
112 // void sort(QPieSeries::SortByValue|label|??)
90 // void sort(QPieSeries::SortByValue|label|??)
113
91
114 // TODO: general graphics customization
92 // TODO: general graphics customization
115 // setDrawStyle(2d|3d)
93 // setDrawStyle(2d|3d)
116 // setDropShadows
94 // setDropShadows
117
95
118 Q_SIGNALS:
96 Q_SIGNALS:
119
97
120 void changed(const QPieSeries::ChangeSet& changeSet);
98 void changed(const QPieSeries::ChangeSet& changeSet);
121
99
122 void clicked(QPieSlice* slice);
100 void clicked(QPieSlice* slice);
123 void hoverEnter(QPieSlice* slice);
101 void hoverEnter(QPieSlice* slice);
124 void hoverLeave(QPieSlice* slice);
102 void hoverLeave(QPieSlice* slice);
125
103
126 void sizeFactorChanged();
104 void sizeFactorChanged();
127 void positionChanged();
105 void positionChanged();
128 void sizePolicyChanged();
129
106
130 private Q_SLOTS: // TODO: should be private and not visible in the interface at all
107 private Q_SLOTS: // TODO: should be private and not visible in the interface at all
131 void sliceChanged();
108 void sliceChanged();
132 void sliceClicked();
109 void sliceClicked();
133 void sliceHoverEnter();
110 void sliceHoverEnter();
134 void sliceHoverLeave();
111 void sliceHoverLeave();
135
112
136 private:
113 private:
137 void updateDerivativeData();
114 void updateDerivativeData();
138
115
139 private:
116 private:
140 Q_DISABLE_COPY(QPieSeries)
117 Q_DISABLE_COPY(QPieSeries)
141
118
142 // TODO: use PIML
119 // TODO: use PIML
143 friend class PiePresenter;
120 friend class PiePresenter;
144 friend class PieSlice;
121 friend class PieSlice;
145
122
146 QList<QPieSlice*> m_slices;
123 QList<QPieSlice*> m_slices;
147 qreal m_sizeFactor;
124 qreal m_hPositionFactor;
148 PiePosition m_position;
125 qreal m_vPositionFactor;
149 PieSizePolicy m_sizePolicy;
126 qreal m_pieSizeFactor;
150 qreal m_total;
151 qreal m_pieStartAngle;
127 qreal m_pieStartAngle;
152 qreal m_pieEndAngle;
128 qreal m_pieEndAngle;
129 qreal m_total;
153 };
130 };
154
131
155 QTCOMMERCIALCHART_END_NAMESPACE
132 QTCOMMERCIALCHART_END_NAMESPACE
156
133
157 #endif // PIESERIES_H
134 #endif // PIESERIES_H
@@ -1,376 +1,401
1 #include "qpieslice.h"
1 #include "qpieslice.h"
2
2
3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4
4
5 #define DEFAULT_PEN_COLOR Qt::black
5 #define DEFAULT_PEN_COLOR Qt::black
6 #define DEFAULT_BRUSH_COLOR Qt::white
6 #define DEFAULT_BRUSH_COLOR Qt::white
7 #define DEFAULT_LABEL_ARM_LENGTH 40
7 #define DEFAULT_LABEL_ARM_LENGTH_FACTOR 0.15
8 #define DEFAULT_EXPOLODE_DISTANCE 20
8 #define DEFAULT_EXPOLODE_DISTANCE_FACTOR 0.15
9
9
10 /*!
10 /*!
11 \class QPieSlice
11 \class QPieSlice
12 \brief Defines a slice in pie series.
12 \brief Defines a slice in pie series.
13
13
14 Holds all the data of a single slice in a QPieSeries and provides the means
14 Holds all the data of a single slice in a QPieSeries and provides the means
15 to modify slice data and customize the visual appearance of the slice.
15 to modify slice data and customize the visual appearance of the slice.
16
16
17 It also provides the means to customize user interaction with the slice by
17 It also provides the means to customize user interaction with the slice by
18 providing signals for clicking and hover events.
18 providing signals for clicking and hover events.
19 */
19 */
20
20
21 /*!
21 /*!
22 \property QPieSlice::label
22 \property QPieSlice::label
23
23
24 Label of the slice.
24 Label of the slice.
25 */
25 */
26
26
27 /*!
27 /*!
28 \property QPieSlice::value
28 \property QPieSlice::value
29
29
30 Value of the slice.
30 Value of the slice.
31 */
31 */
32
32
33 /*!
33 /*!
34 Constructs an empty slice with a \a parent.
34 Constructs an empty slice with a \a parent.
35
35
36 Note that QPieSeries takes ownership of the slice when it is set/added.
36 Note that QPieSeries takes ownership of the slice when it is set/added.
37
37
38 \sa QPieSeries::replace(), QPieSeries::add()
38 \sa QPieSeries::replace(), QPieSeries::add()
39 */
39 */
40 QPieSlice::QPieSlice(QObject *parent)
40 QPieSlice::QPieSlice(QObject *parent)
41 :QObject(parent),
41 :QObject(parent),
42 m_value(0),
42 m_value(0),
43 m_isLabelVisible(false),
43 m_isLabelVisible(false),
44 m_isExploded(false),
44 m_isExploded(false),
45 m_explodeDistance(DEFAULT_EXPOLODE_DISTANCE),
45 m_explodeDistanceFactor(DEFAULT_EXPOLODE_DISTANCE_FACTOR),
46 m_percentage(0),
46 m_percentage(0),
47 m_startAngle(0),
47 m_startAngle(0),
48 m_angleSpan(0),
48 m_angleSpan(0),
49 m_pen(DEFAULT_PEN_COLOR),
49 m_pen(DEFAULT_PEN_COLOR),
50 m_brush(DEFAULT_BRUSH_COLOR),
50 m_brush(DEFAULT_BRUSH_COLOR),
51 m_labelPen(DEFAULT_PEN_COLOR),
51 m_labelPen(DEFAULT_PEN_COLOR),
52 m_labelArmLength(DEFAULT_LABEL_ARM_LENGTH)
52 m_labelArmLengthFactor(DEFAULT_LABEL_ARM_LENGTH_FACTOR)
53 {
53 {
54
54
55 }
55 }
56
56
57 /*!
57 /*!
58 Constructs an empty slice with given \a value, \a label and a \a parent.
58 Constructs an empty slice with given \a value, \a label and a \a parent.
59 Note that QPieSeries takes ownership of the slice when it is set/added.
59 Note that QPieSeries takes ownership of the slice when it is set/added.
60 \sa QPieSeries::replace(), QPieSeries::add()
60 \sa QPieSeries::replace(), QPieSeries::add()
61 */
61 */
62 QPieSlice::QPieSlice(qreal value, QString label, QObject *parent)
62 QPieSlice::QPieSlice(qreal value, QString label, QObject *parent)
63 :QObject(parent),
63 :QObject(parent),
64 m_value(value),
64 m_value(value),
65 m_label(label),
65 m_label(label),
66 m_isLabelVisible(false),
66 m_isLabelVisible(false),
67 m_isExploded(false),
67 m_isExploded(false),
68 m_explodeDistance(DEFAULT_EXPOLODE_DISTANCE),
68 m_explodeDistanceFactor(DEFAULT_EXPOLODE_DISTANCE_FACTOR),
69 m_percentage(0),
69 m_percentage(0),
70 m_startAngle(0),
70 m_startAngle(0),
71 m_angleSpan(0),
71 m_angleSpan(0),
72 m_pen(DEFAULT_PEN_COLOR),
72 m_pen(DEFAULT_PEN_COLOR),
73 m_brush(DEFAULT_BRUSH_COLOR),
73 m_brush(DEFAULT_BRUSH_COLOR),
74 m_labelPen(DEFAULT_PEN_COLOR),
74 m_labelPen(DEFAULT_PEN_COLOR),
75 m_labelArmLength(DEFAULT_LABEL_ARM_LENGTH)
75 m_labelArmLengthFactor(DEFAULT_LABEL_ARM_LENGTH_FACTOR)
76 {
76 {
77
77
78 }
78 }
79
79
80 /*!
80 /*!
81 Destroys the slice.
81 Destroys the slice.
82 User should not delete the slice if it has been added to the series.
82 User should not delete the slice if it has been added to the series.
83 */
83 */
84 QPieSlice::~QPieSlice()
84 QPieSlice::~QPieSlice()
85 {
85 {
86
86
87 }
87 }
88
88
89 /*!
89 /*!
90 Gets the value of the slice.
90 Gets the value of the slice.
91 Note that all values in the series
91 Note that all values in the series
92 \sa setValue()
92 \sa setValue()
93 */
93 */
94 qreal QPieSlice::value() const
94 qreal QPieSlice::value() const
95 {
95 {
96 return m_value;
96 return m_value;
97 }
97 }
98
98
99 /*!
99 /*!
100 Gets the label of the slice.
100 Gets the label of the slice.
101 \sa setLabel()
101 \sa setLabel()
102 */
102 */
103 QString QPieSlice::label() const
103 QString QPieSlice::label() const
104 {
104 {
105 return m_label;
105 return m_label;
106 }
106 }
107
107
108 /*!
108 /*!
109 Returns true if label is set as visible.
109 Returns true if label is set as visible.
110 \sa setLabelVisible()
110 \sa setLabelVisible()
111 */
111 */
112 bool QPieSlice::isLabelVisible() const
112 bool QPieSlice::isLabelVisible() const
113 {
113 {
114 return m_isLabelVisible;
114 return m_isLabelVisible;
115 }
115 }
116
116
117 /*!
117 /*!
118 Returns true if slice is exloded from the pie.
118 Returns true if slice is exloded from the pie.
119 \sa setExploded()
119 \sa setExploded(), setExplodeDistanceFactor()
120 */
120 */
121 bool QPieSlice::isExploded() const
121 bool QPieSlice::isExploded() const
122 {
122 {
123 return m_isExploded;
123 return m_isExploded;
124 }
124 }
125
125
126 /*!
126 /*!
127 Returns the explosion distance of the slice.
127 Returns the explode distance factor.
128 Default value is 20.
128
129 \sa setExplodeDistance()
129 The factor is relative to pie radius. For example:
130 1.0 means the distance is the same as the radius.
131 0.5 means the distance is half of the radius.
132
133 Default value is 0.15.
134
135 \sa setExplodeDistanceFactor()
130 */
136 */
131 qreal QPieSlice::explodeDistance() const
137 qreal QPieSlice::explodeDistanceFactor() const
132 {
138 {
133 return m_explodeDistance;
139 return m_explodeDistanceFactor;
134 }
140 }
135
141
136 /*!
142 /*!
137 Returns the percentage of this slice compared to all slices in the same series.
143 Returns the percentage of this slice compared to all slices in the same series.
138 The returned value ranges from 0 to 1.0.
144 The returned value ranges from 0 to 1.0.
139
145
140 Updated internally after the slice is added to the series.
146 Updated internally after the slice is added to the series.
141 */
147 */
142 qreal QPieSlice::percentage() const
148 qreal QPieSlice::percentage() const
143 {
149 {
144 return m_percentage;
150 return m_percentage;
145 }
151 }
146
152
147 /*!
153 /*!
148 Returns the starting angle of this slice in the series it belongs to.
154 Returns the starting angle of this slice in the series it belongs to.
149
155
150 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
156 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
151
157
152 Updated internally after the slice is added to the series.
158 Updated internally after the slice is added to the series.
153 */
159 */
154 qreal QPieSlice::startAngle() const
160 qreal QPieSlice::startAngle() const
155 {
161 {
156 return m_startAngle;
162 return m_startAngle;
157 }
163 }
158
164
159 /*!
165 /*!
160 Returns the end angle of this slice in the series it belongs to.
166 Returns the end angle of this slice in the series it belongs to.
161
167
162 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
168 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
163
169
164 Updated internally after the slice is added to the series.
170 Updated internally after the slice is added to the series.
165 */
171 */
166 qreal QPieSlice::endAngle() const
172 qreal QPieSlice::endAngle() const
167 {
173 {
168 return m_startAngle + m_angleSpan;
174 return m_startAngle + m_angleSpan;
169 }
175 }
170
176
171 /*!
177 /*!
172 Returns the pen used to draw this slice.
178 Returns the pen used to draw this slice.
173 \sa setPen()
179 \sa setPen()
174 */
180 */
175 QPen QPieSlice::pen() const
181 QPen QPieSlice::pen() const
176 {
182 {
177 return m_pen;
183 return m_pen;
178 }
184 }
179
185
180 /*!
186 /*!
181 Returns the brush used to draw this slice.
187 Returns the brush used to draw this slice.
182 \sa setBrush()
188 \sa setBrush()
183 */
189 */
184 QBrush QPieSlice::brush() const
190 QBrush QPieSlice::brush() const
185 {
191 {
186 return m_brush;
192 return m_brush;
187 }
193 }
188
194
189 /*!
195 /*!
190 Returns the pen used to draw label in this slice.
196 Returns the pen used to draw label in this slice.
191 \sa setLabelPen()
197 \sa setLabelPen()
192 */
198 */
193 QPen QPieSlice::labelPen() const
199 QPen QPieSlice::labelPen() const
194 {
200 {
195 return m_labelPen;
201 return m_labelPen;
196 }
202 }
197
203
198 /*!
204 /*!
199 Returns the font used to draw label in this slice.
205 Returns the font used to draw label in this slice.
200 \sa setLabelFont()
206 \sa setLabelFont()
201 */
207 */
202 QFont QPieSlice::labelFont() const
208 QFont QPieSlice::labelFont() const
203 {
209 {
204 return m_labelFont;
210 return m_labelFont;
205 }
211 }
206
212
207 /*!
213 /*!
208 Returns the label arm lenght used in this slice.
214 Gets the label arm lenght factor.
209 Default value is 40 pixels.
215
210 \sa setLabelArmLength()
216 The factor is relative to pie radius. For example:
217 1.0 means the length is the same as the radius.
218 0.5 means the length is half of the radius.
219
220 Default value is 0.15
221
222 \sa setLabelArmLengthFactor()
211 */
223 */
212 qreal QPieSlice::labelArmLength() const
224 qreal QPieSlice::labelArmLengthFactor() const
213 {
225 {
214 return m_labelArmLength;
226 return m_labelArmLengthFactor;
215 }
227 }
216
228
217 /*!
229 /*!
218 \fn void QPieSlice::clicked()
230 \fn void QPieSlice::clicked()
219
231
220 This signal is emitted when user has clicked the slice.
232 This signal is emitted when user has clicked the slice.
221
233
222 \sa QPieSeries::clicked()
234 \sa QPieSeries::clicked()
223 */
235 */
224
236
225 /*!
237 /*!
226 \fn void QPieSlice::hoverEnter()
238 \fn void QPieSlice::hoverEnter()
227
239
228 This signal is emitted when user has hovered over the slice.
240 This signal is emitted when user has hovered over the slice.
229
241
230 \sa QPieSeries::hoverEnter()
242 \sa QPieSeries::hoverEnter()
231 */
243 */
232
244
233 /*!
245 /*!
234 \fn void QPieSlice::hoverLeave()
246 \fn void QPieSlice::hoverLeave()
235
247
236 This signal is emitted when user has hovered away from the slice.
248 This signal is emitted when user has hovered away from the slice.
237
249
238 \sa QPieSeries::hoverLeave()
250 \sa QPieSeries::hoverLeave()
239 */
251 */
240
252
241 /*!
253 /*!
242 \fn void QPieSlice::changed()
254 \fn void QPieSlice::changed()
243
255
244 This signal emitted when something has changed in the slice.
256 This signal emitted when something has changed in the slice.
245
257
246 \sa QPieSeries::changed()
258 \sa QPieSeries::changed()
247 */
259 */
248
260
249 /*!
261 /*!
250 Sets the value of this slice.
262 Sets the \a value of this slice.
251 \sa value()
263 \sa value()
252 */
264 */
253 void QPieSlice::setValue(qreal value)
265 void QPieSlice::setValue(qreal value)
254 {
266 {
255 if (m_value != value) {
267 if (m_value != value) {
256 m_value = value;
268 m_value = value;
257 emit changed();
269 emit changed();
258 }
270 }
259 }
271 }
260
272
261 /*!
273 /*!
262 Sets the \a label of the slice.
274 Sets the \a label of the slice.
263 \sa label()
275 \sa label()
264 */
276 */
265 void QPieSlice::setLabel(QString label)
277 void QPieSlice::setLabel(QString label)
266 {
278 {
267 if (m_label != label) {
279 if (m_label != label) {
268 m_label = label;
280 m_label = label;
269 emit changed();
281 emit changed();
270 }
282 }
271 }
283 }
272
284
273 /*!
285 /*!
274 Sets the label \a visible in this slice.
286 Sets the label \a visible in this slice.
275 \sa isLabelVisible(), QPieSeries::setLabelsVisible()
287 \sa isLabelVisible(), QPieSeries::setLabelsVisible()
276 */
288 */
277 void QPieSlice::setLabelVisible(bool visible)
289 void QPieSlice::setLabelVisible(bool visible)
278 {
290 {
279 if (m_isLabelVisible != visible) {
291 if (m_isLabelVisible != visible) {
280 m_isLabelVisible = visible;
292 m_isLabelVisible = visible;
281 emit changed();
293 emit changed();
282 }
294 }
283 }
295 }
284
296
285 /*!
297 /*!
286 Sets this slice \a exploded.
298 Sets this slice \a exploded.
287 \sa isExploded(), setExplodeDistance()
299 \sa isExploded(), explodeDistanceFactor()
288 */
300 */
289 void QPieSlice::setExploded(bool exploded)
301 void QPieSlice::setExploded(bool exploded)
290 {
302 {
291 if (m_isExploded != exploded) {
303 if (m_isExploded != exploded) {
292 m_isExploded = exploded;
304 m_isExploded = exploded;
293 emit changed();
305 emit changed();
294 }
306 }
295 }
307 }
296
308
297 /*!
309 /*!
298 Sets the explosion \a distance of this slice.
310 Sets the explode distance \a factor.
299 It is the distance the slice is moved away from the pie center.
311
300 \sa explodeDistance(), isExploded()
312 The factor is relative to pie radius. For example:
313 1.0 means the distance is the same as the radius.
314 0.5 means the distance is half of the radius.
315
316 Default value is 0.15
317
318 \sa explodeDistanceFactor()
301 */
319 */
302 void QPieSlice::setExplodeDistance(qreal distance)
320 void QPieSlice::setExplodeDistanceFactor(qreal factor)
303 {
321 {
304 if (m_explodeDistance != distance) {
322 if (m_explodeDistanceFactor != factor) {
305 m_explodeDistance = distance;
323 m_explodeDistanceFactor = factor;
306 emit changed();
324 emit changed();
307 }
325 }
308 }
326 }
309
327
310 /*!
328 /*!
311 Sets the \a pen used to draw this slice.
329 Sets the \a pen used to draw this slice.
312 Note that applying a theme will override this.
330 Note that applying a theme will override this.
313 \sa pen()
331 \sa pen()
314 */
332 */
315 void QPieSlice::setPen(QPen pen)
333 void QPieSlice::setPen(QPen pen)
316 {
334 {
317 if (m_pen != pen) {
335 if (m_pen != pen) {
318 m_pen = pen;
336 m_pen = pen;
319 emit changed();
337 emit changed();
320 }
338 }
321 }
339 }
322
340
323 /*!
341 /*!
324 Sets the \a brush used to draw this slice.
342 Sets the \a brush used to draw this slice.
325 Note that applying a theme will override this.
343 Note that applying a theme will override this.
326 \sa brush()
344 \sa brush()
327 */
345 */
328 void QPieSlice::setBrush(QBrush brush)
346 void QPieSlice::setBrush(QBrush brush)
329 {
347 {
330 if (m_brush != brush) {
348 if (m_brush != brush) {
331 m_brush = brush;
349 m_brush = brush;
332 emit changed();
350 emit changed();
333 }
351 }
334 }
352 }
335
353
336 /*!
354 /*!
337 Sets the \a pen used to draw the label in this slice.
355 Sets the \a pen used to draw the label in this slice.
338 Note that applying a theme will override this.
356 Note that applying a theme will override this.
339 \sa labelPen()
357 \sa labelPen()
340 */
358 */
341 void QPieSlice::setLabelPen(QPen pen)
359 void QPieSlice::setLabelPen(QPen pen)
342 {
360 {
343 if (m_labelPen != pen) {
361 if (m_labelPen != pen) {
344 m_labelPen = pen;
362 m_labelPen = pen;
345 emit changed();
363 emit changed();
346 }
364 }
347 }
365 }
348
366
349 /*!
367 /*!
350 Sets the \a font used to draw the label in this slice.
368 Sets the \a font used to draw the label in this slice.
351 Note that applying a theme will override this.
369 Note that applying a theme will override this.
352 \sa labelFont()
370 \sa labelFont()
353 */
371 */
354 void QPieSlice::setLabelFont(QFont font)
372 void QPieSlice::setLabelFont(QFont font)
355 {
373 {
356 if (m_labelFont != font) {
374 if (m_labelFont != font) {
357 m_labelFont = font;
375 m_labelFont = font;
358 emit changed();
376 emit changed();
359 }
377 }
360 }
378 }
361
379
362 /*!
380 /*!
363 Sets the label arm \a length used to draw the label in this slice.
381 Sets the label arm lenght \a factor.
364 \sa labelArmLength()
382
383 The factor is relative to pie radius. For example:
384 1.0 means the length is the same as the radius.
385 0.5 means the length is half of the radius.
386
387 Default value is 0.15
388
389 \sa labelArmLengthFactor()
365 */
390 */
366 void QPieSlice::setLabelArmLength(qreal length)
391 void QPieSlice::setLabelArmLengthFactor(qreal factor)
367 {
392 {
368 if (m_labelArmLength != length) {
393 if (m_labelArmLengthFactor != factor) {
369 m_labelArmLength = length;
394 m_labelArmLengthFactor = factor;
370 emit changed();
395 emit changed();
371 }
396 }
372 }
397 }
373
398
374 #include "moc_qpieslice.cpp"
399 #include "moc_qpieslice.cpp"
375
400
376 QTCOMMERCIALCHART_END_NAMESPACE
401 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,91 +1,91
1 #ifndef QPIESLICE_H
1 #ifndef QPIESLICE_H
2 #define QPIESLICE_H
2 #define QPIESLICE_H
3
3
4 #include <qchartglobal.h>
4 #include <qchartglobal.h>
5 #include <QObject>
5 #include <QObject>
6 #include <QPen>
6 #include <QPen>
7 #include <QBrush>
7 #include <QBrush>
8 #include <QFont>
8 #include <QFont>
9
9
10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11
11
12 class QTCOMMERCIALCHART_EXPORT QPieSlice : public QObject
12 class QTCOMMERCIALCHART_EXPORT QPieSlice : public QObject
13 {
13 {
14 Q_OBJECT
14 Q_OBJECT
15 Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY changed)
15 Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY changed)
16 Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY changed)
16 Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY changed)
17
17
18 public:
18 public:
19 QPieSlice(QObject *parent = 0);
19 QPieSlice(QObject *parent = 0);
20 QPieSlice(qreal value, QString label, QObject *parent = 0);
20 QPieSlice(qreal value, QString label, QObject *parent = 0);
21 virtual ~QPieSlice();
21 virtual ~QPieSlice();
22
22
23 // data
23 // data
24 void setValue(qreal value);
24 void setValue(qreal value);
25 qreal value() const;
25 qreal value() const;
26 void setLabel(QString label);
26 void setLabel(QString label);
27 QString label() const;
27 QString label() const;
28 void setLabelVisible(bool visible);
28 void setLabelVisible(bool visible);
29 bool isLabelVisible() const;
29 bool isLabelVisible() const;
30 void setExploded(bool exploded);
30 void setExploded(bool exploded);
31 bool isExploded() const;
31 bool isExploded() const;
32 void setExplodeDistance(qreal distance);
32 void setExplodeDistanceFactor(qreal factor);
33 qreal explodeDistance() const;
33 qreal explodeDistanceFactor() const;
34
34
35 // generated data
35 // generated data
36 qreal percentage() const;
36 qreal percentage() const;
37 qreal startAngle() const;
37 qreal startAngle() const;
38 qreal endAngle() const;
38 qreal endAngle() const;
39
39
40 // customization
40 // customization
41 void setPen(QPen pen);
41 void setPen(QPen pen);
42 QPen pen() const;
42 QPen pen() const;
43 void setBrush(QBrush brush);
43 void setBrush(QBrush brush);
44 QBrush brush() const;
44 QBrush brush() const;
45 void setLabelPen(QPen pen);
45 void setLabelPen(QPen pen);
46 QPen labelPen() const;
46 QPen labelPen() const;
47 void setLabelFont(QFont font);
47 void setLabelFont(QFont font);
48 QFont labelFont() const;
48 QFont labelFont() const;
49 void setLabelArmLength(qreal len);
49 void setLabelArmLengthFactor(qreal factor);
50 qreal labelArmLength() const;
50 qreal labelArmLengthFactor() const;
51
51
52 // TODO: label position in general
52 // TODO: label position in general
53 // setLabelFlags(inside|outside|labelArmOn|labelArmOff|???)
53 // setLabelFlags(inside|outside|labelArmOn|labelArmOff|???)
54 // setLabelOrientation(horizontal|vertical|same as slice center angle|???)
54 // setLabelOrientation(horizontal|vertical|same as slice center angle|???)
55
55
56 Q_SIGNALS:
56 Q_SIGNALS:
57 void clicked();
57 void clicked();
58 void hoverEnter();
58 void hoverEnter();
59 void hoverLeave();
59 void hoverLeave();
60 void changed();
60 void changed();
61
61
62 private:
62 private:
63
63
64 // TODO: use private class
64 // TODO: use private class
65 friend class QPieSeries;
65 friend class QPieSeries;
66 friend class PiePresenter;
66 friend class PiePresenter;
67 friend class PieSlice;
67 friend class PieSlice;
68
68
69 // data
69 // data
70 qreal m_value;
70 qreal m_value;
71 QString m_label;
71 QString m_label;
72 bool m_isLabelVisible;
72 bool m_isLabelVisible;
73 bool m_isExploded;
73 bool m_isExploded;
74 qreal m_explodeDistance;
74 qreal m_explodeDistanceFactor;
75
75
76 // generated data
76 // generated data
77 qreal m_percentage;
77 qreal m_percentage;
78 qreal m_startAngle;
78 qreal m_startAngle;
79 qreal m_angleSpan;
79 qreal m_angleSpan;
80
80
81 // customization
81 // customization
82 QPen m_pen;
82 QPen m_pen;
83 QBrush m_brush;
83 QBrush m_brush;
84 QPen m_labelPen;
84 QPen m_labelPen;
85 QFont m_labelFont;
85 QFont m_labelFont;
86 qreal m_labelArmLength;
86 qreal m_labelArmLengthFactor;
87 };
87 };
88
88
89 QTCOMMERCIALCHART_END_NAMESPACE
89 QTCOMMERCIALCHART_END_NAMESPACE
90
90
91 #endif // QPIESLICE_H
91 #endif // QPIESLICE_H
General Comments 0
You need to be logged in to leave comments. Login now