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