##// END OF EJS Templates
Added QDonutGroup class
Marek Rosa -
r1671:86eb2ea7496a
parent child
Show More
@@ -0,0 +1,39
1 #include "qdonutgroup.h"
2 #include "qdonutgroup_p.h"
3
4 QTCOMMERCIALCHART_BEGIN_NAMESPACE
5
6 QDonutGroup::QDonutGroup(QObject *parent) :
7 QObject(parent),
8 d_ptr(new QDonutGroupPrivate(this))
9 {
10 }
11
12 void QDonutGroup::append(QPieSeries *donut)
13 {
14 if (donut == 0)
15 return;
16
17 donut->setDonut();
18 Q_D(QDonutGroup);
19 d->m_donuts.append(donut);
20 qreal donutFraction = 1.0 / (d->m_donuts.count() + 1);
21 for(int i = 0; i < d->m_donuts.count(); i++) {
22 d->m_donuts[i]->setPieSize( (i + 2) * donutFraction);
23 d->m_donuts[i]->setDonutInnerSize( (i + 1) * donutFraction);
24 }
25 }
26
27 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28
29 QDonutGroupPrivate::QDonutGroupPrivate(QDonutGroup *q):
30 QObject(q),
31 q_ptr(q)
32 {
33 //
34 }
35
36 #include "moc_qdonutgroup.cpp"
37 #include "moc_qdonutgroup_p.cpp"
38
39 QTCOMMERCIALCHART_END_NAMESPACE
@@ -0,0 +1,27
1 #ifndef QDONUTGROUP_H
2 #define QDONUTGROUP_H
3
4 #include <QObject>
5 #include <QPieSeries>
6
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8
9 //class QPieSeries;
10 class QDonutGroupPrivate;
11
12 class QTCOMMERCIALCHART_EXPORT QDonutGroup : public QObject
13 {
14 Q_OBJECT
15 public:
16 explicit QDonutGroup(QObject *parent = 0);
17
18 void append(QPieSeries *donut);
19
20 protected:
21 QDonutGroupPrivate * const d_ptr;
22 Q_DECLARE_PRIVATE(QDonutGroup)
23 };
24
25 QTCOMMERCIALCHART_END_NAMESPACE
26
27 #endif // QDONUTGROUP_H
@@ -0,0 +1,29
1 #ifndef QDONUTGROUP_P_H
2 #define QDONUTGROUP_P_H
3
4 #include <QObject>
5 #include <qdonutgroup.h>
6
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8
9 class QPieSeries;
10
11 class QDonutGroupPrivate : public QObject
12 {
13 Q_OBJECT
14 public:
15 explicit QDonutGroupPrivate(QDonutGroup *q);
16
17 void append(QPieSeries *donut);
18
19 private:
20 QList<QPieSeries *> m_donuts;
21
22 private:
23 QDonutGroup *q_ptr;
24 Q_DECLARE_PUBLIC(QDonutGroup)
25 };
26
27 QTCOMMERCIALCHART_END_NAMESPACE
28
29 #endif // QDONUTGROUP_P_H
@@ -1,568 +1,569
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qbarmodelmapper.h"
21 #include "qbarmodelmapper.h"
22 #include "qbarmodelmapper_p.h"
22 #include "qbarmodelmapper_p.h"
23 #include "qabstractbarseries.h"
23 #include "qabstractbarseries.h"
24 #include "qbarset.h"
24 #include "qbarset.h"
25 #include "qchart.h"
25 #include "qchart.h"
26 #include <QAbstractItemModel>
26 #include <QAbstractItemModel>
27
27
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29
29
30 QBarModelMapper::QBarModelMapper(QObject *parent) :
30 QBarModelMapper::QBarModelMapper(QObject *parent) :
31 QObject(parent),
31 QObject(parent),
32 d_ptr(new QBarModelMapperPrivate(this))
32 d_ptr(new QBarModelMapperPrivate(this))
33 {
33 {
34 }
34 }
35
35
36 QAbstractItemModel* QBarModelMapper::model() const
36 QAbstractItemModel* QBarModelMapper::model() const
37 {
37 {
38 Q_D(const QBarModelMapper);
38 Q_D(const QBarModelMapper);
39 return d->m_model;
39 return d->m_model;
40 }
40 }
41
41
42 void QBarModelMapper::setModel(QAbstractItemModel *model)
42 void QBarModelMapper::setModel(QAbstractItemModel *model)
43 {
43 {
44 if (model == 0)
44 if (model == 0)
45 return;
45 return;
46
46
47 Q_D(QBarModelMapper);
47 Q_D(QBarModelMapper);
48 if (d->m_model) {
48 if (d->m_model) {
49 disconnect(d->m_model, 0, d, 0);
49 disconnect(d->m_model, 0, d, 0);
50 }
50 }
51
51
52 d->m_model = model;
52 d->m_model = model;
53 d->initializeBarFromModel();
53 d->initializeBarFromModel();
54 // connect signals from the model
54 // connect signals from the model
55 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
55 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
56 connect(d->m_model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), d, SLOT(modelHeaderDataUpdated(Qt::Orientation,int,int)));
56 connect(d->m_model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), d, SLOT(modelHeaderDataUpdated(Qt::Orientation,int,int)));
57 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
57 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
58 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
58 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
59 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
59 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
60 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
60 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
61 connect(d->m_model, SIGNAL(destroyed()), d, SLOT(handleModelDestroyed()));
61 connect(d->m_model, SIGNAL(destroyed()), d, SLOT(handleModelDestroyed()));
62 }
62 }
63
63
64 QAbstractBarSeries* QBarModelMapper::series() const
64 QAbstractBarSeries* QBarModelMapper::series() const
65 {
65 {
66 Q_D(const QBarModelMapper);
66 Q_D(const QBarModelMapper);
67 return d->m_series;
67 return d->m_series;
68 }
68 }
69
69
70 void QBarModelMapper::setSeries(QAbstractBarSeries *series)
70 void QBarModelMapper::setSeries(QAbstractBarSeries *series)
71 {
71 {
72 Q_D(QBarModelMapper);
72 Q_D(QBarModelMapper);
73 if (d->m_series) {
73 if (d->m_series) {
74 disconnect(d->m_series, 0, d, 0);
74 disconnect(d->m_series, 0, d, 0);
75 }
75 }
76
76
77 if (series == 0)
77 if (series == 0)
78 return;
78 return;
79
79
80 d->m_series = series;
80 d->m_series = series;
81 d->initializeBarFromModel();
81 d->initializeBarFromModel();
82 // connect the signals from the series
82 // connect the signals from the series
83 connect(d->m_series, SIGNAL(barsetsAdded(QList<QBarSet*>)), d, SLOT(barSetsAdded(QList<QBarSet*>)));
83 connect(d->m_series, SIGNAL(barsetsAdded(QList<QBarSet*>)), d, SLOT(barSetsAdded(QList<QBarSet*>)));
84 connect(d->m_series, SIGNAL(barsetsRemoved(QList<QBarSet*>)), d, SLOT(barSetsRemoved(QList<QBarSet*>)));
84 connect(d->m_series, SIGNAL(barsetsRemoved(QList<QBarSet*>)), d, SLOT(barSetsRemoved(QList<QBarSet*>)));
85 connect(d->m_series, SIGNAL(destroyed()), d, SLOT(handleSeriesDestroyed()));
85 connect(d->m_series, SIGNAL(destroyed()), d, SLOT(handleSeriesDestroyed()));
86 }
86 }
87
87
88 /*!
88 /*!
89 Returns which row/column of the model contains the first values of the QBarSets in the series.
89 Returns which row/column of the model contains the first values of the QBarSets in the series.
90 The default value is 0.
90 The default value is 0.
91 */
91 */
92 int QBarModelMapper::first() const
92 int QBarModelMapper::first() const
93 {
93 {
94 Q_D(const QBarModelMapper);
94 Q_D(const QBarModelMapper);
95 return d->m_first;
95 return d->m_first;
96 }
96 }
97
97
98 /*!
98 /*!
99 Sets which row of the model contains the \a first values of the QBarSets in the series.
99 Sets which row of the model contains the \a first values of the QBarSets in the series.
100 The default value is 0.
100 The default value is 0.
101 */
101 */
102 void QBarModelMapper::setFirst(int first)
102 void QBarModelMapper::setFirst(int first)
103 {
103 {
104 Q_D(QBarModelMapper);
104 Q_D(QBarModelMapper);
105 d->m_first = qMax(first, 0);
105 d->m_first = qMax(first, 0);
106 d->initializeBarFromModel();
106 d->initializeBarFromModel();
107 }
107 }
108
108
109 /*!
109 /*!
110 Returns the number of rows/columns of the model that are mapped as the data for QAbstractBarSeries
110 Returns the number of rows/columns of the model that are mapped as the data for QAbstractBarSeries
111 Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
111 Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
112 */
112 */
113 int QBarModelMapper::count() const
113 int QBarModelMapper::count() const
114 {
114 {
115 Q_D(const QBarModelMapper);
115 Q_D(const QBarModelMapper);
116 return d->m_count;
116 return d->m_count;
117 }
117 }
118
118
119 /*!
119 /*!
120 Sets the \a count of rows/columns of the model that are mapped as the data for QAbstractBarSeries
120 Sets the \a count of rows/columns of the model that are mapped as the data for QAbstractBarSeries
121 Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
121 Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
122 */
122 */
123 void QBarModelMapper::setCount(int count)
123 void QBarModelMapper::setCount(int count)
124 {
124 {
125 Q_D(QBarModelMapper);
125 Q_D(QBarModelMapper);
126 d->m_count = qMax(count, -1);
126 d->m_count = qMax(count, -1);
127 d->initializeBarFromModel();
127 d->initializeBarFromModel();
128 }
128 }
129
129
130 /*!
130 /*!
131 Returns the orientation that is used when QBarModelMapper accesses the model.
131 Returns the orientation that is used when QBarModelMapper accesses the model.
132 This mean whether the consecutive values of the bar set are read from row (Qt::Horizontal)
132 This mean whether the consecutive values of the bar set are read from row (Qt::Horizontal)
133 or from columns (Qt::Vertical)
133 or from columns (Qt::Vertical)
134 */
134 */
135 Qt::Orientation QBarModelMapper::orientation() const
135 Qt::Orientation QBarModelMapper::orientation() const
136 {
136 {
137 Q_D(const QBarModelMapper);
137 Q_D(const QBarModelMapper);
138 return d->m_orientation;
138 return d->m_orientation;
139 }
139 }
140
140
141 /*!
141 /*!
142 Returns the \a orientation that is used when QBarModelMapper accesses the model.
142 Returns the \a orientation that is used when QBarModelMapper accesses the model.
143 This mean whether the consecutive values of the pie are read from row (Qt::Horizontal)
143 This mean whether the consecutive values of the pie are read from row (Qt::Horizontal)
144 or from columns (Qt::Vertical)
144 or from columns (Qt::Vertical)
145 */
145 */
146 void QBarModelMapper::setOrientation(Qt::Orientation orientation)
146 void QBarModelMapper::setOrientation(Qt::Orientation orientation)
147 {
147 {
148 Q_D(QBarModelMapper);
148 Q_D(QBarModelMapper);
149 d->m_orientation = orientation;
149 d->m_orientation = orientation;
150 d->initializeBarFromModel();
150 d->initializeBarFromModel();
151 }
151 }
152
152
153 /*!
153 /*!
154 Returns which section of the model is used as the data source for the first bar set
154 Returns which section of the model is used as the data source for the first bar set
155 */
155 */
156 int QBarModelMapper::firstBarSetSection() const
156 int QBarModelMapper::firstBarSetSection() const
157 {
157 {
158 Q_D(const QBarModelMapper);
158 Q_D(const QBarModelMapper);
159 return d->m_firstBarSetSection;
159 return d->m_firstBarSetSection;
160 }
160 }
161
161
162 /*!
162 /*!
163 Sets the model section that is used as the data source for the first bar set
163 Sets the model section that is used as the data source for the first bar set
164 Parameter \a firstBarSetSection specifies the section of the model.
164 Parameter \a firstBarSetSection specifies the section of the model.
165 */
165 */
166 void QBarModelMapper::setFirstBarSetSection(int firstBarSetSection)
166 void QBarModelMapper::setFirstBarSetSection(int firstBarSetSection)
167 {
167 {
168 Q_D(QBarModelMapper);
168 Q_D(QBarModelMapper);
169 d->m_firstBarSetSection = qMax(-1, firstBarSetSection);
169 d->m_firstBarSetSection = qMax(-1, firstBarSetSection);
170 d->initializeBarFromModel();
170 d->initializeBarFromModel();
171 }
171 }
172
172
173 /*!
173 /*!
174 Returns which section of the model is used as the data source for the last bar set
174 Returns which section of the model is used as the data source for the last bar set
175 */
175 */
176 int QBarModelMapper::lastBarSetSection() const
176 int QBarModelMapper::lastBarSetSection() const
177 {
177 {
178 Q_D(const QBarModelMapper);
178 Q_D(const QBarModelMapper);
179 return d->m_lastBarSetSection;
179 return d->m_lastBarSetSection;
180 }
180 }
181
181
182 /*!
182 /*!
183 Sets the model section that is used as the data source for the last bar set
183 Sets the model section that is used as the data source for the last bar set
184 Parameter \a lastBarSetSection specifies the section of the model.
184 Parameter \a lastBarSetSection specifies the section of the model.
185 */
185 */
186 void QBarModelMapper::setLastBarSetSection(int lastBarSetSection)
186 void QBarModelMapper::setLastBarSetSection(int lastBarSetSection)
187 {
187 {
188 Q_D(QBarModelMapper);
188 Q_D(QBarModelMapper);
189 d->m_lastBarSetSection = qMax(-1, lastBarSetSection);
189 d->m_lastBarSetSection = qMax(-1, lastBarSetSection);
190 d->initializeBarFromModel();
190 d->initializeBarFromModel();
191 }
191 }
192
192
193 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
193 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
194
194
195 QBarModelMapperPrivate::QBarModelMapperPrivate(QBarModelMapper *q) :
195 QBarModelMapperPrivate::QBarModelMapperPrivate(QBarModelMapper *q) :
196 QObject(q),
196 m_series(0),
197 m_series(0),
197 m_model(0),
198 m_model(0),
198 m_first(0),
199 m_first(0),
199 m_count(-1),
200 m_count(-1),
200 m_orientation(Qt::Vertical),
201 m_orientation(Qt::Vertical),
201 m_firstBarSetSection(-1),
202 m_firstBarSetSection(-1),
202 m_lastBarSetSection(-1),
203 m_lastBarSetSection(-1),
203 m_seriesSignalsBlock(false),
204 m_seriesSignalsBlock(false),
204 m_modelSignalsBlock(false),
205 m_modelSignalsBlock(false),
205 q_ptr(q)
206 q_ptr(q)
206 {
207 {
207 }
208 }
208
209
209 void QBarModelMapperPrivate::blockModelSignals(bool block)
210 void QBarModelMapperPrivate::blockModelSignals(bool block)
210 {
211 {
211 m_modelSignalsBlock = block;
212 m_modelSignalsBlock = block;
212 }
213 }
213
214
214 void QBarModelMapperPrivate::blockSeriesSignals(bool block)
215 void QBarModelMapperPrivate::blockSeriesSignals(bool block)
215 {
216 {
216 m_seriesSignalsBlock = block;
217 m_seriesSignalsBlock = block;
217 }
218 }
218
219
219 QBarSet* QBarModelMapperPrivate::barSet(QModelIndex index)
220 QBarSet* QBarModelMapperPrivate::barSet(QModelIndex index)
220 {
221 {
221 if (!index.isValid())
222 if (!index.isValid())
222 return 0;
223 return 0;
223
224
224 if (m_orientation == Qt::Vertical && index.column() >= m_firstBarSetSection && index.column() <= m_lastBarSetSection) {
225 if (m_orientation == Qt::Vertical && index.column() >= m_firstBarSetSection && index.column() <= m_lastBarSetSection) {
225 if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
226 if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
226 // if (m_model->index(index.row(), m_valuesSection).isValid() && m_model->index(index.row(), m_labelsSection).isValid())
227 // if (m_model->index(index.row(), m_valuesSection).isValid() && m_model->index(index.row(), m_labelsSection).isValid())
227 return m_series->barSets().at(index.column() - m_firstBarSetSection);
228 return m_series->barSets().at(index.column() - m_firstBarSetSection);
228 // else
229 // else
229 // return 0;
230 // return 0;
230 }
231 }
231 } else if (m_orientation == Qt::Horizontal && index.row() >= m_firstBarSetSection && index.row() <= m_lastBarSetSection) {
232 } else if (m_orientation == Qt::Horizontal && index.row() >= m_firstBarSetSection && index.row() <= m_lastBarSetSection) {
232 if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count))
233 if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count))
233 return m_series->barSets().at(index.row() - m_firstBarSetSection);
234 return m_series->barSets().at(index.row() - m_firstBarSetSection);
234 }
235 }
235 return 0; // This part of model has not been mapped to any slice
236 return 0; // This part of model has not been mapped to any slice
236 }
237 }
237
238
238 QModelIndex QBarModelMapperPrivate::barModelIndex(int barSection, int posInBar)
239 QModelIndex QBarModelMapperPrivate::barModelIndex(int barSection, int posInBar)
239 {
240 {
240 if (m_count != -1 && posInBar >= m_count)
241 if (m_count != -1 && posInBar >= m_count)
241 return QModelIndex(); // invalid
242 return QModelIndex(); // invalid
242
243
243 if (barSection < m_firstBarSetSection || barSection > m_lastBarSetSection)
244 if (barSection < m_firstBarSetSection || barSection > m_lastBarSetSection)
244 return QModelIndex(); // invalid
245 return QModelIndex(); // invalid
245
246
246 if (m_orientation == Qt::Vertical)
247 if (m_orientation == Qt::Vertical)
247 return m_model->index(posInBar + m_first, barSection);
248 return m_model->index(posInBar + m_first, barSection);
248 else
249 else
249 return m_model->index(barSection, posInBar + m_first);
250 return m_model->index(barSection, posInBar + m_first);
250 }
251 }
251
252
252 void QBarModelMapperPrivate::handleSeriesDestroyed()
253 void QBarModelMapperPrivate::handleSeriesDestroyed()
253 {
254 {
254 m_series = 0;
255 m_series = 0;
255 }
256 }
256
257
257 void QBarModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
258 void QBarModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
258 {
259 {
259 Q_UNUSED(topLeft)
260 Q_UNUSED(topLeft)
260 Q_UNUSED(bottomRight)
261 Q_UNUSED(bottomRight)
261
262
262 if (m_model == 0 || m_series == 0)
263 if (m_model == 0 || m_series == 0)
263 return;
264 return;
264
265
265 if (m_modelSignalsBlock)
266 if (m_modelSignalsBlock)
266 return;
267 return;
267
268
268 blockSeriesSignals();
269 blockSeriesSignals();
269 QModelIndex index;
270 QModelIndex index;
270 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
271 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
271 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
272 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
272 index = topLeft.sibling(row, column);
273 index = topLeft.sibling(row, column);
273 QBarSet* bar = barSet(index);
274 QBarSet* bar = barSet(index);
274 if (bar) {
275 if (bar) {
275 if (m_orientation == Qt::Vertical)
276 if (m_orientation == Qt::Vertical)
276 bar->replace(row - m_first, m_model->data(index).toReal());
277 bar->replace(row - m_first, m_model->data(index).toReal());
277 else
278 else
278 bar->replace(column - m_first, m_model->data(index).toReal());
279 bar->replace(column - m_first, m_model->data(index).toReal());
279 }
280 }
280 }
281 }
281 }
282 }
282 blockSeriesSignals(false);
283 blockSeriesSignals(false);
283 }
284 }
284
285
285 void QBarModelMapperPrivate::modelHeaderDataUpdated(Qt::Orientation orientation, int first, int last)
286 void QBarModelMapperPrivate::modelHeaderDataUpdated(Qt::Orientation orientation, int first, int last)
286 {
287 {
287 if (m_model == 0 || m_series == 0)
288 if (m_model == 0 || m_series == 0)
288 return;
289 return;
289
290
290 if (m_modelSignalsBlock)
291 if (m_modelSignalsBlock)
291 return;
292 return;
292
293
293 blockSeriesSignals();
294 blockSeriesSignals();
294 if (orientation != m_orientation) {
295 if (orientation != m_orientation) {
295 for (int section = first; section <= last; section++) {
296 for (int section = first; section <= last; section++) {
296 if (section >= m_firstBarSetSection && section <= m_lastBarSetSection) {
297 if (section >= m_firstBarSetSection && section <= m_lastBarSetSection) {
297 QBarSet* bar = m_series->barSets().at(section - m_firstBarSetSection);
298 QBarSet* bar = m_series->barSets().at(section - m_firstBarSetSection);
298 if (bar)
299 if (bar)
299 bar->setLabel(m_model->headerData(section, orientation).toString());
300 bar->setLabel(m_model->headerData(section, orientation).toString());
300 }
301 }
301 }
302 }
302 }
303 }
303 blockSeriesSignals(false);
304 blockSeriesSignals(false);
304 }
305 }
305
306
306 void QBarModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
307 void QBarModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
307 {
308 {
308 Q_UNUSED(parent);
309 Q_UNUSED(parent);
309 Q_UNUSED(end)
310 Q_UNUSED(end)
310 if (m_modelSignalsBlock)
311 if (m_modelSignalsBlock)
311 return;
312 return;
312
313
313 blockSeriesSignals();
314 blockSeriesSignals();
314 if (m_orientation == Qt::Vertical)
315 if (m_orientation == Qt::Vertical)
315 // insertData(start, end);
316 // insertData(start, end);
316 initializeBarFromModel();
317 initializeBarFromModel();
317 else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
318 else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
318 initializeBarFromModel();
319 initializeBarFromModel();
319 blockSeriesSignals(false);
320 blockSeriesSignals(false);
320 }
321 }
321
322
322 void QBarModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
323 void QBarModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
323 {
324 {
324 Q_UNUSED(parent);
325 Q_UNUSED(parent);
325 Q_UNUSED(end)
326 Q_UNUSED(end)
326 if (m_modelSignalsBlock)
327 if (m_modelSignalsBlock)
327 return;
328 return;
328
329
329 blockSeriesSignals();
330 blockSeriesSignals();
330 if (m_orientation == Qt::Vertical)
331 if (m_orientation == Qt::Vertical)
331 // removeData(start, end);
332 // removeData(start, end);
332 initializeBarFromModel();
333 initializeBarFromModel();
333 else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
334 else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
334 initializeBarFromModel();
335 initializeBarFromModel();
335 blockSeriesSignals(false);
336 blockSeriesSignals(false);
336 }
337 }
337
338
338 void QBarModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
339 void QBarModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
339 {
340 {
340 Q_UNUSED(parent);
341 Q_UNUSED(parent);
341 Q_UNUSED(end)
342 Q_UNUSED(end)
342 if (m_modelSignalsBlock)
343 if (m_modelSignalsBlock)
343 return;
344 return;
344
345
345 blockSeriesSignals();
346 blockSeriesSignals();
346 if (m_orientation == Qt::Horizontal)
347 if (m_orientation == Qt::Horizontal)
347 // insertData(start, end);
348 // insertData(start, end);
348 initializeBarFromModel();
349 initializeBarFromModel();
349 else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
350 else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
350 initializeBarFromModel();
351 initializeBarFromModel();
351 blockSeriesSignals(false);
352 blockSeriesSignals(false);
352 }
353 }
353
354
354 void QBarModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
355 void QBarModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
355 {
356 {
356 Q_UNUSED(parent);
357 Q_UNUSED(parent);
357 Q_UNUSED(end)
358 Q_UNUSED(end)
358 if (m_modelSignalsBlock)
359 if (m_modelSignalsBlock)
359 return;
360 return;
360
361
361 blockSeriesSignals();
362 blockSeriesSignals();
362 if (m_orientation == Qt::Horizontal)
363 if (m_orientation == Qt::Horizontal)
363 // removeData(start, end);
364 // removeData(start, end);
364 initializeBarFromModel();
365 initializeBarFromModel();
365 else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
366 else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
366 initializeBarFromModel();
367 initializeBarFromModel();
367 blockSeriesSignals(false);
368 blockSeriesSignals(false);
368 }
369 }
369
370
370 void QBarModelMapperPrivate::handleModelDestroyed()
371 void QBarModelMapperPrivate::handleModelDestroyed()
371 {
372 {
372 m_model = 0;
373 m_model = 0;
373 }
374 }
374
375
375 void QBarModelMapperPrivate::insertData(int start, int end)
376 void QBarModelMapperPrivate::insertData(int start, int end)
376 {
377 {
377 Q_UNUSED(end)
378 Q_UNUSED(end)
378 Q_UNUSED(start)
379 Q_UNUSED(start)
379 Q_UNUSED(end)
380 Q_UNUSED(end)
380 // To be implemented
381 // To be implemented
381 }
382 }
382
383
383 void QBarModelMapperPrivate::removeData(int start, int end)
384 void QBarModelMapperPrivate::removeData(int start, int end)
384 {
385 {
385 Q_UNUSED(end)
386 Q_UNUSED(end)
386 Q_UNUSED(start)
387 Q_UNUSED(start)
387 Q_UNUSED(end)
388 Q_UNUSED(end)
388 // To be implemented
389 // To be implemented
389 }
390 }
390
391
391 void QBarModelMapperPrivate::barSetsAdded(QList<QBarSet*> sets)
392 void QBarModelMapperPrivate::barSetsAdded(QList<QBarSet*> sets)
392 {
393 {
393 if (m_seriesSignalsBlock)
394 if (m_seriesSignalsBlock)
394 return;
395 return;
395
396
396 if (sets.count() == 0)
397 if (sets.count() == 0)
397 return;
398 return;
398
399
399 int firstIndex = m_series->barSets().indexOf(sets.at(0));
400 int firstIndex = m_series->barSets().indexOf(sets.at(0));
400 if (firstIndex == -1)
401 if (firstIndex == -1)
401 return;
402 return;
402
403
403 int maxCount = 0;
404 int maxCount = 0;
404 for(int i = 0; i < sets.count(); i++)
405 for(int i = 0; i < sets.count(); i++)
405 if (sets.at(i)->count() > m_count)
406 if (sets.at(i)->count() > m_count)
406 maxCount = sets.at(i)->count();
407 maxCount = sets.at(i)->count();
407
408
408 if (m_count != -1 && m_count < maxCount)
409 if (m_count != -1 && m_count < maxCount)
409 m_count = maxCount;
410 m_count = maxCount;
410
411
411 m_lastBarSetSection += sets.count();
412 m_lastBarSetSection += sets.count();
412
413
413 blockModelSignals();
414 blockModelSignals();
414 int modelCapacity = m_orientation == Qt::Vertical ? m_model->rowCount() - m_first : m_model->columnCount() - m_first;
415 int modelCapacity = m_orientation == Qt::Vertical ? m_model->rowCount() - m_first : m_model->columnCount() - m_first;
415 if (maxCount > modelCapacity) {
416 if (maxCount > modelCapacity) {
416 if (m_orientation == Qt::Vertical)
417 if (m_orientation == Qt::Vertical)
417 m_model->insertRows(m_model->rowCount(), maxCount - modelCapacity);
418 m_model->insertRows(m_model->rowCount(), maxCount - modelCapacity);
418 else
419 else
419 m_model->insertColumns(m_model->columnCount(), maxCount - modelCapacity);
420 m_model->insertColumns(m_model->columnCount(), maxCount - modelCapacity);
420 }
421 }
421
422
422 if (m_orientation == Qt::Vertical)
423 if (m_orientation == Qt::Vertical)
423 m_model->insertColumns(firstIndex + m_firstBarSetSection, sets.count());
424 m_model->insertColumns(firstIndex + m_firstBarSetSection, sets.count());
424 else
425 else
425 m_model->insertRows(firstIndex + m_firstBarSetSection, sets.count());
426 m_model->insertRows(firstIndex + m_firstBarSetSection, sets.count());
426
427
427
428
428 for(int i = firstIndex + m_firstBarSetSection; i < firstIndex + m_firstBarSetSection + sets.count(); i++) {
429 for(int i = firstIndex + m_firstBarSetSection; i < firstIndex + m_firstBarSetSection + sets.count(); i++) {
429 m_model->setHeaderData(i, m_orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical, sets.at(i - firstIndex - m_firstBarSetSection)->label());
430 m_model->setHeaderData(i, m_orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical, sets.at(i - firstIndex - m_firstBarSetSection)->label());
430 for (int j = 0; j < sets.at(i - firstIndex - m_firstBarSetSection)->count(); j++)
431 for (int j = 0; j < sets.at(i - firstIndex - m_firstBarSetSection)->count(); j++)
431 m_model->setData(barModelIndex(i, j), sets.at(i - firstIndex - m_firstBarSetSection)->at(j));
432 m_model->setData(barModelIndex(i, j), sets.at(i - firstIndex - m_firstBarSetSection)->at(j));
432 }
433 }
433 blockModelSignals(false);
434 blockModelSignals(false);
434 initializeBarFromModel();
435 initializeBarFromModel();
435 }
436 }
436
437
437 void QBarModelMapperPrivate::barSetsRemoved(QList<QBarSet*> sets)
438 void QBarModelMapperPrivate::barSetsRemoved(QList<QBarSet*> sets)
438 {
439 {
439 if (m_seriesSignalsBlock)
440 if (m_seriesSignalsBlock)
440 return;
441 return;
441
442
442 if (sets.count() == 0)
443 if (sets.count() == 0)
443 return;
444 return;
444
445
445 int firstIndex = m_barSets.indexOf(sets.at(0));
446 int firstIndex = m_barSets.indexOf(sets.at(0));
446 if (firstIndex == -1)
447 if (firstIndex == -1)
447 return;
448 return;
448
449
449 m_lastBarSetSection -= sets.count();
450 m_lastBarSetSection -= sets.count();
450
451
451 for (int i = firstIndex + sets.count() - 1; i >= firstIndex; i--)
452 for (int i = firstIndex + sets.count() - 1; i >= firstIndex; i--)
452 m_barSets.removeAt(i);
453 m_barSets.removeAt(i);
453
454
454 blockModelSignals();
455 blockModelSignals();
455 if (m_orientation == Qt::Vertical)
456 if (m_orientation == Qt::Vertical)
456 m_model->removeColumns(firstIndex + m_firstBarSetSection, sets.count());
457 m_model->removeColumns(firstIndex + m_firstBarSetSection, sets.count());
457 else
458 else
458 m_model->removeRows(firstIndex + m_firstBarSetSection, sets.count());
459 m_model->removeRows(firstIndex + m_firstBarSetSection, sets.count());
459 blockModelSignals(false);
460 blockModelSignals(false);
460 initializeBarFromModel();
461 initializeBarFromModel();
461 }
462 }
462
463
463 void QBarModelMapperPrivate::valuesAdded(int index, int count)
464 void QBarModelMapperPrivate::valuesAdded(int index, int count)
464 {
465 {
465 if (m_seriesSignalsBlock)
466 if (m_seriesSignalsBlock)
466 return;
467 return;
467
468
468 if (m_count != -1)
469 if (m_count != -1)
469 m_count += count;
470 m_count += count;
470
471
471 int barSetIndex = m_barSets.indexOf(qobject_cast<QBarSet *>(QObject::sender()));
472 int barSetIndex = m_barSets.indexOf(qobject_cast<QBarSet *>(QObject::sender()));
472
473
473 blockModelSignals();
474 blockModelSignals();
474 if (m_orientation == Qt::Vertical)
475 if (m_orientation == Qt::Vertical)
475 m_model->insertRows(index + m_first, count);
476 m_model->insertRows(index + m_first, count);
476 else
477 else
477 m_model->insertColumns(index + m_first, count);
478 m_model->insertColumns(index + m_first, count);
478
479
479 for (int j = index; j < index + count; j++)
480 for (int j = index; j < index + count; j++)
480 m_model->setData(barModelIndex(barSetIndex + m_firstBarSetSection, j), m_barSets.at(barSetIndex)->at(j));
481 m_model->setData(barModelIndex(barSetIndex + m_firstBarSetSection, j), m_barSets.at(barSetIndex)->at(j));
481
482
482 blockModelSignals(false);
483 blockModelSignals(false);
483 initializeBarFromModel();
484 initializeBarFromModel();
484 }
485 }
485
486
486 void QBarModelMapperPrivate::valuesRemoved(int index, int count)
487 void QBarModelMapperPrivate::valuesRemoved(int index, int count)
487 {
488 {
488 if (m_seriesSignalsBlock)
489 if (m_seriesSignalsBlock)
489 return;
490 return;
490
491
491 if (m_count != -1)
492 if (m_count != -1)
492 m_count -= count;
493 m_count -= count;
493
494
494 blockModelSignals();
495 blockModelSignals();
495 if (m_orientation == Qt::Vertical)
496 if (m_orientation == Qt::Vertical)
496 m_model->removeRows(index + m_first, count);
497 m_model->removeRows(index + m_first, count);
497 else
498 else
498 m_model->removeColumns(index + m_first, count);
499 m_model->removeColumns(index + m_first, count);
499
500
500 blockModelSignals(false);
501 blockModelSignals(false);
501 initializeBarFromModel();
502 initializeBarFromModel();
502 }
503 }
503
504
504 void QBarModelMapperPrivate::barLabelChanged()
505 void QBarModelMapperPrivate::barLabelChanged()
505 {
506 {
506 if (m_seriesSignalsBlock)
507 if (m_seriesSignalsBlock)
507 return;
508 return;
508
509
509 int barSetIndex = m_barSets.indexOf(qobject_cast<QBarSet *>(QObject::sender()));
510 int barSetIndex = m_barSets.indexOf(qobject_cast<QBarSet *>(QObject::sender()));
510
511
511 blockModelSignals();
512 blockModelSignals();
512 m_model->setHeaderData(barSetIndex + m_firstBarSetSection, m_orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical, m_barSets.at(barSetIndex)->label());
513 m_model->setHeaderData(barSetIndex + m_firstBarSetSection, m_orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical, m_barSets.at(barSetIndex)->label());
513 blockModelSignals(false);
514 blockModelSignals(false);
514 initializeBarFromModel();
515 initializeBarFromModel();
515 }
516 }
516
517
517 void QBarModelMapperPrivate::barValueChanged(int index)
518 void QBarModelMapperPrivate::barValueChanged(int index)
518 {
519 {
519 if (m_seriesSignalsBlock)
520 if (m_seriesSignalsBlock)
520 return;
521 return;
521
522
522 int barSetIndex = m_barSets.indexOf(qobject_cast<QBarSet *>(QObject::sender()));
523 int barSetIndex = m_barSets.indexOf(qobject_cast<QBarSet *>(QObject::sender()));
523
524
524 blockModelSignals();
525 blockModelSignals();
525 m_model->setData(barModelIndex(barSetIndex + m_firstBarSetSection, index), m_barSets.at(barSetIndex)->at(index));
526 m_model->setData(barModelIndex(barSetIndex + m_firstBarSetSection, index), m_barSets.at(barSetIndex)->at(index));
526 blockModelSignals(false);
527 blockModelSignals(false);
527 initializeBarFromModel();
528 initializeBarFromModel();
528 }
529 }
529
530
530 void QBarModelMapperPrivate::initializeBarFromModel()
531 void QBarModelMapperPrivate::initializeBarFromModel()
531 {
532 {
532 if (m_model == 0 || m_series == 0)
533 if (m_model == 0 || m_series == 0)
533 return;
534 return;
534
535
535 blockSeriesSignals();
536 blockSeriesSignals();
536 // clear current content
537 // clear current content
537 m_series->clear();
538 m_series->clear();
538 m_barSets.clear();
539 m_barSets.clear();
539
540
540 // create the initial bar sets
541 // create the initial bar sets
541 for (int i = m_firstBarSetSection; i <= m_lastBarSetSection; i++) {
542 for (int i = m_firstBarSetSection; i <= m_lastBarSetSection; i++) {
542 int posInBar = 0;
543 int posInBar = 0;
543 QModelIndex barIndex = barModelIndex(i, posInBar);
544 QModelIndex barIndex = barModelIndex(i, posInBar);
544 // check if there is such model index
545 // check if there is such model index
545 if (barIndex.isValid()) {
546 if (barIndex.isValid()) {
546 QBarSet *barSet = new QBarSet(m_model->headerData(i, m_orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical).toString());
547 QBarSet *barSet = new QBarSet(m_model->headerData(i, m_orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical).toString());
547 while (barIndex.isValid()) {
548 while (barIndex.isValid()) {
548 barSet->append(m_model->data(barIndex, Qt::DisplayRole).toDouble());
549 barSet->append(m_model->data(barIndex, Qt::DisplayRole).toDouble());
549 posInBar++;
550 posInBar++;
550 barIndex = barModelIndex(i, posInBar);
551 barIndex = barModelIndex(i, posInBar);
551 }
552 }
552 connect(barSet, SIGNAL(valuesAdded(int, int)), this, SLOT(valuesAdded(int, int)));
553 connect(barSet, SIGNAL(valuesAdded(int, int)), this, SLOT(valuesAdded(int, int)));
553 connect(barSet, SIGNAL(valuesRemoved(int, int)), this, SLOT(valuesRemoved(int, int)));
554 connect(barSet, SIGNAL(valuesRemoved(int, int)), this, SLOT(valuesRemoved(int, int)));
554 connect(barSet, SIGNAL(valueChanged(int)), this, SLOT(barValueChanged(int)));
555 connect(barSet, SIGNAL(valueChanged(int)), this, SLOT(barValueChanged(int)));
555 connect(barSet, SIGNAL(labelChanged()), this, SLOT(barLabelChanged()));
556 connect(barSet, SIGNAL(labelChanged()), this, SLOT(barLabelChanged()));
556 m_series->append(barSet);
557 m_series->append(barSet);
557 m_barSets.append(barSet);
558 m_barSets.append(barSet);
558 } else {
559 } else {
559 break;
560 break;
560 }
561 }
561 }
562 }
562 blockSeriesSignals(false);
563 blockSeriesSignals(false);
563 }
564 }
564
565
565 #include "moc_qbarmodelmapper.cpp"
566 #include "moc_qbarmodelmapper.cpp"
566 #include "moc_qbarmodelmapper_p.cpp"
567 #include "moc_qbarmodelmapper_p.cpp"
567
568
568 QTCOMMERCIALCHART_END_NAMESPACE
569 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,27 +1,29
1 INCLUDEPATH += $$PWD
1 INCLUDEPATH += $$PWD
2 DEPENDPATH += $$PWD
2 DEPENDPATH += $$PWD
3
3
4 SOURCES += \
4 SOURCES += \
5 $$PWD/qpieseries.cpp \
5 $$PWD/qpieseries.cpp \
6 $$PWD/piesliceitem.cpp \
6 $$PWD/piesliceitem.cpp \
7 $$PWD/piechartitem.cpp \
7 $$PWD/piechartitem.cpp \
8 $$PWD/qpieslice.cpp \
8 $$PWD/qpieslice.cpp \
9 $$PWD/qpiemodelmapper.cpp \
9 $$PWD/qpiemodelmapper.cpp \
10 $$PWD/qvpiemodelmapper.cpp \
10 $$PWD/qvpiemodelmapper.cpp \
11 $$PWD/qhpiemodelmapper.cpp
11 $$PWD/qhpiemodelmapper.cpp \
12 piechart/qdonutgroup.cpp
12
13
13 PRIVATE_HEADERS += \
14 PRIVATE_HEADERS += \
14 $$PWD/pieslicedata_p.h \
15 $$PWD/pieslicedata_p.h \
15 $$PWD/piechartitem_p.h \
16 $$PWD/piechartitem_p.h \
16 $$PWD/piesliceitem_p.h \
17 $$PWD/piesliceitem_p.h \
17 $$PWD/qpieslice_p.h \
18 $$PWD/qpieslice_p.h \
18 $$PWD/qpieseries_p.h \
19 $$PWD/qpieseries_p.h \
19 $$PWD/qpiemodelmapper_p.h
20 $$PWD/qpiemodelmapper_p.h \
21 $$PWD/qdonutgroup_p.h
20
22
21 PUBLIC_HEADERS += \
23 PUBLIC_HEADERS += \
22 $$PWD/qpieseries.h \
24 $$PWD/qpieseries.h \
23 $$PWD/qpieslice.h \
25 $$PWD/qpieslice.h \
24 $$PWD/qpiemodelmapper.h \
26 $$PWD/qpiemodelmapper.h \
25 $$PWD/qvpiemodelmapper.h \
27 $$PWD/qvpiemodelmapper.h \
26 $$PWD/qhpiemodelmapper.h
28 $$PWD/qhpiemodelmapper.h \
27
29 $$PWD/qdonutgroup.h
@@ -1,223 +1,226
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "piechartitem_p.h"
21 #include "piechartitem_p.h"
22 #include "piesliceitem_p.h"
22 #include "piesliceitem_p.h"
23 #include "qpieslice.h"
23 #include "qpieslice.h"
24 #include "qpieslice_p.h"
24 #include "qpieslice_p.h"
25 #include "qpieseries.h"
25 #include "qpieseries.h"
26 #include "qpieseries_p.h"
26 #include "qpieseries_p.h"
27 #include "chartpresenter_p.h"
27 #include "chartpresenter_p.h"
28 #include "chartdataset_p.h"
28 #include "chartdataset_p.h"
29 #include "chartanimator_p.h"
29 #include "chartanimator_p.h"
30 #include <QPainter>
30 #include <QPainter>
31 #include <QTimer>
31 #include <QTimer>
32
32
33 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 QTCOMMERCIALCHART_BEGIN_NAMESPACE
34
34
35 PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter* presenter)
35 PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter* presenter)
36 :ChartItem(presenter),
36 :ChartItem(presenter),
37 m_series(series)
37 m_series(series)
38 {
38 {
39 Q_ASSERT(series);
39 Q_ASSERT(series);
40
40
41 QPieSeriesPrivate *p = QPieSeriesPrivate::fromSeries(series);
41 QPieSeriesPrivate *p = QPieSeriesPrivate::fromSeries(series);
42 connect(series, SIGNAL(visibleChanged()), this, SLOT(handleSeriesVisibleChanged()));
42 connect(series, SIGNAL(visibleChanged()), this, SLOT(handleSeriesVisibleChanged()));
43 connect(series, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>)));
43 connect(series, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>)));
44 connect(series, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>)));
44 connect(series, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>)));
45 connect(p, SIGNAL(horizontalPositionChanged()), this, SLOT(updateLayout()));
45 connect(p, SIGNAL(horizontalPositionChanged()), this, SLOT(updateLayout()));
46 connect(p, SIGNAL(verticalPositionChanged()), this, SLOT(updateLayout()));
46 connect(p, SIGNAL(verticalPositionChanged()), this, SLOT(updateLayout()));
47 connect(p, SIGNAL(pieSizeChanged()), this, SLOT(updateLayout()));
47 connect(p, SIGNAL(pieSizeChanged()), this, SLOT(updateLayout()));
48 connect(p, SIGNAL(calculatedDataChanged()), this, SLOT(updateLayout()));
48 connect(p, SIGNAL(calculatedDataChanged()), this, SLOT(updateLayout()));
49
49
50 // Note: the following does not affect as long as the item does not have anything to paint
50 // Note: the following does not affect as long as the item does not have anything to paint
51 setZValue(ChartPresenter::PieSeriesZValue);
51 setZValue(ChartPresenter::PieSeriesZValue);
52
52
53 // Note: will not create slice items until we have a proper rectangle to draw on.
53 // Note: will not create slice items until we have a proper rectangle to draw on.
54 }
54 }
55
55
56 PieChartItem::~PieChartItem()
56 PieChartItem::~PieChartItem()
57 {
57 {
58 // slices deleted automatically through QGraphicsItem
58 // slices deleted automatically through QGraphicsItem
59 }
59 }
60
60
61 void PieChartItem::handleGeometryChanged(const QRectF& rect)
61 void PieChartItem::handleGeometryChanged(const QRectF& rect)
62 {
62 {
63 prepareGeometryChange();
63 prepareGeometryChange();
64 m_rect = rect;
64 m_rect = rect;
65 updateLayout();
65 updateLayout();
66
66
67 // This is for delayed initialization of the slice items during startup.
67 // This is for delayed initialization of the slice items during startup.
68 // It ensures that startup animation originates from the correct position.
68 // It ensures that startup animation originates from the correct position.
69 if (m_sliceItems.isEmpty())
69 if (m_sliceItems.isEmpty())
70 handleSlicesAdded(m_series->slices());
70 handleSlicesAdded(m_series->slices());
71 }
71 }
72
72
73 void PieChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
73 void PieChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
74 {
74 {
75 Q_UNUSED(minX);
75 Q_UNUSED(minX);
76 Q_UNUSED(maxX);
76 Q_UNUSED(maxX);
77 Q_UNUSED(minY);
77 Q_UNUSED(minY);
78 Q_UNUSED(maxY);
78 Q_UNUSED(maxY);
79 // does not apply to pie
79 // does not apply to pie
80 }
80 }
81
81
82 void PieChartItem::rangeXChanged(qreal min, qreal max, int tickXCount)
82 void PieChartItem::rangeXChanged(qreal min, qreal max, int tickXCount)
83 {
83 {
84 Q_UNUSED(min);
84 Q_UNUSED(min);
85 Q_UNUSED(max);
85 Q_UNUSED(max);
86 Q_UNUSED(tickXCount);
86 Q_UNUSED(tickXCount);
87 // does not apply to pie
87 // does not apply to pie
88 }
88 }
89
89
90 void PieChartItem::rangeYChanged(qreal min, qreal max, int tickYCount)
90 void PieChartItem::rangeYChanged(qreal min, qreal max, int tickYCount)
91 {
91 {
92 Q_UNUSED(min);
92 Q_UNUSED(min);
93 Q_UNUSED(max);
93 Q_UNUSED(max);
94 Q_UNUSED(tickYCount);
94 Q_UNUSED(tickYCount);
95 // does not apply to pie
95 // does not apply to pie
96 }
96 }
97
97
98 void PieChartItem::updateLayout()
98 void PieChartItem::updateLayout()
99 {
99 {
100 // find pie center coordinates
100 // find pie center coordinates
101 m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->horizontalPosition()));
101 m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->horizontalPosition()));
102 m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->verticalPosition()));
102 m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->verticalPosition()));
103
103
104 // find maximum radius for pie
104 // find maximum radius for pie
105 m_pieRadius = m_rect.height() / 2;
105 m_pieRadius = m_rect.height() / 2;
106 if (m_rect.width() < m_rect.height())
106 if (m_rect.width() < m_rect.height())
107 m_pieRadius = m_rect.width() / 2;
107 m_pieRadius = m_rect.width() / 2;
108
108
109 m_donutInnerRadius = m_pieRadius;
109 // apply size factor
110 // apply size factor
110 m_pieRadius *= m_series->pieSize();
111 m_pieRadius *= m_series->pieSize();
112 m_donutInnerRadius *= m_series->donutInnerSize();
111
113
112 // set layouts for existing slice items
114 // set layouts for existing slice items
113 foreach (QPieSlice* slice, m_series->slices()) {
115 foreach (QPieSlice* slice, m_series->slices()) {
114 PieSliceItem *sliceItem = m_sliceItems.value(slice);
116 PieSliceItem *sliceItem = m_sliceItems.value(slice);
115 if (sliceItem) {
117 if (sliceItem) {
116 PieSliceData sliceData = updateSliceGeometry(slice);
118 PieSliceData sliceData = updateSliceGeometry(slice);
117 if (animator())
119 if (animator())
118 animator()->updateAnimation(this, sliceItem, sliceData);
120 animator()->updateAnimation(this, sliceItem, sliceData);
119 else
121 else
120 sliceItem->setLayout(sliceData);
122 sliceItem->setLayout(sliceData);
121 }
123 }
122 }
124 }
123
125
124 update();
126 update();
125 }
127 }
126
128
127 void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices)
129 void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices)
128 {
130 {
129 // delay creating slice items until there is a proper rectangle
131 // delay creating slice items until there is a proper rectangle
130 if (!m_rect.isValid() && m_sliceItems.isEmpty())
132 if (!m_rect.isValid() && m_sliceItems.isEmpty())
131 return;
133 return;
132
134
133 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
135 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
134
136
135 bool startupAnimation = m_sliceItems.isEmpty();
137 bool startupAnimation = m_sliceItems.isEmpty();
136
138
137 foreach (QPieSlice *slice, slices) {
139 foreach (QPieSlice *slice, slices) {
138 PieSliceItem* sliceItem = new PieSliceItem(this);
140 PieSliceItem* sliceItem = new PieSliceItem(this);
139 m_sliceItems.insert(slice, sliceItem);
141 m_sliceItems.insert(slice, sliceItem);
140
142
141 // Note: no need to connect to slice valueChanged() etc.
143 // Note: no need to connect to slice valueChanged() etc.
142 // This is handled through calculatedDataChanged signal.
144 // This is handled through calculatedDataChanged signal.
143 connect(slice, SIGNAL(labelChanged()), this, SLOT(handleSliceChanged()));
145 connect(slice, SIGNAL(labelChanged()), this, SLOT(handleSliceChanged()));
144 connect(slice, SIGNAL(labelVisibleChanged()), this, SLOT(handleSliceChanged()));
146 connect(slice, SIGNAL(labelVisibleChanged()), this, SLOT(handleSliceChanged()));
145 connect(slice, SIGNAL(penChanged()), this, SLOT(handleSliceChanged()));
147 connect(slice, SIGNAL(penChanged()), this, SLOT(handleSliceChanged()));
146 connect(slice, SIGNAL(brushChanged()), this, SLOT(handleSliceChanged()));
148 connect(slice, SIGNAL(brushChanged()), this, SLOT(handleSliceChanged()));
147 connect(slice, SIGNAL(labelBrushChanged()), this, SLOT(handleSliceChanged()));
149 connect(slice, SIGNAL(labelBrushChanged()), this, SLOT(handleSliceChanged()));
148 connect(slice, SIGNAL(labelFontChanged()), this, SLOT(handleSliceChanged()));
150 connect(slice, SIGNAL(labelFontChanged()), this, SLOT(handleSliceChanged()));
149
151
150 QPieSlicePrivate *p = QPieSlicePrivate::fromSlice(slice);
152 QPieSlicePrivate *p = QPieSlicePrivate::fromSlice(slice);
151 connect(p, SIGNAL(labelPositionChanged()), this, SLOT(handleSliceChanged()));
153 connect(p, SIGNAL(labelPositionChanged()), this, SLOT(handleSliceChanged()));
152 connect(p, SIGNAL(explodedChanged()), this, SLOT(handleSliceChanged()));
154 connect(p, SIGNAL(explodedChanged()), this, SLOT(handleSliceChanged()));
153 connect(p, SIGNAL(labelArmLengthFactorChanged()), this, SLOT(handleSliceChanged()));
155 connect(p, SIGNAL(labelArmLengthFactorChanged()), this, SLOT(handleSliceChanged()));
154 connect(p, SIGNAL(explodeDistanceFactorChanged()), this, SLOT(handleSliceChanged()));
156 connect(p, SIGNAL(explodeDistanceFactorChanged()), this, SLOT(handleSliceChanged()));
155
157
156 connect(sliceItem, SIGNAL(clicked(Qt::MouseButtons)), slice, SIGNAL(clicked()));
158 connect(sliceItem, SIGNAL(clicked(Qt::MouseButtons)), slice, SIGNAL(clicked()));
157 connect(sliceItem, SIGNAL(hovered(bool)), slice, SIGNAL(hovered(bool)));
159 connect(sliceItem, SIGNAL(hovered(bool)), slice, SIGNAL(hovered(bool)));
158
160
159 PieSliceData sliceData = updateSliceGeometry(slice);
161 PieSliceData sliceData = updateSliceGeometry(slice);
160 if (animator())
162 if (animator())
161 animator()->addAnimation(this, sliceItem, sliceData, startupAnimation);
163 animator()->addAnimation(this, sliceItem, sliceData, startupAnimation);
162 else
164 else
163 sliceItem->setLayout(sliceData);
165 sliceItem->setLayout(sliceData);
164 }
166 }
165 }
167 }
166
168
167 void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices)
169 void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices)
168 {
170 {
169 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
171 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
170
172
171 foreach (QPieSlice *slice, slices) {
173 foreach (QPieSlice *slice, slices) {
172
174
173 PieSliceItem *sliceItem = m_sliceItems.value(slice);
175 PieSliceItem *sliceItem = m_sliceItems.value(slice);
174
176
175 // this can happen if you call append() & remove() in a row so that PieSliceItem is not even created
177 // this can happen if you call append() & remove() in a row so that PieSliceItem is not even created
176 if (!sliceItem)
178 if (!sliceItem)
177 continue;
179 continue;
178
180
179 m_sliceItems.remove(slice);
181 m_sliceItems.remove(slice);
180
182
181 if (animator())
183 if (animator())
182 animator()->removeAnimation(this, sliceItem); // animator deletes the PieSliceItem
184 animator()->removeAnimation(this, sliceItem); // animator deletes the PieSliceItem
183 else
185 else
184 delete sliceItem;
186 delete sliceItem;
185 }
187 }
186 }
188 }
187
189
188 void PieChartItem::handleSliceChanged()
190 void PieChartItem::handleSliceChanged()
189 {
191 {
190 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
192 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
191 if (!slice) {
193 if (!slice) {
192 QPieSlicePrivate* slicep = qobject_cast<QPieSlicePrivate *>(sender());
194 QPieSlicePrivate* slicep = qobject_cast<QPieSlicePrivate *>(sender());
193 slice = slicep->q_ptr;
195 slice = slicep->q_ptr;
194 }
196 }
195 Q_ASSERT(m_sliceItems.contains(slice));
197 Q_ASSERT(m_sliceItems.contains(slice));
196
198
197 PieSliceItem *sliceItem = m_sliceItems.value(slice);
199 PieSliceItem *sliceItem = m_sliceItems.value(slice);
198 PieSliceData sliceData = updateSliceGeometry(slice);
200 PieSliceData sliceData = updateSliceGeometry(slice);
199 if (animator())
201 if (animator())
200 animator()->updateAnimation(this, sliceItem, sliceData);
202 animator()->updateAnimation(this, sliceItem, sliceData);
201 else
203 else
202 sliceItem->setLayout(sliceData);
204 sliceItem->setLayout(sliceData);
203
205
204 update();
206 update();
205 }
207 }
206
208
207 void PieChartItem::handleSeriesVisibleChanged()
209 void PieChartItem::handleSeriesVisibleChanged()
208 {
210 {
209 setVisible(m_series->isVisible());
211 setVisible(m_series->isVisible());
210 }
212 }
211
213
212 PieSliceData PieChartItem::updateSliceGeometry(QPieSlice *slice)
214 PieSliceData PieChartItem::updateSliceGeometry(QPieSlice *slice)
213 {
215 {
214 PieSliceData &sliceData = QPieSlicePrivate::fromSlice(slice)->m_data;
216 PieSliceData &sliceData = QPieSlicePrivate::fromSlice(slice)->m_data;
215 sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice);
217 sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice);
216 sliceData.m_radius = m_pieRadius;
218 sliceData.m_radius = m_pieRadius;
217 sliceData.m_donut = m_series->donut();
219 sliceData.m_donut = m_series->donut();
220 sliceData.m_innerRadius = m_donutInnerRadius;
218 return sliceData;
221 return sliceData;
219 }
222 }
220
223
221 #include "moc_piechartitem_p.cpp"
224 #include "moc_piechartitem_p.cpp"
222
225
223 QTCOMMERCIALCHART_END_NAMESPACE
226 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,80 +1,81
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 // W A R N I N G
21 // W A R N I N G
22 // -------------
22 // -------------
23 //
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 // implementation detail. This header file may change from version to
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
26 // version without notice, or even be removed.
27 //
27 //
28 // We mean it.
28 // We mean it.
29
29
30 #ifndef PIECHARTITEM_H
30 #ifndef PIECHARTITEM_H
31 #define PIECHARTITEM_H
31 #define PIECHARTITEM_H
32
32
33 #include "qpieseries.h"
33 #include "qpieseries.h"
34 #include "chartitem_p.h"
34 #include "chartitem_p.h"
35 #include "piesliceitem_p.h"
35 #include "piesliceitem_p.h"
36
36
37 class QGraphicsItem;
37 class QGraphicsItem;
38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
39 class QPieSlice;
39 class QPieSlice;
40 class ChartPresenter;
40 class ChartPresenter;
41
41
42 class PieChartItem : public ChartItem
42 class PieChartItem : public ChartItem
43 {
43 {
44 Q_OBJECT
44 Q_OBJECT
45
45
46 public:
46 public:
47 explicit PieChartItem(QPieSeries *series, ChartPresenter *presenter);
47 explicit PieChartItem(QPieSeries *series, ChartPresenter *presenter);
48 ~PieChartItem();
48 ~PieChartItem();
49
49
50 // from QGraphicsItem
50 // from QGraphicsItem
51 QRectF boundingRect() const { return m_rect; }
51 QRectF boundingRect() const { return m_rect; }
52 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
52 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
53
53
54 public Q_SLOTS:
54 public Q_SLOTS:
55 // from Chart
55 // from Chart
56 virtual void handleGeometryChanged(const QRectF &rect);
56 virtual void handleGeometryChanged(const QRectF &rect);
57 virtual void handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY);
57 virtual void handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY);
58 virtual void rangeXChanged(qreal min, qreal max, int tickXCount);
58 virtual void rangeXChanged(qreal min, qreal max, int tickXCount);
59 virtual void rangeYChanged(qreal min, qreal max, int tickYCount);
59 virtual void rangeYChanged(qreal min, qreal max, int tickYCount);
60
60
61 void updateLayout();
61 void updateLayout();
62 void handleSlicesAdded(QList<QPieSlice*> slices);
62 void handleSlicesAdded(QList<QPieSlice*> slices);
63 void handleSlicesRemoved(QList<QPieSlice*> slices);
63 void handleSlicesRemoved(QList<QPieSlice*> slices);
64 void handleSliceChanged();
64 void handleSliceChanged();
65 void handleSeriesVisibleChanged();
65 void handleSeriesVisibleChanged();
66
66
67 private:
67 private:
68 PieSliceData updateSliceGeometry(QPieSlice *slice);
68 PieSliceData updateSliceGeometry(QPieSlice *slice);
69
69
70 private:
70 private:
71 QHash<QPieSlice*, PieSliceItem*> m_sliceItems;
71 QHash<QPieSlice*, PieSliceItem*> m_sliceItems;
72 QPieSeries *m_series;
72 QPieSeries *m_series;
73 QRectF m_rect;
73 QRectF m_rect;
74 QPointF m_pieCenter;
74 QPointF m_pieCenter;
75 qreal m_pieRadius;
75 qreal m_pieRadius;
76 qreal m_donutInnerRadius;
76 };
77 };
77
78
78 QTCOMMERCIALCHART_END_NAMESPACE
79 QTCOMMERCIALCHART_END_NAMESPACE
79
80
80 #endif // PIECHARTITEM_H
81 #endif // PIECHARTITEM_H
@@ -1,144 +1,148
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 // W A R N I N G
21 // W A R N I N G
22 // -------------
22 // -------------
23 //
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 // implementation detail. This header file may change from version to
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
26 // version without notice, or even be removed.
27 //
27 //
28 // We mean it.
28 // We mean it.
29
29
30 #ifndef PIESLICEDATA_P_H
30 #ifndef PIESLICEDATA_P_H
31 #define PIESLICEDATA_P_H
31 #define PIESLICEDATA_P_H
32
32
33 #include "qchartglobal.h"
33 #include "qchartglobal.h"
34 #include "qpieslice.h"
34 #include "qpieslice.h"
35 #include <QPen>
35 #include <QPen>
36 #include <QBrush>
36 #include <QBrush>
37
37
38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
39
39
40 template <class T>
40 template <class T>
41 class Themed : public T
41 class Themed : public T
42 {
42 {
43 public:
43 public:
44 Themed():m_isThemed(true) {}
44 Themed():m_isThemed(true) {}
45
45
46 inline T &operator=(const T &other) { return T::operator =(other); }
46 inline T &operator=(const T &other) { return T::operator =(other); }
47
47
48 inline bool operator!=(const T &other) const { return T::operator !=(other); }
48 inline bool operator!=(const T &other) const { return T::operator !=(other); }
49 inline bool operator!=(const Themed &other) const
49 inline bool operator!=(const Themed &other) const
50 {
50 {
51 if (T::operator !=(other))
51 if (T::operator !=(other))
52 return true;
52 return true;
53
53
54 if (m_isThemed != other.m_isThemed)
54 if (m_isThemed != other.m_isThemed)
55 return true;
55 return true;
56
56
57 return false;
57 return false;
58 }
58 }
59
59
60 inline void setThemed(bool state) { m_isThemed = state; }
60 inline void setThemed(bool state) { m_isThemed = state; }
61 inline bool isThemed() const { return m_isThemed; }
61 inline bool isThemed() const { return m_isThemed; }
62
62
63 private:
63 private:
64 bool m_isThemed;
64 bool m_isThemed;
65 };
65 };
66
66
67 class PieSliceData
67 class PieSliceData
68 {
68 {
69 public:
69 public:
70 PieSliceData()
70 PieSliceData()
71 {
71 {
72 m_value = 0;
72 m_value = 0;
73
73
74 m_isExploded = false;
74 m_isExploded = false;
75 m_explodeDistanceFactor = 0.15;
75 m_explodeDistanceFactor = 0.15;
76
76
77 m_isLabelVisible = false;
77 m_isLabelVisible = false;
78 m_labelPosition = QPieSlice::LabelOutside;
78 m_labelPosition = QPieSlice::LabelOutside;
79 m_labelArmLengthFactor = 0.15;
79 m_labelArmLengthFactor = 0.15;
80
80
81 m_percentage = 0;
81 m_percentage = 0;
82 m_radius = 0;
82 m_radius = 0;
83 m_startAngle = 0;
83 m_startAngle = 0;
84 m_angleSpan = 0;
84 m_angleSpan = 0;
85
85 m_donut = false;
86 m_donut = false;
87 m_innerRadius = 0;
86 }
88 }
87
89
88 bool operator!=(const PieSliceData &other) const
90 bool operator!=(const PieSliceData &other) const
89 {
91 {
90 if (!qFuzzyIsNull(m_value - other.m_value))
92 if (!qFuzzyIsNull(m_value - other.m_value))
91 return true;
93 return true;
92
94
93 if (m_slicePen != other.m_slicePen ||
95 if (m_slicePen != other.m_slicePen ||
94 m_sliceBrush != other.m_sliceBrush)
96 m_sliceBrush != other.m_sliceBrush)
95 return true;
97 return true;
96
98
97 if (m_isExploded != other.m_isExploded ||
99 if (m_isExploded != other.m_isExploded ||
98 !qFuzzyIsNull(m_explodeDistanceFactor - other.m_explodeDistanceFactor))
100 !qFuzzyIsNull(m_explodeDistanceFactor - other.m_explodeDistanceFactor))
99 return true;
101 return true;
100
102
101 if (m_isLabelVisible != other.m_isLabelVisible ||
103 if (m_isLabelVisible != other.m_isLabelVisible ||
102 m_labelText != other.m_labelText ||
104 m_labelText != other.m_labelText ||
103 m_labelFont != other.m_labelFont ||
105 m_labelFont != other.m_labelFont ||
104 m_labelPosition != other.m_labelPosition ||
106 m_labelPosition != other.m_labelPosition ||
105 !qFuzzyIsNull(m_labelArmLengthFactor - other.m_labelArmLengthFactor) ||
107 !qFuzzyIsNull(m_labelArmLengthFactor - other.m_labelArmLengthFactor) ||
106 m_labelBrush != other.m_labelBrush)
108 m_labelBrush != other.m_labelBrush)
107 return true;
109 return true;
108
110
109 if (!qFuzzyIsNull(m_percentage - other.m_percentage) ||
111 if (!qFuzzyIsNull(m_percentage - other.m_percentage) ||
110 m_center != other.m_center ||
112 m_center != other.m_center ||
111 !qFuzzyIsNull(m_radius - other.m_radius) ||
113 !qFuzzyIsNull(m_radius - other.m_radius) ||
112 !qFuzzyIsNull(m_startAngle - other.m_startAngle) ||
114 !qFuzzyIsNull(m_startAngle - other.m_startAngle) ||
113 !qFuzzyIsNull(m_angleSpan - other.m_angleSpan))
115 !qFuzzyIsNull(m_angleSpan - other.m_angleSpan))
114 return true;
116 return true;
115
117
116 return false;
118 return false;
117 }
119 }
118
120
119 qreal m_value;
121 qreal m_value;
120
122
121 Themed<QPen> m_slicePen;
123 Themed<QPen> m_slicePen;
122 Themed<QBrush> m_sliceBrush;
124 Themed<QBrush> m_sliceBrush;
123
125
124 bool m_isExploded;
126 bool m_isExploded;
125 qreal m_explodeDistanceFactor;
127 qreal m_explodeDistanceFactor;
126
128
127 bool m_isLabelVisible;
129 bool m_isLabelVisible;
128 QString m_labelText;
130 QString m_labelText;
129 Themed<QFont> m_labelFont;
131 Themed<QFont> m_labelFont;
130 QPieSlice::LabelPosition m_labelPosition;
132 QPieSlice::LabelPosition m_labelPosition;
131 qreal m_labelArmLengthFactor;
133 qreal m_labelArmLengthFactor;
132 Themed<QBrush> m_labelBrush;
134 Themed<QBrush> m_labelBrush;
133
135
134 qreal m_percentage;
136 qreal m_percentage;
135 QPointF m_center;
137 QPointF m_center;
136 qreal m_radius;
138 qreal m_radius;
137 qreal m_startAngle;
139 qreal m_startAngle;
138 qreal m_angleSpan;
140 qreal m_angleSpan;
141
139 bool m_donut;
142 bool m_donut;
143 qreal m_innerRadius;
140 };
144 };
141
145
142 QTCOMMERCIALCHART_END_NAMESPACE
146 QTCOMMERCIALCHART_END_NAMESPACE
143
147
144 #endif // PIESLICEDATA_P_H
148 #endif // PIESLICEDATA_P_H
@@ -1,242 +1,241
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "piesliceitem_p.h"
21 #include "piesliceitem_p.h"
22 #include "piechartitem_p.h"
22 #include "piechartitem_p.h"
23 #include "qpieseries.h"
23 #include "qpieseries.h"
24 #include "qpieslice.h"
24 #include "qpieslice.h"
25 #include "chartpresenter_p.h"
25 #include "chartpresenter_p.h"
26 #include <QPainter>
26 #include <QPainter>
27 #include <qmath.h>
27 #include <qmath.h>
28 #include <QGraphicsSceneEvent>
28 #include <QGraphicsSceneEvent>
29 #include <QTime>
29 #include <QTime>
30 #include <QDebug>
30 #include <QDebug>
31
31
32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33
33
34 QPointF offset(qreal angle, qreal length)
34 QPointF offset(qreal angle, qreal length)
35 {
35 {
36 qreal dx = qSin(angle*(M_PI/180)) * length;
36 qreal dx = qSin(angle*(M_PI/180)) * length;
37 qreal dy = qCos(angle*(M_PI/180)) * length;
37 qreal dy = qCos(angle*(M_PI/180)) * length;
38 return QPointF(dx, -dy);
38 return QPointF(dx, -dy);
39 }
39 }
40
40
41 PieSliceItem::PieSliceItem(QGraphicsItem* parent)
41 PieSliceItem::PieSliceItem(QGraphicsItem* parent)
42 :QGraphicsObject(parent),
42 :QGraphicsObject(parent),
43 m_hovered(false)
43 m_hovered(false)
44 {
44 {
45 setAcceptHoverEvents(true);
45 setAcceptHoverEvents(true);
46 setAcceptedMouseButtons(Qt::MouseButtonMask);
46 setAcceptedMouseButtons(Qt::MouseButtonMask);
47 setZValue(ChartPresenter::PieSeriesZValue);
47 setZValue(ChartPresenter::PieSeriesZValue);
48 }
48 }
49
49
50 PieSliceItem::~PieSliceItem()
50 PieSliceItem::~PieSliceItem()
51 {
51 {
52 // If user is hovering over the slice and it gets destroyed we do
52 // If user is hovering over the slice and it gets destroyed we do
53 // not get a hover leave event. So we must emit the signal here.
53 // not get a hover leave event. So we must emit the signal here.
54 if (m_hovered)
54 if (m_hovered)
55 emit hovered(false);
55 emit hovered(false);
56 }
56 }
57
57
58 QRectF PieSliceItem::boundingRect() const
58 QRectF PieSliceItem::boundingRect() const
59 {
59 {
60 return m_boundingRect;
60 return m_boundingRect;
61 }
61 }
62
62
63 QPainterPath PieSliceItem::shape() const
63 QPainterPath PieSliceItem::shape() const
64 {
64 {
65 // Don't include the label and label arm.
65 // Don't include the label and label arm.
66 // This is used to detect a mouse clicks. We do not want clicks from label.
66 // This is used to detect a mouse clicks. We do not want clicks from label.
67 return m_slicePath;
67 return m_slicePath;
68 }
68 }
69
69
70 void PieSliceItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
70 void PieSliceItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
71 {
71 {
72 painter->save();
72 painter->save();
73 painter->setClipRect(parentItem()->boundingRect());
73 painter->setClipRect(parentItem()->boundingRect());
74 painter->setPen(m_data.m_slicePen);
74 painter->setPen(m_data.m_slicePen);
75 painter->setBrush(m_data.m_sliceBrush);
75 painter->setBrush(m_data.m_sliceBrush);
76 painter->drawPath(m_slicePath);
76 painter->drawPath(m_slicePath);
77 painter->restore();
77 painter->restore();
78
78
79 if (m_data.m_isLabelVisible) {
79 if (m_data.m_isLabelVisible) {
80 painter->save();
80 painter->save();
81
81
82 // Pen for label arm not defined in the QPieSeries api, let's use brush's color instead
82 // Pen for label arm not defined in the QPieSeries api, let's use brush's color instead
83 // Also, the drawText actually uses the pen color for the text color (unlike QGraphicsSimpleTextItem)
83 // Also, the drawText actually uses the pen color for the text color (unlike QGraphicsSimpleTextItem)
84 painter->setPen(m_data.m_labelBrush.color());
84 painter->setPen(m_data.m_labelBrush.color());
85 painter->setBrush(m_data.m_labelBrush);
85 painter->setBrush(m_data.m_labelBrush);
86 painter->setFont(m_data.m_labelFont);
86 painter->setFont(m_data.m_labelFont);
87 if (m_data.m_labelPosition == QPieSlice::LabelOutside) {
87 if (m_data.m_labelPosition == QPieSlice::LabelOutside) {
88 painter->setClipRect(parentItem()->boundingRect());
88 painter->setClipRect(parentItem()->boundingRect());
89 painter->strokePath(m_labelArmPath, m_data.m_labelBrush.color());
89 painter->strokePath(m_labelArmPath, m_data.m_labelBrush.color());
90 } else { // QPieSlice::LabelInside
90 } else { // QPieSlice::LabelInside
91 painter->setClipPath(m_slicePath);
91 painter->setClipPath(m_slicePath);
92 }
92 }
93 painter->drawText(m_labelTextRect, Qt::AlignCenter, m_data.m_labelText);
93 painter->drawText(m_labelTextRect, Qt::AlignCenter, m_data.m_labelText);
94
94
95 painter->restore();
95 painter->restore();
96 }
96 }
97 }
97 }
98
98
99 void PieSliceItem::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
99 void PieSliceItem::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
100 {
100 {
101 m_hovered = true;
101 m_hovered = true;
102 emit hovered(true);
102 emit hovered(true);
103 }
103 }
104
104
105 void PieSliceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
105 void PieSliceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
106 {
106 {
107 m_hovered = false;
107 m_hovered = false;
108 emit hovered(false);
108 emit hovered(false);
109 }
109 }
110
110
111 void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
111 void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
112 {
112 {
113 emit clicked(event->buttons());
113 emit clicked(event->buttons());
114 }
114 }
115
115
116 void PieSliceItem::setLayout(const PieSliceData &sliceData)
116 void PieSliceItem::setLayout(const PieSliceData &sliceData)
117 {
117 {
118 m_data = sliceData;
118 m_data = sliceData;
119 updateGeometry();
119 updateGeometry();
120 update();
120 update();
121 }
121 }
122
122
123 void PieSliceItem::updateGeometry()
123 void PieSliceItem::updateGeometry()
124 {
124 {
125 if (m_data.m_radius <= 0)
125 if (m_data.m_radius <= 0)
126 return;
126 return;
127
127
128 prepareGeometryChange();
128 prepareGeometryChange();
129
129
130 // slice path
130 // slice path
131 qreal centerAngle;
131 qreal centerAngle;
132 QPointF armStart;
132 QPointF armStart;
133 m_slicePath = slicePath(m_data.m_center, m_data.m_radius, m_data.m_startAngle, m_data.m_angleSpan, &centerAngle, &armStart);
133 m_slicePath = slicePath(m_data.m_center, m_data.m_radius, m_data.m_startAngle, m_data.m_angleSpan, &centerAngle, &armStart);
134
134
135 // text rect
135 // text rect
136 QFontMetricsF fm(m_data.m_labelFont);
136 QFontMetricsF fm(m_data.m_labelFont);
137 m_labelTextRect = QRectF(0, 0, fm.width(m_data.m_labelText), fm.height());
137 m_labelTextRect = QRectF(0, 0, fm.width(m_data.m_labelText), fm.height());
138
138
139 // label arm path
139 // label arm path
140 QPointF labelTextStart;
140 QPointF labelTextStart;
141 m_labelArmPath = labelArmPath(armStart, centerAngle, m_data.m_radius * m_data.m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
141 m_labelArmPath = labelArmPath(armStart, centerAngle, m_data.m_radius * m_data.m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
142
142
143 // text position
143 // text position
144 if (m_data.m_labelPosition == QPieSlice::LabelOutside)
144 if (m_data.m_labelPosition == QPieSlice::LabelOutside)
145 m_labelTextRect.moveBottomLeft(labelTextStart);
145 m_labelTextRect.moveBottomLeft(labelTextStart);
146 else {// QPieSlice::LabelInside
146 else {// QPieSlice::LabelInside
147 QPointF sliceCenter = m_data.m_center + offset(centerAngle, m_data.m_radius / 2);
147 QPointF sliceCenter = m_data.m_center + offset(centerAngle, m_data.m_radius / 2);
148 m_labelTextRect.moveCenter(sliceCenter);
148 m_labelTextRect.moveCenter(sliceCenter);
149 }
149 }
150
150
151 // bounding rect
151 // bounding rect
152 if (m_data.m_isLabelVisible)
152 if (m_data.m_isLabelVisible)
153 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
153 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
154 else
154 else
155 m_boundingRect = m_slicePath.boundingRect();
155 m_boundingRect = m_slicePath.boundingRect();
156 }
156 }
157
157
158 QPointF PieSliceItem::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
158 QPointF PieSliceItem::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
159 {
159 {
160 if (slice->isExploded()) {
160 if (slice->isExploded()) {
161 qreal centerAngle = slice->startAngle() + (slice->angleSpan()/2);
161 qreal centerAngle = slice->startAngle() + (slice->angleSpan()/2);
162 qreal len = radius * slice->explodeDistanceFactor();
162 qreal len = radius * slice->explodeDistanceFactor();
163 point += offset(centerAngle, len);
163 point += offset(centerAngle, len);
164 }
164 }
165 return point;
165 return point;
166 }
166 }
167
167
168 QPainterPath PieSliceItem::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF* armStart)
168 QPainterPath PieSliceItem::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF* armStart)
169 {
169 {
170 // calculate center angle
170 // calculate center angle
171 *centerAngle = startAngle + (angleSpan/2);
171 *centerAngle = startAngle + (angleSpan/2);
172
172
173 // calculate slice rectangle
173 // calculate slice rectangle
174 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
174 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
175
175
176 // slice path
176 // slice path
177 QPainterPath path;
177 QPainterPath path;
178 if (m_data.m_donut) {
178 if (m_data.m_donut) {
179 qreal donutFraction = 5.0;
179 QRectF insideRect(center.x() - m_data.m_innerRadius, center.y()-m_data.m_innerRadius, m_data.m_innerRadius*2, m_data.m_innerRadius*2);
180 QRectF insideRect = rect.adjusted(rect.width() / donutFraction, rect.height() / donutFraction, -rect.width() / donutFraction, -rect.height() / donutFraction);
181 path.arcMoveTo(rect, -startAngle + 90);
180 path.arcMoveTo(rect, -startAngle + 90);
182 path.arcTo(rect, -startAngle + 90, -angleSpan);
181 path.arcTo(rect, -startAngle + 90, -angleSpan);
183 path.arcTo(insideRect, -startAngle + 90 - angleSpan, angleSpan);
182 path.arcTo(insideRect, -startAngle + 90 - angleSpan, angleSpan);
184 path.closeSubpath();
183 path.closeSubpath();
185 } else {
184 } else {
186 path.moveTo(rect.center());
185 path.moveTo(rect.center());
187 path.arcTo(rect, -startAngle + 90, -angleSpan);
186 path.arcTo(rect, -startAngle + 90, -angleSpan);
188 path.closeSubpath();
187 path.closeSubpath();
189 }
188 }
190
189
191 // calculate label arm start point
190 // calculate label arm start point
192 *armStart = center;
191 *armStart = center;
193 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
192 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
194
193
195 return path;
194 return path;
196 }
195 }
197
196
198 QPainterPath PieSliceItem::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart)
197 QPainterPath PieSliceItem::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart)
199 {
198 {
200 // Normalize the angle to 0-360 range
199 // Normalize the angle to 0-360 range
201 // NOTE: We are using int here on purpose. Depenging on platform and hardware
200 // NOTE: We are using int here on purpose. Depenging on platform and hardware
202 // qreal can be a double, float or something the user gives to the Qt configure
201 // qreal can be a double, float or something the user gives to the Qt configure
203 // (QT_COORD_TYPE). Compilers do not seem to support modulo for double or float
202 // (QT_COORD_TYPE). Compilers do not seem to support modulo for double or float
204 // but there are fmod() and fmodf() functions for that. So instead of some #ifdef
203 // but there are fmod() and fmodf() functions for that. So instead of some #ifdef
205 // that might break we just use int. Precision for this is just fine for our needs.
204 // that might break we just use int. Precision for this is just fine for our needs.
206 int normalized = angle * 10.0;
205 int normalized = angle * 10.0;
207 normalized = normalized % 3600;
206 normalized = normalized % 3600;
208 if (normalized < 0)
207 if (normalized < 0)
209 normalized += 3600;
208 normalized += 3600;
210 angle = (qreal) normalized / 10.0;
209 angle = (qreal) normalized / 10.0;
211
210
212 // prevent label arm pointing straight down because it will look bad
211 // prevent label arm pointing straight down because it will look bad
213 if (angle < 180 && angle > 170)
212 if (angle < 180 && angle > 170)
214 angle = 170;
213 angle = 170;
215 if (angle > 180 && angle < 190)
214 if (angle > 180 && angle < 190)
216 angle = 190;
215 angle = 190;
217
216
218 // line from slice to label
217 // line from slice to label
219 QPointF parm1 = start + offset(angle, length);
218 QPointF parm1 = start + offset(angle, length);
220
219
221 // line to underline the label
220 // line to underline the label
222 QPointF parm2 = parm1;
221 QPointF parm2 = parm1;
223 if (angle < 180) { // arm swings the other way on the left side
222 if (angle < 180) { // arm swings the other way on the left side
224 parm2 += QPointF(textWidth, 0);
223 parm2 += QPointF(textWidth, 0);
225 *textStart = parm1;
224 *textStart = parm1;
226 }
225 }
227 else {
226 else {
228 parm2 += QPointF(-textWidth,0);
227 parm2 += QPointF(-textWidth,0);
229 *textStart = parm2;
228 *textStart = parm2;
230 }
229 }
231
230
232 QPainterPath path;
231 QPainterPath path;
233 path.moveTo(start);
232 path.moveTo(start);
234 path.lineTo(parm1);
233 path.lineTo(parm1);
235 path.lineTo(parm2);
234 path.lineTo(parm2);
236
235
237 return path;
236 return path;
238 }
237 }
239
238
240 #include "moc_piesliceitem_p.cpp"
239 #include "moc_piesliceitem_p.cpp"
241
240
242 QTCOMMERCIALCHART_END_NAMESPACE
241 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,567 +1,568
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qpiemodelmapper_p.h"
21 #include "qpiemodelmapper_p.h"
22 #include "qpiemodelmapper.h"
22 #include "qpiemodelmapper.h"
23 #include "qpieseries.h"
23 #include "qpieseries.h"
24 #include "qpieslice.h"
24 #include "qpieslice.h"
25 #include <QAbstractItemModel>
25 #include <QAbstractItemModel>
26
26
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28
28
29 QPieModelMapper::QPieModelMapper(QObject *parent) :
29 QPieModelMapper::QPieModelMapper(QObject *parent) :
30 QObject(parent),
30 QObject(parent),
31 d_ptr(new QPieModelMapperPrivate(this))
31 d_ptr(new QPieModelMapperPrivate(this))
32 {
32 {
33 }
33 }
34
34
35 QAbstractItemModel* QPieModelMapper::model() const
35 QAbstractItemModel* QPieModelMapper::model() const
36 {
36 {
37 Q_D(const QPieModelMapper);
37 Q_D(const QPieModelMapper);
38 return d->m_model;
38 return d->m_model;
39 }
39 }
40
40
41 void QPieModelMapper::setModel(QAbstractItemModel *model)
41 void QPieModelMapper::setModel(QAbstractItemModel *model)
42 {
42 {
43 if (model == 0)
43 if (model == 0)
44 return;
44 return;
45
45
46 Q_D(QPieModelMapper);
46 Q_D(QPieModelMapper);
47 if (d->m_model) {
47 if (d->m_model) {
48 disconnect(d->m_model, 0, d, 0);
48 disconnect(d->m_model, 0, d, 0);
49 }
49 }
50
50
51 d->m_model = model;
51 d->m_model = model;
52 d->initializePieFromModel();
52 d->initializePieFromModel();
53 // connect signals from the model
53 // connect signals from the model
54 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
54 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
55 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
55 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
56 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
56 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
57 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
57 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
58 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
58 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
59 connect(d->m_model, SIGNAL(destroyed()), d, SLOT(handleModelDestroyed()));
59 connect(d->m_model, SIGNAL(destroyed()), d, SLOT(handleModelDestroyed()));
60 }
60 }
61
61
62 QPieSeries* QPieModelMapper::series() const
62 QPieSeries* QPieModelMapper::series() const
63 {
63 {
64 Q_D(const QPieModelMapper);
64 Q_D(const QPieModelMapper);
65 return d->m_series;
65 return d->m_series;
66 }
66 }
67
67
68 void QPieModelMapper::setSeries(QPieSeries *series)
68 void QPieModelMapper::setSeries(QPieSeries *series)
69 {
69 {
70 Q_D(QPieModelMapper);
70 Q_D(QPieModelMapper);
71 if (d->m_series) {
71 if (d->m_series) {
72 disconnect(d->m_series, 0, d, 0);
72 disconnect(d->m_series, 0, d, 0);
73 }
73 }
74
74
75 if (series == 0)
75 if (series == 0)
76 return;
76 return;
77
77
78 d->m_series = series;
78 d->m_series = series;
79 d->initializePieFromModel();
79 d->initializePieFromModel();
80 // connect the signals from the series
80 // connect the signals from the series
81 connect(d->m_series, SIGNAL(added(QList<QPieSlice*>)), d, SLOT(slicesAdded(QList<QPieSlice*>)));
81 connect(d->m_series, SIGNAL(added(QList<QPieSlice*>)), d, SLOT(slicesAdded(QList<QPieSlice*>)));
82 connect(d->m_series, SIGNAL(removed(QList<QPieSlice*>)), d, SLOT(slicesRemoved(QList<QPieSlice*>)));
82 connect(d->m_series, SIGNAL(removed(QList<QPieSlice*>)), d, SLOT(slicesRemoved(QList<QPieSlice*>)));
83 connect(d->m_series, SIGNAL(destroyed()), d, SLOT(handleSeriesDestroyed()));
83 connect(d->m_series, SIGNAL(destroyed()), d, SLOT(handleSeriesDestroyed()));
84 }
84 }
85
85
86 /*!
86 /*!
87 Defines which row/column of the model contains the first slice value.
87 Defines which row/column of the model contains the first slice value.
88 Minimal and default value is: 0
88 Minimal and default value is: 0
89 */
89 */
90 int QPieModelMapper::first() const
90 int QPieModelMapper::first() const
91 {
91 {
92 Q_D(const QPieModelMapper);
92 Q_D(const QPieModelMapper);
93 return d->m_first;
93 return d->m_first;
94 }
94 }
95
95
96 /*!
96 /*!
97 Sets which row/column of the model contains the \a first slice value.
97 Sets which row/column of the model contains the \a first slice value.
98 Minimal and default value is: 0
98 Minimal and default value is: 0
99 */
99 */
100 void QPieModelMapper::setFirst(int first)
100 void QPieModelMapper::setFirst(int first)
101 {
101 {
102 Q_D(QPieModelMapper);
102 Q_D(QPieModelMapper);
103 d->m_first = qMax(first, 0);
103 d->m_first = qMax(first, 0);
104 d->initializePieFromModel();
104 d->initializePieFromModel();
105 }
105 }
106
106
107 /*!
107 /*!
108 Defines the number of rows/columns of the model that are mapped as the data for QPieSeries
108 Defines the number of rows/columns of the model that are mapped as the data for QPieSeries
109 Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
109 Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
110 */
110 */
111 int QPieModelMapper::count() const
111 int QPieModelMapper::count() const
112 {
112 {
113 Q_D(const QPieModelMapper);
113 Q_D(const QPieModelMapper);
114 return d->m_count;
114 return d->m_count;
115 }
115 }
116
116
117 /*!
117 /*!
118 Defines the \a count of rows/columns of the model that are mapped as the data for QPieSeries
118 Defines the \a count of rows/columns of the model that are mapped as the data for QPieSeries
119 Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
119 Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
120 */
120 */
121 void QPieModelMapper::setCount(int count)
121 void QPieModelMapper::setCount(int count)
122 {
122 {
123 Q_D(QPieModelMapper);
123 Q_D(QPieModelMapper);
124 d->m_count = qMax(count, -1);
124 d->m_count = qMax(count, -1);
125 d->initializePieFromModel();
125 d->initializePieFromModel();
126 }
126 }
127
127
128 /*!
128 /*!
129 Returns the orientation that is used when QPieModelMapper accesses the model.
129 Returns the orientation that is used when QPieModelMapper accesses the model.
130 This mean whether the consecutive values/labels of the pie are read from row (Qt::Horizontal)
130 This mean whether the consecutive values/labels of the pie are read from row (Qt::Horizontal)
131 or from columns (Qt::Vertical)
131 or from columns (Qt::Vertical)
132 */
132 */
133 Qt::Orientation QPieModelMapper::orientation() const
133 Qt::Orientation QPieModelMapper::orientation() const
134 {
134 {
135 Q_D(const QPieModelMapper);
135 Q_D(const QPieModelMapper);
136 return d->m_orientation;
136 return d->m_orientation;
137 }
137 }
138
138
139 /*!
139 /*!
140 Returns the \a orientation that is used when QPieModelMapper accesses the model.
140 Returns the \a orientation that is used when QPieModelMapper accesses the model.
141 This mean whether the consecutive values/labels of the pie are read from row (Qt::Horizontal)
141 This mean whether the consecutive values/labels of the pie are read from row (Qt::Horizontal)
142 or from columns (Qt::Vertical)
142 or from columns (Qt::Vertical)
143 */
143 */
144 void QPieModelMapper::setOrientation(Qt::Orientation orientation)
144 void QPieModelMapper::setOrientation(Qt::Orientation orientation)
145 {
145 {
146 Q_D(QPieModelMapper);
146 Q_D(QPieModelMapper);
147 d->m_orientation = orientation;
147 d->m_orientation = orientation;
148 d->initializePieFromModel();
148 d->initializePieFromModel();
149 }
149 }
150
150
151 /*!
151 /*!
152 Returns which section of the model is kept in sync with the values of the pie's slices
152 Returns which section of the model is kept in sync with the values of the pie's slices
153 */
153 */
154 int QPieModelMapper::valuesSection() const
154 int QPieModelMapper::valuesSection() const
155 {
155 {
156 Q_D(const QPieModelMapper);
156 Q_D(const QPieModelMapper);
157 return d->m_valuesSection;
157 return d->m_valuesSection;
158 }
158 }
159
159
160 /*!
160 /*!
161 Sets the model section that is kept in sync with the pie slices values.
161 Sets the model section that is kept in sync with the pie slices values.
162 Parameter \a valuesSection specifies the section of the model.
162 Parameter \a valuesSection specifies the section of the model.
163 */
163 */
164 void QPieModelMapper::setValuesSection(int valuesSection)
164 void QPieModelMapper::setValuesSection(int valuesSection)
165 {
165 {
166 Q_D(QPieModelMapper);
166 Q_D(QPieModelMapper);
167 d->m_valuesSection = qMax(-1, valuesSection);
167 d->m_valuesSection = qMax(-1, valuesSection);
168 d->initializePieFromModel();
168 d->initializePieFromModel();
169 }
169 }
170
170
171 /*!
171 /*!
172 Returns which section of the model is kept in sync with the labels of the pie's slices
172 Returns which section of the model is kept in sync with the labels of the pie's slices
173 */
173 */
174 int QPieModelMapper::labelsSection() const
174 int QPieModelMapper::labelsSection() const
175 {
175 {
176 Q_D(const QPieModelMapper);
176 Q_D(const QPieModelMapper);
177 return d->m_labelsSection;
177 return d->m_labelsSection;
178 }
178 }
179
179
180 /*!
180 /*!
181 Sets the model section that is kept in sync with the pie slices labels.
181 Sets the model section that is kept in sync with the pie slices labels.
182 Parameter \a labelsSection specifies the section of the model.
182 Parameter \a labelsSection specifies the section of the model.
183 */
183 */
184 void QPieModelMapper::setLabelsSection(int labelsSection)
184 void QPieModelMapper::setLabelsSection(int labelsSection)
185 {
185 {
186 Q_D(QPieModelMapper);
186 Q_D(QPieModelMapper);
187 d->m_labelsSection = qMax(-1, labelsSection);
187 d->m_labelsSection = qMax(-1, labelsSection);
188 d->initializePieFromModel();
188 d->initializePieFromModel();
189 }
189 }
190
190
191 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
191 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
192
192
193 QPieModelMapperPrivate::QPieModelMapperPrivate(QPieModelMapper *q) :
193 QPieModelMapperPrivate::QPieModelMapperPrivate(QPieModelMapper *q) :
194 QObject(q),
194 m_series(0),
195 m_series(0),
195 m_model(0),
196 m_model(0),
196 m_first(0),
197 m_first(0),
197 m_count(-1),
198 m_count(-1),
198 m_orientation(Qt::Vertical),
199 m_orientation(Qt::Vertical),
199 m_valuesSection(-1),
200 m_valuesSection(-1),
200 m_labelsSection(-1),
201 m_labelsSection(-1),
201 m_seriesSignalsBlock(false),
202 m_seriesSignalsBlock(false),
202 m_modelSignalsBlock(false),
203 m_modelSignalsBlock(false),
203 q_ptr(q)
204 q_ptr(q)
204 {
205 {
205 }
206 }
206
207
207 void QPieModelMapperPrivate::blockModelSignals(bool block)
208 void QPieModelMapperPrivate::blockModelSignals(bool block)
208 {
209 {
209 m_modelSignalsBlock = block;
210 m_modelSignalsBlock = block;
210 }
211 }
211
212
212 void QPieModelMapperPrivate::blockSeriesSignals(bool block)
213 void QPieModelMapperPrivate::blockSeriesSignals(bool block)
213 {
214 {
214 m_seriesSignalsBlock = block;
215 m_seriesSignalsBlock = block;
215 }
216 }
216
217
217
218
218 QPieSlice* QPieModelMapperPrivate::pieSlice(QModelIndex index) const
219 QPieSlice* QPieModelMapperPrivate::pieSlice(QModelIndex index) const
219 {
220 {
220 if (!index.isValid())
221 if (!index.isValid())
221 return 0; // index is invalid
222 return 0; // index is invalid
222
223
223 if (m_orientation == Qt::Vertical && (index.column() == m_valuesSection || index.column() == m_labelsSection)) {
224 if (m_orientation == Qt::Vertical && (index.column() == m_valuesSection || index.column() == m_labelsSection)) {
224 if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
225 if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
225 if (m_model->index(index.row(), m_valuesSection).isValid() && m_model->index(index.row(), m_labelsSection).isValid())
226 if (m_model->index(index.row(), m_valuesSection).isValid() && m_model->index(index.row(), m_labelsSection).isValid())
226 return m_series->slices().at(index.row() - m_first);
227 return m_series->slices().at(index.row() - m_first);
227 else
228 else
228 return 0;
229 return 0;
229 }
230 }
230 } else if (m_orientation == Qt::Horizontal && (index.row() == m_valuesSection || index.row() == m_labelsSection)) {
231 } else if (m_orientation == Qt::Horizontal && (index.row() == m_valuesSection || index.row() == m_labelsSection)) {
231 if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count)) {
232 if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count)) {
232 if (m_model->index(m_valuesSection, index.column()).isValid() && m_model->index(m_labelsSection, index.column()).isValid())
233 if (m_model->index(m_valuesSection, index.column()).isValid() && m_model->index(m_labelsSection, index.column()).isValid())
233 return m_series->slices().at(index.column() - m_first);
234 return m_series->slices().at(index.column() - m_first);
234 else
235 else
235 return 0;
236 return 0;
236 }
237 }
237 }
238 }
238 return 0; // This part of model has not been mapped to any slice
239 return 0; // This part of model has not been mapped to any slice
239 }
240 }
240
241
241 QModelIndex QPieModelMapperPrivate::valueModelIndex(int slicePos)
242 QModelIndex QPieModelMapperPrivate::valueModelIndex(int slicePos)
242 {
243 {
243 if (m_count != -1 && slicePos >= m_count)
244 if (m_count != -1 && slicePos >= m_count)
244 return QModelIndex(); // invalid
245 return QModelIndex(); // invalid
245
246
246 if (m_orientation == Qt::Vertical)
247 if (m_orientation == Qt::Vertical)
247 return m_model->index(slicePos + m_first, m_valuesSection);
248 return m_model->index(slicePos + m_first, m_valuesSection);
248 else
249 else
249 return m_model->index(m_valuesSection, slicePos + m_first);
250 return m_model->index(m_valuesSection, slicePos + m_first);
250 }
251 }
251
252
252 QModelIndex QPieModelMapperPrivate::labelModelIndex(int slicePos)
253 QModelIndex QPieModelMapperPrivate::labelModelIndex(int slicePos)
253 {
254 {
254 if (m_count != -1 && slicePos >= m_count)
255 if (m_count != -1 && slicePos >= m_count)
255 return QModelIndex(); // invalid
256 return QModelIndex(); // invalid
256
257
257 if (m_orientation == Qt::Vertical)
258 if (m_orientation == Qt::Vertical)
258 return m_model->index(slicePos + m_first, m_labelsSection);
259 return m_model->index(slicePos + m_first, m_labelsSection);
259 else
260 else
260 return m_model->index(m_labelsSection, slicePos + m_first);
261 return m_model->index(m_labelsSection, slicePos + m_first);
261 }
262 }
262
263
263 bool QPieModelMapperPrivate::isLabelIndex(QModelIndex index) const
264 bool QPieModelMapperPrivate::isLabelIndex(QModelIndex index) const
264 {
265 {
265 if (m_orientation == Qt::Vertical && index.column() == m_labelsSection)
266 if (m_orientation == Qt::Vertical && index.column() == m_labelsSection)
266 return true;
267 return true;
267 else if (m_orientation == Qt::Horizontal && index.row() == m_labelsSection)
268 else if (m_orientation == Qt::Horizontal && index.row() == m_labelsSection)
268 return true;
269 return true;
269
270
270 return false;
271 return false;
271 }
272 }
272
273
273 bool QPieModelMapperPrivate::isValueIndex(QModelIndex index) const
274 bool QPieModelMapperPrivate::isValueIndex(QModelIndex index) const
274 {
275 {
275 if (m_orientation == Qt::Vertical && index.column() == m_valuesSection)
276 if (m_orientation == Qt::Vertical && index.column() == m_valuesSection)
276 return true;
277 return true;
277 else if (m_orientation == Qt::Horizontal && index.row() == m_valuesSection)
278 else if (m_orientation == Qt::Horizontal && index.row() == m_valuesSection)
278 return true;
279 return true;
279
280
280 return false;
281 return false;
281 }
282 }
282
283
283 void QPieModelMapperPrivate::slicesAdded(QList<QPieSlice*> slices)
284 void QPieModelMapperPrivate::slicesAdded(QList<QPieSlice*> slices)
284 {
285 {
285 if (m_seriesSignalsBlock)
286 if (m_seriesSignalsBlock)
286 return;
287 return;
287
288
288 if (slices.count() == 0)
289 if (slices.count() == 0)
289 return;
290 return;
290
291
291 int firstIndex = m_series->slices().indexOf(slices.at(0));
292 int firstIndex = m_series->slices().indexOf(slices.at(0));
292 if (firstIndex == -1)
293 if (firstIndex == -1)
293 return;
294 return;
294
295
295 if (m_count != -1)
296 if (m_count != -1)
296 m_count += slices.count();
297 m_count += slices.count();
297
298
298 for (int i = firstIndex; i < firstIndex + slices.count(); i++) {
299 for (int i = firstIndex; i < firstIndex + slices.count(); i++) {
299 m_slices.insert(i, slices.at(i - firstIndex));
300 m_slices.insert(i, slices.at(i - firstIndex));
300 connect(slices.at(i - firstIndex), SIGNAL(labelChanged()), this, SLOT(sliceLabelChanged()));
301 connect(slices.at(i - firstIndex), SIGNAL(labelChanged()), this, SLOT(sliceLabelChanged()));
301 connect(slices.at(i - firstIndex), SIGNAL(valueChanged()), this, SLOT(sliceValueChanged()));
302 connect(slices.at(i - firstIndex), SIGNAL(valueChanged()), this, SLOT(sliceValueChanged()));
302 }
303 }
303
304
304 blockModelSignals();
305 blockModelSignals();
305 if (m_orientation == Qt::Vertical)
306 if (m_orientation == Qt::Vertical)
306 m_model->insertRows(firstIndex + m_first, slices.count());
307 m_model->insertRows(firstIndex + m_first, slices.count());
307 else
308 else
308 m_model->insertColumns(firstIndex + m_first, slices.count());
309 m_model->insertColumns(firstIndex + m_first, slices.count());
309
310
310 for(int i = firstIndex; i < firstIndex + slices.count(); i++) {
311 for(int i = firstIndex; i < firstIndex + slices.count(); i++) {
311 m_model->setData(valueModelIndex(i), slices.at(i - firstIndex)->value());
312 m_model->setData(valueModelIndex(i), slices.at(i - firstIndex)->value());
312 m_model->setData(labelModelIndex(i), slices.at(i - firstIndex)->label());
313 m_model->setData(labelModelIndex(i), slices.at(i - firstIndex)->label());
313 }
314 }
314 blockModelSignals(false);
315 blockModelSignals(false);
315 }
316 }
316
317
317 void QPieModelMapperPrivate::slicesRemoved(QList<QPieSlice*> slices)
318 void QPieModelMapperPrivate::slicesRemoved(QList<QPieSlice*> slices)
318 {
319 {
319 if (m_seriesSignalsBlock)
320 if (m_seriesSignalsBlock)
320 return;
321 return;
321
322
322 if (slices.count() == 0)
323 if (slices.count() == 0)
323 return;
324 return;
324
325
325 int firstIndex = m_slices.indexOf(slices.at(0));
326 int firstIndex = m_slices.indexOf(slices.at(0));
326 if (firstIndex == -1)
327 if (firstIndex == -1)
327 return;
328 return;
328
329
329 if (m_count != -1)
330 if (m_count != -1)
330 m_count -= slices.count();
331 m_count -= slices.count();
331
332
332 for (int i = firstIndex + slices.count() - 1; i >= firstIndex; i--)
333 for (int i = firstIndex + slices.count() - 1; i >= firstIndex; i--)
333 m_slices.removeAt(i);
334 m_slices.removeAt(i);
334
335
335 blockModelSignals();
336 blockModelSignals();
336 if (m_orientation == Qt::Vertical)
337 if (m_orientation == Qt::Vertical)
337 m_model->removeRows(firstIndex + m_first, slices.count());
338 m_model->removeRows(firstIndex + m_first, slices.count());
338 else
339 else
339 m_model->removeColumns(firstIndex + m_first, slices.count());
340 m_model->removeColumns(firstIndex + m_first, slices.count());
340 blockModelSignals(false);
341 blockModelSignals(false);
341 }
342 }
342
343
343 void QPieModelMapperPrivate::sliceLabelChanged()
344 void QPieModelMapperPrivate::sliceLabelChanged()
344 {
345 {
345 if (m_seriesSignalsBlock)
346 if (m_seriesSignalsBlock)
346 return;
347 return;
347
348
348 blockModelSignals();
349 blockModelSignals();
349 QPieSlice *slice = qobject_cast<QPieSlice *>(QObject::sender());
350 QPieSlice *slice = qobject_cast<QPieSlice *>(QObject::sender());
350 m_model->setData(labelModelIndex(m_series->slices().indexOf(slice)), slice->label());
351 m_model->setData(labelModelIndex(m_series->slices().indexOf(slice)), slice->label());
351 blockModelSignals(false);
352 blockModelSignals(false);
352 }
353 }
353
354
354 void QPieModelMapperPrivate::sliceValueChanged()
355 void QPieModelMapperPrivate::sliceValueChanged()
355 {
356 {
356 if (m_seriesSignalsBlock)
357 if (m_seriesSignalsBlock)
357 return;
358 return;
358
359
359 blockModelSignals();
360 blockModelSignals();
360 QPieSlice *slice = qobject_cast<QPieSlice *>(QObject::sender());
361 QPieSlice *slice = qobject_cast<QPieSlice *>(QObject::sender());
361 m_model->setData(valueModelIndex(m_series->slices().indexOf(slice)), slice->value());
362 m_model->setData(valueModelIndex(m_series->slices().indexOf(slice)), slice->value());
362 blockModelSignals(false);
363 blockModelSignals(false);
363 }
364 }
364
365
365 void QPieModelMapperPrivate::handleSeriesDestroyed()
366 void QPieModelMapperPrivate::handleSeriesDestroyed()
366 {
367 {
367 m_series = 0;
368 m_series = 0;
368 }
369 }
369
370
370 void QPieModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
371 void QPieModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
371 {
372 {
372 if (m_model == 0 || m_series == 0)
373 if (m_model == 0 || m_series == 0)
373 return;
374 return;
374
375
375 if (m_modelSignalsBlock)
376 if (m_modelSignalsBlock)
376 return;
377 return;
377
378
378 blockSeriesSignals();
379 blockSeriesSignals();
379 QModelIndex index;
380 QModelIndex index;
380 QPieSlice *slice;
381 QPieSlice *slice;
381 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
382 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
382 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
383 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
383 index = topLeft.sibling(row, column);
384 index = topLeft.sibling(row, column);
384 slice = pieSlice(index);
385 slice = pieSlice(index);
385 if (slice) {
386 if (slice) {
386 if (isValueIndex(index))
387 if (isValueIndex(index))
387 slice->setValue(m_model->data(index, Qt::DisplayRole).toReal());
388 slice->setValue(m_model->data(index, Qt::DisplayRole).toReal());
388 if (isLabelIndex(index))
389 if (isLabelIndex(index))
389 slice->setLabel(m_model->data(index, Qt::DisplayRole).toString());
390 slice->setLabel(m_model->data(index, Qt::DisplayRole).toString());
390 }
391 }
391 }
392 }
392 }
393 }
393 blockSeriesSignals(false);
394 blockSeriesSignals(false);
394 }
395 }
395
396
396
397
397 void QPieModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
398 void QPieModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
398 {
399 {
399 Q_UNUSED(parent);
400 Q_UNUSED(parent);
400 if (m_modelSignalsBlock)
401 if (m_modelSignalsBlock)
401 return;
402 return;
402
403
403 blockSeriesSignals();
404 blockSeriesSignals();
404 if (m_orientation == Qt::Vertical)
405 if (m_orientation == Qt::Vertical)
405 insertData(start, end);
406 insertData(start, end);
406 else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
407 else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
407 initializePieFromModel();
408 initializePieFromModel();
408 blockSeriesSignals(false);
409 blockSeriesSignals(false);
409 }
410 }
410
411
411 void QPieModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
412 void QPieModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
412 {
413 {
413 Q_UNUSED(parent);
414 Q_UNUSED(parent);
414 if (m_modelSignalsBlock)
415 if (m_modelSignalsBlock)
415 return;
416 return;
416
417
417 blockSeriesSignals();
418 blockSeriesSignals();
418 if (m_orientation == Qt::Vertical)
419 if (m_orientation == Qt::Vertical)
419 removeData(start, end);
420 removeData(start, end);
420 else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
421 else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
421 initializePieFromModel();
422 initializePieFromModel();
422 blockSeriesSignals(false);
423 blockSeriesSignals(false);
423 }
424 }
424
425
425 void QPieModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
426 void QPieModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
426 {
427 {
427 Q_UNUSED(parent);
428 Q_UNUSED(parent);
428 if (m_modelSignalsBlock)
429 if (m_modelSignalsBlock)
429 return;
430 return;
430
431
431 blockSeriesSignals();
432 blockSeriesSignals();
432 if (m_orientation == Qt::Horizontal)
433 if (m_orientation == Qt::Horizontal)
433 insertData(start, end);
434 insertData(start, end);
434 else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
435 else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
435 initializePieFromModel();
436 initializePieFromModel();
436 blockSeriesSignals(false);
437 blockSeriesSignals(false);
437 }
438 }
438
439
439 void QPieModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
440 void QPieModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
440 {
441 {
441 Q_UNUSED(parent);
442 Q_UNUSED(parent);
442 if (m_modelSignalsBlock)
443 if (m_modelSignalsBlock)
443 return;
444 return;
444
445
445 blockSeriesSignals();
446 blockSeriesSignals();
446 if (m_orientation == Qt::Horizontal)
447 if (m_orientation == Qt::Horizontal)
447 removeData(start, end);
448 removeData(start, end);
448 else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
449 else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
449 initializePieFromModel();
450 initializePieFromModel();
450 blockSeriesSignals(false);
451 blockSeriesSignals(false);
451 }
452 }
452
453
453 void QPieModelMapperPrivate::handleModelDestroyed()
454 void QPieModelMapperPrivate::handleModelDestroyed()
454 {
455 {
455 m_model = 0;
456 m_model = 0;
456 }
457 }
457
458
458 void QPieModelMapperPrivate::insertData(int start, int end)
459 void QPieModelMapperPrivate::insertData(int start, int end)
459 {
460 {
460 if (m_model == 0 || m_series == 0)
461 if (m_model == 0 || m_series == 0)
461 return;
462 return;
462
463
463 if (m_count != -1 && start >= m_first + m_count) {
464 if (m_count != -1 && start >= m_first + m_count) {
464 return;
465 return;
465 } else {
466 } else {
466 int addedCount = end - start + 1;
467 int addedCount = end - start + 1;
467 if (m_count != -1 && addedCount > m_count)
468 if (m_count != -1 && addedCount > m_count)
468 addedCount = m_count;
469 addedCount = m_count;
469 int first = qMax(start, m_first);
470 int first = qMax(start, m_first);
470 int last = qMin(first + addedCount - 1, m_orientation == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
471 int last = qMin(first + addedCount - 1, m_orientation == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
471 for (int i = first; i <= last; i++) {
472 for (int i = first; i <= last; i++) {
472 QModelIndex valueIndex = valueModelIndex(i - m_first);
473 QModelIndex valueIndex = valueModelIndex(i - m_first);
473 QModelIndex labelIndex = labelModelIndex(i - m_first);
474 QModelIndex labelIndex = labelModelIndex(i - m_first);
474 if (valueIndex.isValid() && labelIndex.isValid()) {
475 if (valueIndex.isValid() && labelIndex.isValid()) {
475 QPieSlice *slice = new QPieSlice;
476 QPieSlice *slice = new QPieSlice;
476 slice->setValue(m_model->data(valueIndex, Qt::DisplayRole).toDouble());
477 slice->setValue(m_model->data(valueIndex, Qt::DisplayRole).toDouble());
477 slice->setLabel(m_model->data(labelIndex, Qt::DisplayRole).toString());
478 slice->setLabel(m_model->data(labelIndex, Qt::DisplayRole).toString());
478 connect(slice, SIGNAL(labelChanged()), this, SLOT(sliceLabelChanged()));
479 connect(slice, SIGNAL(labelChanged()), this, SLOT(sliceLabelChanged()));
479 connect(slice, SIGNAL(valueChanged()), this, SLOT(sliceValueChanged()));
480 connect(slice, SIGNAL(valueChanged()), this, SLOT(sliceValueChanged()));
480 m_series->insert(i - m_first, slice);
481 m_series->insert(i - m_first, slice);
481 m_slices.insert(i - m_first, slice);
482 m_slices.insert(i - m_first, slice);
482 }
483 }
483 }
484 }
484
485
485 // remove excess of slices (abouve m_count)
486 // remove excess of slices (abouve m_count)
486 if (m_count != -1 && m_series->slices().size() > m_count)
487 if (m_count != -1 && m_series->slices().size() > m_count)
487 for (int i = m_series->slices().size() - 1; i >= m_count; i--) {
488 for (int i = m_series->slices().size() - 1; i >= m_count; i--) {
488 m_series->remove(m_series->slices().at(i));
489 m_series->remove(m_series->slices().at(i));
489 m_slices.removeAt(i);
490 m_slices.removeAt(i);
490 }
491 }
491 }
492 }
492 }
493 }
493
494
494 void QPieModelMapperPrivate::removeData(int start, int end)
495 void QPieModelMapperPrivate::removeData(int start, int end)
495 {
496 {
496 if (m_model == 0 || m_series == 0)
497 if (m_model == 0 || m_series == 0)
497 return;
498 return;
498
499
499 int removedCount = end - start + 1;
500 int removedCount = end - start + 1;
500 if (m_count != -1 && start >= m_first + m_count) {
501 if (m_count != -1 && start >= m_first + m_count) {
501 return;
502 return;
502 } else {
503 } else {
503 int toRemove = qMin(m_series->slices().size(), removedCount); // first find how many items can actually be removed
504 int toRemove = qMin(m_series->slices().size(), removedCount); // first find how many items can actually be removed
504 int first = qMax(start, m_first); // get the index of the first item that will be removed.
505 int first = qMax(start, m_first); // get the index of the first item that will be removed.
505 int last = qMin(first + toRemove - 1, m_series->slices().size() + m_first - 1); // get the index of the last item that will be removed.
506 int last = qMin(first + toRemove - 1, m_series->slices().size() + m_first - 1); // get the index of the last item that will be removed.
506 for (int i = last; i >= first; i--) {
507 for (int i = last; i >= first; i--) {
507 m_series->remove(m_series->slices().at(i - m_first));
508 m_series->remove(m_series->slices().at(i - m_first));
508 m_slices.removeAt(i - m_first);
509 m_slices.removeAt(i - m_first);
509 }
510 }
510
511
511 if (m_count != -1) {
512 if (m_count != -1) {
512 int itemsAvailable; // check how many are available to be added
513 int itemsAvailable; // check how many are available to be added
513 if (m_orientation == Qt::Vertical)
514 if (m_orientation == Qt::Vertical)
514 itemsAvailable = m_model->rowCount() - m_first - m_series->slices().size();
515 itemsAvailable = m_model->rowCount() - m_first - m_series->slices().size();
515 else
516 else
516 itemsAvailable = m_model->columnCount() - m_first - m_series->slices().size();
517 itemsAvailable = m_model->columnCount() - m_first - m_series->slices().size();
517 int toBeAdded = qMin(itemsAvailable, m_count - m_series->slices().size()); // add not more items than there is space left to be filled.
518 int toBeAdded = qMin(itemsAvailable, m_count - m_series->slices().size()); // add not more items than there is space left to be filled.
518 int currentSize = m_series->slices().size();
519 int currentSize = m_series->slices().size();
519 if (toBeAdded > 0)
520 if (toBeAdded > 0)
520 for (int i = m_series->slices().size(); i < currentSize + toBeAdded; i++) {
521 for (int i = m_series->slices().size(); i < currentSize + toBeAdded; i++) {
521 QModelIndex valueIndex = valueModelIndex(i - m_first);
522 QModelIndex valueIndex = valueModelIndex(i - m_first);
522 QModelIndex labelIndex = labelModelIndex(i - m_first);
523 QModelIndex labelIndex = labelModelIndex(i - m_first);
523 if (valueIndex.isValid() && labelIndex.isValid()) {
524 if (valueIndex.isValid() && labelIndex.isValid()) {
524 QPieSlice *slice = new QPieSlice;
525 QPieSlice *slice = new QPieSlice;
525 slice->setValue(m_model->data(valueIndex, Qt::DisplayRole).toDouble());
526 slice->setValue(m_model->data(valueIndex, Qt::DisplayRole).toDouble());
526 slice->setLabel(m_model->data(labelIndex, Qt::DisplayRole).toString());
527 slice->setLabel(m_model->data(labelIndex, Qt::DisplayRole).toString());
527 m_series->insert(i, slice);
528 m_series->insert(i, slice);
528 m_slices.insert(i, slice);
529 m_slices.insert(i, slice);
529 }
530 }
530 }
531 }
531 }
532 }
532 }
533 }
533 }
534 }
534
535
535 void QPieModelMapperPrivate::initializePieFromModel()
536 void QPieModelMapperPrivate::initializePieFromModel()
536 {
537 {
537 if (m_model == 0 || m_series == 0)
538 if (m_model == 0 || m_series == 0)
538 return;
539 return;
539
540
540 blockSeriesSignals();
541 blockSeriesSignals();
541 // clear current content
542 // clear current content
542 m_series->clear();
543 m_series->clear();
543 m_slices.clear();
544 m_slices.clear();
544
545
545 // create the initial slices set
546 // create the initial slices set
546 int slicePos = 0;
547 int slicePos = 0;
547 QModelIndex valueIndex = valueModelIndex(slicePos);
548 QModelIndex valueIndex = valueModelIndex(slicePos);
548 QModelIndex labelIndex = labelModelIndex(slicePos);
549 QModelIndex labelIndex = labelModelIndex(slicePos);
549 while (valueIndex.isValid() && labelIndex.isValid()) {
550 while (valueIndex.isValid() && labelIndex.isValid()) {
550 QPieSlice *slice = new QPieSlice;
551 QPieSlice *slice = new QPieSlice;
551 slice->setLabel(m_model->data(labelIndex, Qt::DisplayRole).toString());
552 slice->setLabel(m_model->data(labelIndex, Qt::DisplayRole).toString());
552 slice->setValue(m_model->data(valueIndex, Qt::DisplayRole).toDouble());
553 slice->setValue(m_model->data(valueIndex, Qt::DisplayRole).toDouble());
553 connect(slice, SIGNAL(labelChanged()), this, SLOT(sliceLabelChanged()));
554 connect(slice, SIGNAL(labelChanged()), this, SLOT(sliceLabelChanged()));
554 connect(slice, SIGNAL(valueChanged()), this, SLOT(sliceValueChanged()));
555 connect(slice, SIGNAL(valueChanged()), this, SLOT(sliceValueChanged()));
555 m_series->append(slice);
556 m_series->append(slice);
556 m_slices.append(slice);
557 m_slices.append(slice);
557 slicePos++;
558 slicePos++;
558 valueIndex = valueModelIndex(slicePos);
559 valueIndex = valueModelIndex(slicePos);
559 labelIndex = labelModelIndex(slicePos);
560 labelIndex = labelModelIndex(slicePos);
560 }
561 }
561 blockSeriesSignals(false);
562 blockSeriesSignals(false);
562 }
563 }
563
564
564 #include "moc_qpiemodelmapper_p.cpp"
565 #include "moc_qpiemodelmapper_p.cpp"
565 #include "moc_qpiemodelmapper.cpp"
566 #include "moc_qpiemodelmapper.cpp"
566
567
567 QTCOMMERCIALCHART_END_NAMESPACE
568 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,796 +1,816
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qpieseries.h"
21 #include "qpieseries.h"
22 #include "qpieseries_p.h"
22 #include "qpieseries_p.h"
23 #include "qpieslice.h"
23 #include "qpieslice.h"
24 #include "qpieslice_p.h"
24 #include "qpieslice_p.h"
25 #include "pieslicedata_p.h"
25 #include "pieslicedata_p.h"
26 #include "chartdataset_p.h"
26 #include "chartdataset_p.h"
27 #include "charttheme_p.h"
27 #include "charttheme_p.h"
28 #include "chartanimator_p.h"
28 #include "chartanimator_p.h"
29 #include "legendmarker_p.h"
29 #include "legendmarker_p.h"
30 #include "qabstractaxis.h"
30 #include "qabstractaxis.h"
31
31
32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33
33
34 /*!
34 /*!
35 \class QPieSeries
35 \class QPieSeries
36 \brief Pie series API for QtCommercial Charts
36 \brief Pie series API for QtCommercial Charts
37
37
38 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
38 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
39 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
39 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
40 The actual slice size is determined by that relative value.
40 The actual slice size is determined by that relative value.
41
41
42 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
42 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
43 These relate to the actual chart rectangle.
43 These relate to the actual chart rectangle.
44
44
45 By default the pie is defined as a full pie but it can also be a partial pie.
45 By default the pie is defined as a full pie but it can also be a partial pie.
46 This can be done by setting a starting angle and angle span to the series.
46 This can be done by setting a starting angle and angle span to the series.
47 Full pie is 360 degrees where 0 is at 12 a'clock.
47 Full pie is 360 degrees where 0 is at 12 a'clock.
48
48
49 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
49 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
50 \image examples_piechart.png
50 \image examples_piechart.png
51 */
51 */
52 /*!
52 /*!
53 \qmlclass PieSeries QPieSeries
53 \qmlclass PieSeries QPieSeries
54 \inherits AbstractSeries
54 \inherits AbstractSeries
55
55
56 The following QML shows how to create a simple pie chart.
56 The following QML shows how to create a simple pie chart.
57
57
58 \snippet ../demos/qmlchart/qml/qmlchart/View1.qml 1
58 \snippet ../demos/qmlchart/qml/qmlchart/View1.qml 1
59
59
60 \beginfloatleft
60 \beginfloatleft
61 \image demos_qmlchart1.png
61 \image demos_qmlchart1.png
62 \endfloat
62 \endfloat
63 \clearfloat
63 \clearfloat
64 */
64 */
65
65
66 /*!
66 /*!
67 \property QPieSeries::horizontalPosition
67 \property QPieSeries::horizontalPosition
68 \brief Defines the horizontal position of the pie.
68 \brief Defines the horizontal position of the pie.
69
69
70 The value is a relative value to the chart rectangle where:
70 The value is a relative value to the chart rectangle where:
71
71
72 \list
72 \list
73 \o 0.0 is the absolute left.
73 \o 0.0 is the absolute left.
74 \o 1.0 is the absolute right.
74 \o 1.0 is the absolute right.
75 \endlist
75 \endlist
76 Default value is 0.5 (center).
76 Default value is 0.5 (center).
77 \sa verticalPosition
77 \sa verticalPosition
78 */
78 */
79
79
80 /*!
80 /*!
81 \qmlproperty real PieSeries::horizontalPosition
81 \qmlproperty real PieSeries::horizontalPosition
82
82
83 Defines the horizontal position of the pie.
83 Defines the horizontal position of the pie.
84
84
85 The value is a relative value to the chart rectangle where:
85 The value is a relative value to the chart rectangle where:
86
86
87 \list
87 \list
88 \o 0.0 is the absolute left.
88 \o 0.0 is the absolute left.
89 \o 1.0 is the absolute right.
89 \o 1.0 is the absolute right.
90 \endlist
90 \endlist
91 Default value is 0.5 (center).
91 Default value is 0.5 (center).
92 \sa verticalPosition
92 \sa verticalPosition
93 */
93 */
94
94
95 /*!
95 /*!
96 \property QPieSeries::verticalPosition
96 \property QPieSeries::verticalPosition
97 \brief Defines the vertical position of the pie.
97 \brief Defines the vertical position of the pie.
98
98
99 The value is a relative value to the chart rectangle where:
99 The value is a relative value to the chart rectangle where:
100
100
101 \list
101 \list
102 \o 0.0 is the absolute top.
102 \o 0.0 is the absolute top.
103 \o 1.0 is the absolute bottom.
103 \o 1.0 is the absolute bottom.
104 \endlist
104 \endlist
105 Default value is 0.5 (center).
105 Default value is 0.5 (center).
106 \sa horizontalPosition
106 \sa horizontalPosition
107 */
107 */
108
108
109 /*!
109 /*!
110 \qmlproperty real PieSeries::verticalPosition
110 \qmlproperty real PieSeries::verticalPosition
111
111
112 Defines the vertical position of the pie.
112 Defines the vertical position of the pie.
113
113
114 The value is a relative value to the chart rectangle where:
114 The value is a relative value to the chart rectangle where:
115
115
116 \list
116 \list
117 \o 0.0 is the absolute top.
117 \o 0.0 is the absolute top.
118 \o 1.0 is the absolute bottom.
118 \o 1.0 is the absolute bottom.
119 \endlist
119 \endlist
120 Default value is 0.5 (center).
120 Default value is 0.5 (center).
121 \sa horizontalPosition
121 \sa horizontalPosition
122 */
122 */
123
123
124 /*!
124 /*!
125 \property QPieSeries::size
125 \property QPieSeries::size
126 \brief Defines the pie size.
126 \brief Defines the pie size.
127
127
128 The value is a relative value to the chart rectangle where:
128 The value is a relative value to the chart rectangle where:
129
129
130 \list
130 \list
131 \o 0.0 is the minimum size (pie not drawn).
131 \o 0.0 is the minimum size (pie not drawn).
132 \o 1.0 is the maximum size that can fit the chart.
132 \o 1.0 is the maximum size that can fit the chart.
133 \endlist
133 \endlist
134
134
135 Default value is 0.7.
135 Default value is 0.7.
136 */
136 */
137
137
138 /*!
138 /*!
139 \qmlproperty real PieSeries::size
139 \qmlproperty real PieSeries::size
140
140
141 Defines the pie size.
141 Defines the pie size.
142
142
143 The value is a relative value to the chart rectangle where:
143 The value is a relative value to the chart rectangle where:
144
144
145 \list
145 \list
146 \o 0.0 is the minimum size (pie not drawn).
146 \o 0.0 is the minimum size (pie not drawn).
147 \o 1.0 is the maximum size that can fit the chart.
147 \o 1.0 is the maximum size that can fit the chart.
148 \endlist
148 \endlist
149
149
150 Default value is 0.7.
150 Default value is 0.7.
151 */
151 */
152
152
153 /*!
153 /*!
154 \property QPieSeries::startAngle
154 \property QPieSeries::startAngle
155 \brief Defines the starting angle of the pie.
155 \brief Defines the starting angle of the pie.
156
156
157 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
157 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
158
158
159 Default is value is 0.
159 Default is value is 0.
160 */
160 */
161
161
162 /*!
162 /*!
163 \qmlproperty real PieSeries::startAngle
163 \qmlproperty real PieSeries::startAngle
164
164
165 Defines the starting angle of the pie.
165 Defines the starting angle of the pie.
166
166
167 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
167 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
168
168
169 Default is value is 0.
169 Default is value is 0.
170 */
170 */
171
171
172 /*!
172 /*!
173 \property QPieSeries::endAngle
173 \property QPieSeries::endAngle
174 \brief Defines the ending angle of the pie.
174 \brief Defines the ending angle of the pie.
175
175
176 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
176 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
177
177
178 Default is value is 360.
178 Default is value is 360.
179 */
179 */
180
180
181 /*!
181 /*!
182 \qmlproperty real PieSeries::endAngle
182 \qmlproperty real PieSeries::endAngle
183
183
184 Defines the ending angle of the pie.
184 Defines the ending angle of the pie.
185
185
186 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
186 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
187
187
188 Default is value is 360.
188 Default is value is 360.
189 */
189 */
190
190
191 /*!
191 /*!
192 \property QPieSeries::count
192 \property QPieSeries::count
193
193
194 Number of slices in the series.
194 Number of slices in the series.
195 */
195 */
196
196
197 /*!
197 /*!
198 \qmlproperty int PieSeries::count
198 \qmlproperty int PieSeries::count
199
199
200 Number of slices in the series.
200 Number of slices in the series.
201 */
201 */
202
202
203 /*!
203 /*!
204 \fn void QPieSeries::countChanged()
204 \fn void QPieSeries::countChanged()
205 Emitted when the slice count has changed.
205 Emitted when the slice count has changed.
206 \sa count
206 \sa count
207 */
207 */
208 /*!
208 /*!
209 \qmlsignal PieSeries::onCountChanged()
209 \qmlsignal PieSeries::onCountChanged()
210 Emitted when the slice count has changed.
210 Emitted when the slice count has changed.
211 */
211 */
212
212
213 /*!
213 /*!
214 \property QPieSeries::sum
214 \property QPieSeries::sum
215
215
216 Sum of all slices.
216 Sum of all slices.
217
217
218 The series keeps track of the sum of all slices it holds.
218 The series keeps track of the sum of all slices it holds.
219 */
219 */
220
220
221 /*!
221 /*!
222 \qmlproperty real PieSeries::sum
222 \qmlproperty real PieSeries::sum
223
223
224 Sum of all slices.
224 Sum of all slices.
225
225
226 The series keeps track of the sum of all slices it holds.
226 The series keeps track of the sum of all slices it holds.
227 */
227 */
228
228
229 /*!
229 /*!
230 \fn void QPieSeries::sumChanged()
230 \fn void QPieSeries::sumChanged()
231 Emitted when the sum of all slices has changed.
231 Emitted when the sum of all slices has changed.
232 \sa sum
232 \sa sum
233 */
233 */
234 /*!
234 /*!
235 \qmlsignal PieSeries::onSumChanged()
235 \qmlsignal PieSeries::onSumChanged()
236 Emitted when the sum of all slices has changed. This may happen for example if you add or remove slices, or if you
236 Emitted when the sum of all slices has changed. This may happen for example if you add or remove slices, or if you
237 change value of a slice.
237 change value of a slice.
238 */
238 */
239
239
240 /*!
240 /*!
241 \fn void QPieSeries::added(QList<QPieSlice*> slices)
241 \fn void QPieSeries::added(QList<QPieSlice*> slices)
242
242
243 This signal is emitted when \a slices have been added to the series.
243 This signal is emitted when \a slices have been added to the series.
244
244
245 \sa append(), insert()
245 \sa append(), insert()
246 */
246 */
247 /*!
247 /*!
248 \qmlsignal PieSeries::onAdded(PieSlice slice)
248 \qmlsignal PieSeries::onAdded(PieSlice slice)
249 Emitted when \a slice has been added to the series.
249 Emitted when \a slice has been added to the series.
250 */
250 */
251
251
252 /*!
252 /*!
253 \fn void QPieSeries::removed(QList<QPieSlice*> slices)
253 \fn void QPieSeries::removed(QList<QPieSlice*> slices)
254 This signal is emitted when \a slices have been removed from the series.
254 This signal is emitted when \a slices have been removed from the series.
255 \sa remove()
255 \sa remove()
256 */
256 */
257 /*!
257 /*!
258 \qmlsignal PieSeries::onRemoved(PieSlice slice)
258 \qmlsignal PieSeries::onRemoved(PieSlice slice)
259 Emitted when \a slice has been removed from the series.
259 Emitted when \a slice has been removed from the series.
260 */
260 */
261
261
262 /*!
262 /*!
263 \fn void QPieSeries::clicked(QPieSlice* slice)
263 \fn void QPieSeries::clicked(QPieSlice* slice)
264 This signal is emitted when a \a slice has been clicked.
264 This signal is emitted when a \a slice has been clicked.
265 \sa QPieSlice::clicked()
265 \sa QPieSlice::clicked()
266 */
266 */
267 /*!
267 /*!
268 \qmlsignal PieSeries::onClicked(PieSlice slice)
268 \qmlsignal PieSeries::onClicked(PieSlice slice)
269 This signal is emitted when a \a slice has been clicked.
269 This signal is emitted when a \a slice has been clicked.
270 */
270 */
271
271
272 /*!
272 /*!
273 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
273 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
274 This signal is emitted when user has hovered over or away from the \a slice.
274 This signal is emitted when user has hovered over or away from the \a slice.
275 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
275 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
276 \sa QPieSlice::hovered()
276 \sa QPieSlice::hovered()
277 */
277 */
278 /*!
278 /*!
279 \qmlsignal PieSeries::onHovered(PieSlice slice, bool state)
279 \qmlsignal PieSeries::onHovered(PieSlice slice, bool state)
280 This signal is emitted when user has hovered over or away from the \a slice. \a state is true when user has hovered
280 This signal is emitted when user has hovered over or away from the \a slice. \a state is true when user has hovered
281 over the slice and false when hover has moved away from the slice.
281 over the slice and false when hover has moved away from the slice.
282 */
282 */
283
283
284 /*!
284 /*!
285 \qmlmethod PieSlice PieSeries::at(int index)
285 \qmlmethod PieSlice PieSeries::at(int index)
286 Returns slice at \a index. Returns null if the index is not valid.
286 Returns slice at \a index. Returns null if the index is not valid.
287 */
287 */
288
288
289 /*!
289 /*!
290 \qmlmethod PieSlice PieSeries::find(string label)
290 \qmlmethod PieSlice PieSeries::find(string label)
291 Returns the first slice with \a label. Returns null if the index is not valid.
291 Returns the first slice with \a label. Returns null if the index is not valid.
292 */
292 */
293
293
294 /*!
294 /*!
295 \qmlmethod PieSlice PieSeries::append(string label, real value)
295 \qmlmethod PieSlice PieSeries::append(string label, real value)
296 Adds a new slice with \a label and \a value to the pie.
296 Adds a new slice with \a label and \a value to the pie.
297 */
297 */
298
298
299 /*!
299 /*!
300 \qmlmethod bool PieSeries::remove(PieSlice slice)
300 \qmlmethod bool PieSeries::remove(PieSlice slice)
301 Removes the \a slice from the pie. Returns true if the removal was successfull, false otherwise.
301 Removes the \a slice from the pie. Returns true if the removal was successfull, false otherwise.
302 */
302 */
303
303
304 /*!
304 /*!
305 \qmlmethod PieSeries::clear()
305 \qmlmethod PieSeries::clear()
306 Removes all slices from the pie.
306 Removes all slices from the pie.
307 */
307 */
308
308
309 /*!
309 /*!
310 Constructs a series object which is a child of \a parent.
310 Constructs a series object which is a child of \a parent.
311 */
311 */
312 QPieSeries::QPieSeries(QObject *parent) :
312 QPieSeries::QPieSeries(QObject *parent) :
313 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
313 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
314 {
314 {
315
315
316 }
316 }
317
317
318 /*!
318 /*!
319 Destroys the series and its slices.
319 Destroys the series and its slices.
320 */
320 */
321 QPieSeries::~QPieSeries()
321 QPieSeries::~QPieSeries()
322 {
322 {
323 // NOTE: d_prt destroyed by QObject
323 // NOTE: d_prt destroyed by QObject
324 }
324 }
325
325
326 /*!
326 /*!
327 Returns QChartSeries::SeriesTypePie.
327 Returns QChartSeries::SeriesTypePie.
328 */
328 */
329 QAbstractSeries::SeriesType QPieSeries::type() const
329 QAbstractSeries::SeriesType QPieSeries::type() const
330 {
330 {
331 return QAbstractSeries::SeriesTypePie;
331 return QAbstractSeries::SeriesTypePie;
332 }
332 }
333
333
334 /*!
334 /*!
335 Appends a single \a slice to the series.
335 Appends a single \a slice to the series.
336 Slice ownership is passed to the series.
336 Slice ownership is passed to the series.
337
337
338 Returns true if append was succesfull.
338 Returns true if append was succesfull.
339 */
339 */
340 bool QPieSeries::append(QPieSlice* slice)
340 bool QPieSeries::append(QPieSlice* slice)
341 {
341 {
342 return append(QList<QPieSlice*>() << slice);
342 return append(QList<QPieSlice*>() << slice);
343 }
343 }
344
344
345 /*!
345 /*!
346 Appends an array of \a slices to the series.
346 Appends an array of \a slices to the series.
347 Slice ownership is passed to the series.
347 Slice ownership is passed to the series.
348
348
349 Returns true if append was successfull.
349 Returns true if append was successfull.
350 */
350 */
351 bool QPieSeries::append(QList<QPieSlice*> slices)
351 bool QPieSeries::append(QList<QPieSlice*> slices)
352 {
352 {
353 Q_D(QPieSeries);
353 Q_D(QPieSeries);
354
354
355 if (slices.count() == 0)
355 if (slices.count() == 0)
356 return false;
356 return false;
357
357
358 foreach (QPieSlice* s, slices) {
358 foreach (QPieSlice* s, slices) {
359 if (!s || d->m_slices.contains(s))
359 if (!s || d->m_slices.contains(s))
360 return false;
360 return false;
361 if (s->series()) // already added to some series
361 if (s->series()) // already added to some series
362 return false;
362 return false;
363 }
363 }
364
364
365 foreach (QPieSlice* s, slices) {
365 foreach (QPieSlice* s, slices) {
366 s->setParent(this);
366 s->setParent(this);
367 QPieSlicePrivate::fromSlice(s)->m_series = this;
367 QPieSlicePrivate::fromSlice(s)->m_series = this;
368 d->m_slices << s;
368 d->m_slices << s;
369 }
369 }
370
370
371 d->updateDerivativeData();
371 d->updateDerivativeData();
372
372
373 foreach (QPieSlice* s, slices) {
373 foreach (QPieSlice* s, slices) {
374 connect(s, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
374 connect(s, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
375 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
375 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
376 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
376 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
377 }
377 }
378
378
379 emit added(slices);
379 emit added(slices);
380 emit countChanged();
380 emit countChanged();
381
381
382 return true;
382 return true;
383 }
383 }
384
384
385 /*!
385 /*!
386 Appends a single \a slice to the series and returns a reference to the series.
386 Appends a single \a slice to the series and returns a reference to the series.
387 Slice ownership is passed to the series.
387 Slice ownership is passed to the series.
388 */
388 */
389 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
389 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
390 {
390 {
391 append(slice);
391 append(slice);
392 return *this;
392 return *this;
393 }
393 }
394
394
395
395
396 /*!
396 /*!
397 Appends a single slice to the series with give \a value and \a label.
397 Appends a single slice to the series with give \a value and \a label.
398 Slice ownership is passed to the series.
398 Slice ownership is passed to the series.
399 */
399 */
400 QPieSlice* QPieSeries::append(QString label, qreal value)
400 QPieSlice* QPieSeries::append(QString label, qreal value)
401 {
401 {
402 QPieSlice* slice = new QPieSlice(label, value);
402 QPieSlice* slice = new QPieSlice(label, value);
403 append(slice);
403 append(slice);
404 return slice;
404 return slice;
405 }
405 }
406
406
407 /*!
407 /*!
408 Inserts a single \a slice to the series before the slice at \a index position.
408 Inserts a single \a slice to the series before the slice at \a index position.
409 Slice ownership is passed to the series.
409 Slice ownership is passed to the series.
410
410
411 Returns true if insert was successfull.
411 Returns true if insert was successfull.
412 */
412 */
413 bool QPieSeries::insert(int index, QPieSlice* slice)
413 bool QPieSeries::insert(int index, QPieSlice* slice)
414 {
414 {
415 Q_D(QPieSeries);
415 Q_D(QPieSeries);
416
416
417 if (index < 0 || index > d->m_slices.count())
417 if (index < 0 || index > d->m_slices.count())
418 return false;
418 return false;
419
419
420 if (!slice || d->m_slices.contains(slice))
420 if (!slice || d->m_slices.contains(slice))
421 return false;
421 return false;
422
422
423 if (slice->series()) // already added to some series
423 if (slice->series()) // already added to some series
424 return false;
424 return false;
425
425
426 slice->setParent(this);
426 slice->setParent(this);
427 QPieSlicePrivate::fromSlice(slice)->m_series = this;
427 QPieSlicePrivate::fromSlice(slice)->m_series = this;
428 d->m_slices.insert(index, slice);
428 d->m_slices.insert(index, slice);
429
429
430 d->updateDerivativeData();
430 d->updateDerivativeData();
431
431
432 connect(slice, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
432 connect(slice, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
433 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
433 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
434 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
434 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
435
435
436 emit added(QList<QPieSlice*>() << slice);
436 emit added(QList<QPieSlice*>() << slice);
437 emit countChanged();
437 emit countChanged();
438
438
439 return true;
439 return true;
440 }
440 }
441
441
442 /*!
442 /*!
443 Removes a single \a slice from the series and deletes the slice.
443 Removes a single \a slice from the series and deletes the slice.
444
444
445 Do not reference the pointer after this call.
445 Do not reference the pointer after this call.
446
446
447 Returns true if remove was successfull.
447 Returns true if remove was successfull.
448 */
448 */
449 bool QPieSeries::remove(QPieSlice* slice)
449 bool QPieSeries::remove(QPieSlice* slice)
450 {
450 {
451 Q_D(QPieSeries);
451 Q_D(QPieSeries);
452
452
453 if (!d->m_slices.removeOne(slice))
453 if (!d->m_slices.removeOne(slice))
454 return false;
454 return false;
455
455
456 d->updateDerivativeData();
456 d->updateDerivativeData();
457
457
458 emit removed(QList<QPieSlice*>() << slice);
458 emit removed(QList<QPieSlice*>() << slice);
459 emit countChanged();
459 emit countChanged();
460
460
461 delete slice;
461 delete slice;
462 slice = 0;
462 slice = 0;
463
463
464 return true;
464 return true;
465 }
465 }
466
466
467 /*!
467 /*!
468 Clears all slices from the series.
468 Clears all slices from the series.
469 */
469 */
470 void QPieSeries::clear()
470 void QPieSeries::clear()
471 {
471 {
472 Q_D(QPieSeries);
472 Q_D(QPieSeries);
473 if (d->m_slices.count() == 0)
473 if (d->m_slices.count() == 0)
474 return;
474 return;
475
475
476 QList<QPieSlice*> slices = d->m_slices;
476 QList<QPieSlice*> slices = d->m_slices;
477 foreach (QPieSlice* s, d->m_slices) {
477 foreach (QPieSlice* s, d->m_slices) {
478 d->m_slices.removeOne(s);
478 d->m_slices.removeOne(s);
479 delete s;
479 delete s;
480 }
480 }
481
481
482 d->updateDerivativeData();
482 d->updateDerivativeData();
483
483
484 emit removed(slices);
484 emit removed(slices);
485 emit countChanged();
485 emit countChanged();
486 }
486 }
487
487
488 /*!
488 /*!
489 Returns a list of slices that belong to this series.
489 Returns a list of slices that belong to this series.
490 */
490 */
491 QList<QPieSlice*> QPieSeries::slices() const
491 QList<QPieSlice*> QPieSeries::slices() const
492 {
492 {
493 Q_D(const QPieSeries);
493 Q_D(const QPieSeries);
494 return d->m_slices;
494 return d->m_slices;
495 }
495 }
496
496
497 /*!
497 /*!
498 returns the number of the slices in this series.
498 returns the number of the slices in this series.
499 */
499 */
500 int QPieSeries::count() const
500 int QPieSeries::count() const
501 {
501 {
502 Q_D(const QPieSeries);
502 Q_D(const QPieSeries);
503 return d->m_slices.count();
503 return d->m_slices.count();
504 }
504 }
505
505
506 /*!
506 /*!
507 Returns true is the series is empty.
507 Returns true is the series is empty.
508 */
508 */
509 bool QPieSeries::isEmpty() const
509 bool QPieSeries::isEmpty() const
510 {
510 {
511 Q_D(const QPieSeries);
511 Q_D(const QPieSeries);
512 return d->m_slices.isEmpty();
512 return d->m_slices.isEmpty();
513 }
513 }
514
514
515 /*!
515 /*!
516 Returns the sum of all slice values in this series.
516 Returns the sum of all slice values in this series.
517
517
518 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
518 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
519 */
519 */
520 qreal QPieSeries::sum() const
520 qreal QPieSeries::sum() const
521 {
521 {
522 Q_D(const QPieSeries);
522 Q_D(const QPieSeries);
523 return d->m_sum;
523 return d->m_sum;
524 }
524 }
525
525
526 void QPieSeries::setDonut(bool donut)
526 void QPieSeries::setDonut(bool donut)
527 {
527 {
528 Q_D(QPieSeries);
528 Q_D(QPieSeries);
529 d->m_donutChart = donut;
529 d->m_donutChart = donut;
530 d->updateDerivativeData();
530 d->updateDerivativeData();
531 }
531 }
532
532
533 bool QPieSeries::donut() const
533 bool QPieSeries::donut() const
534 {
534 {
535 Q_D(const QPieSeries);
535 Q_D(const QPieSeries);
536 return d->m_donutChart;
536 return d->m_donutChart;
537 }
537 }
538
538
539 void QPieSeries::setDonutInnerSize(qreal innerSize)
540 {
541 Q_D(QPieSeries);
542
543 if (innerSize < 0.0)
544 innerSize = 0.0;
545 if (innerSize > 1.0)
546 innerSize = 1.0;
547
548 d->m_donutRelativeInnerSize = innerSize;
549 d->updateDerivativeData();
550 emit d->pieSizeChanged();
551 }
552
553 qreal QPieSeries::donutInnerSize() const
554 {
555 Q_D(const QPieSeries);
556 return d->m_donutRelativeInnerSize;
557 }
558
539 void QPieSeries::setHorizontalPosition(qreal relativePosition)
559 void QPieSeries::setHorizontalPosition(qreal relativePosition)
540 {
560 {
541 Q_D(QPieSeries);
561 Q_D(QPieSeries);
542
562
543 if (relativePosition < 0.0)
563 if (relativePosition < 0.0)
544 relativePosition = 0.0;
564 relativePosition = 0.0;
545 if (relativePosition > 1.0)
565 if (relativePosition > 1.0)
546 relativePosition = 1.0;
566 relativePosition = 1.0;
547
567
548 if (!qFuzzyIsNull(d->m_pieRelativeHorPos - relativePosition)) {
568 if (!qFuzzyIsNull(d->m_pieRelativeHorPos - relativePosition)) {
549 d->m_pieRelativeHorPos = relativePosition;
569 d->m_pieRelativeHorPos = relativePosition;
550 emit d->horizontalPositionChanged();
570 emit d->horizontalPositionChanged();
551 }
571 }
552 }
572 }
553
573
554 qreal QPieSeries::horizontalPosition() const
574 qreal QPieSeries::horizontalPosition() const
555 {
575 {
556 Q_D(const QPieSeries);
576 Q_D(const QPieSeries);
557 return d->m_pieRelativeHorPos;
577 return d->m_pieRelativeHorPos;
558 }
578 }
559
579
560 void QPieSeries::setVerticalPosition(qreal relativePosition)
580 void QPieSeries::setVerticalPosition(qreal relativePosition)
561 {
581 {
562 Q_D(QPieSeries);
582 Q_D(QPieSeries);
563
583
564 if (relativePosition < 0.0)
584 if (relativePosition < 0.0)
565 relativePosition = 0.0;
585 relativePosition = 0.0;
566 if (relativePosition > 1.0)
586 if (relativePosition > 1.0)
567 relativePosition = 1.0;
587 relativePosition = 1.0;
568
588
569 if (!qFuzzyIsNull(d->m_pieRelativeVerPos - relativePosition)) {
589 if (!qFuzzyIsNull(d->m_pieRelativeVerPos - relativePosition)) {
570 d->m_pieRelativeVerPos = relativePosition;
590 d->m_pieRelativeVerPos = relativePosition;
571 emit d->verticalPositionChanged();
591 emit d->verticalPositionChanged();
572 }
592 }
573 }
593 }
574
594
575 qreal QPieSeries::verticalPosition() const
595 qreal QPieSeries::verticalPosition() const
576 {
596 {
577 Q_D(const QPieSeries);
597 Q_D(const QPieSeries);
578 return d->m_pieRelativeVerPos;
598 return d->m_pieRelativeVerPos;
579 }
599 }
580
600
581 void QPieSeries::setPieSize(qreal relativeSize)
601 void QPieSeries::setPieSize(qreal relativeSize)
582 {
602 {
583 Q_D(QPieSeries);
603 Q_D(QPieSeries);
584
604
585 if (relativeSize < 0.0)
605 if (relativeSize < 0.0)
586 relativeSize = 0.0;
606 relativeSize = 0.0;
587 if (relativeSize > 1.0)
607 if (relativeSize > 1.0)
588 relativeSize = 1.0;
608 relativeSize = 1.0;
589
609
590 if (!qFuzzyIsNull(d->m_pieRelativeSize - relativeSize)) {
610 if (!qFuzzyIsNull(d->m_pieRelativeSize - relativeSize)) {
591 d->m_pieRelativeSize = relativeSize;
611 d->m_pieRelativeSize = relativeSize;
592 emit d->pieSizeChanged();
612 emit d->pieSizeChanged();
593 }
613 }
594 }
614 }
595
615
596 qreal QPieSeries::pieSize() const
616 qreal QPieSeries::pieSize() const
597 {
617 {
598 Q_D(const QPieSeries);
618 Q_D(const QPieSeries);
599 return d->m_pieRelativeSize;
619 return d->m_pieRelativeSize;
600 }
620 }
601
621
602
622
603 void QPieSeries::setPieStartAngle(qreal angle)
623 void QPieSeries::setPieStartAngle(qreal angle)
604 {
624 {
605 Q_D(QPieSeries);
625 Q_D(QPieSeries);
606 if (qFuzzyIsNull(d->m_pieStartAngle - angle))
626 if (qFuzzyIsNull(d->m_pieStartAngle - angle))
607 return;
627 return;
608 d->m_pieStartAngle = angle;
628 d->m_pieStartAngle = angle;
609 d->updateDerivativeData();
629 d->updateDerivativeData();
610 emit d->pieStartAngleChanged();
630 emit d->pieStartAngleChanged();
611 }
631 }
612
632
613 qreal QPieSeries::pieStartAngle() const
633 qreal QPieSeries::pieStartAngle() const
614 {
634 {
615 Q_D(const QPieSeries);
635 Q_D(const QPieSeries);
616 return d->m_pieStartAngle;
636 return d->m_pieStartAngle;
617 }
637 }
618
638
619 /*!
639 /*!
620 Sets the end angle of the pie.
640 Sets the end angle of the pie.
621
641
622 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
642 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
623
643
624 \a angle must be greater than start angle.
644 \a angle must be greater than start angle.
625
645
626 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
646 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
627 */
647 */
628 void QPieSeries::setPieEndAngle(qreal angle)
648 void QPieSeries::setPieEndAngle(qreal angle)
629 {
649 {
630 Q_D(QPieSeries);
650 Q_D(QPieSeries);
631 if (qFuzzyIsNull(d->m_pieEndAngle - angle))
651 if (qFuzzyIsNull(d->m_pieEndAngle - angle))
632 return;
652 return;
633 d->m_pieEndAngle = angle;
653 d->m_pieEndAngle = angle;
634 d->updateDerivativeData();
654 d->updateDerivativeData();
635 emit d->pieEndAngleChanged();
655 emit d->pieEndAngleChanged();
636 }
656 }
637
657
638 /*!
658 /*!
639 Returns the end angle of the pie.
659 Returns the end angle of the pie.
640
660
641 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
661 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
642
662
643 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
663 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
644 */
664 */
645 qreal QPieSeries::pieEndAngle() const
665 qreal QPieSeries::pieEndAngle() const
646 {
666 {
647 Q_D(const QPieSeries);
667 Q_D(const QPieSeries);
648 return d->m_pieEndAngle;
668 return d->m_pieEndAngle;
649 }
669 }
650
670
651 /*!
671 /*!
652 Sets the all the slice labels \a visible or invisible.
672 Sets the all the slice labels \a visible or invisible.
653
673
654 Note that this affects only the current slices in the series.
674 Note that this affects only the current slices in the series.
655 If user adds a new slice the default label visibility is false.
675 If user adds a new slice the default label visibility is false.
656
676
657 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
677 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
658 */
678 */
659 void QPieSeries::setLabelsVisible(bool visible)
679 void QPieSeries::setLabelsVisible(bool visible)
660 {
680 {
661 Q_D(QPieSeries);
681 Q_D(QPieSeries);
662 foreach (QPieSlice* s, d->m_slices)
682 foreach (QPieSlice* s, d->m_slices)
663 s->setLabelVisible(visible);
683 s->setLabelVisible(visible);
664 }
684 }
665
685
666 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
686 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
667
687
668
688
669 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
689 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
670 QAbstractSeriesPrivate(parent),
690 QAbstractSeriesPrivate(parent),
671 m_pieRelativeHorPos(0.5),
691 m_pieRelativeHorPos(0.5),
672 m_pieRelativeVerPos(0.5),
692 m_pieRelativeVerPos(0.5),
673 m_pieRelativeSize(0.7),
693 m_pieRelativeSize(0.7),
674 m_pieStartAngle(0),
694 m_pieStartAngle(0),
675 m_pieEndAngle(360),
695 m_pieEndAngle(360),
676 m_sum(0),
696 m_sum(0),
677 m_donutChart(false)
697 m_donutChart(false),
698 m_donutRelativeInnerSize(0.5)
678 {
699 {
679 }
700 }
680
701
681 QPieSeriesPrivate::~QPieSeriesPrivate()
702 QPieSeriesPrivate::~QPieSeriesPrivate()
682 {
703 {
683 }
704 }
684
705
685 void QPieSeriesPrivate::updateDerivativeData()
706 void QPieSeriesPrivate::updateDerivativeData()
686 {
707 {
687 // calculate sum of all slices
708 // calculate sum of all slices
688 qreal sum = 0;
709 qreal sum = 0;
689 foreach (QPieSlice* s, m_slices)
710 foreach (QPieSlice* s, m_slices)
690 sum += s->value();
711 sum += s->value();
691
712
692 if (!qFuzzyIsNull(m_sum - sum)) {
713 if (!qFuzzyIsNull(m_sum - sum)) {
693 m_sum = sum;
714 m_sum = sum;
694 emit q_func()->sumChanged();
715 emit q_func()->sumChanged();
695 }
716 }
696
717
697 // nothing to show..
718 // nothing to show..
698 if (qFuzzyIsNull(m_sum))
719 if (qFuzzyIsNull(m_sum))
699 return;
720 return;
700
721
701 // update slice attributes
722 // update slice attributes
702 qreal sliceAngle = m_pieStartAngle;
723 qreal sliceAngle = m_pieStartAngle;
703 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
724 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
704 QVector<QPieSlice*> changed;
725 QVector<QPieSlice*> changed;
705 foreach (QPieSlice* s, m_slices) {
726 foreach (QPieSlice* s, m_slices) {
706 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
727 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
707 d->setPercentage(s->value() / m_sum);
728 d->setPercentage(s->value() / m_sum);
708 d->setStartAngle(sliceAngle);
729 d->setStartAngle(sliceAngle);
709 d->setAngleSpan(pieSpan * s->percentage());
730 d->setAngleSpan(pieSpan * s->percentage());
710 d->m_data.m_donut = m_donutChart;
711 sliceAngle += s->angleSpan();
731 sliceAngle += s->angleSpan();
712 }
732 }
713
733
714
734
715 emit calculatedDataChanged();
735 emit calculatedDataChanged();
716 }
736 }
717
737
718 QPieSeriesPrivate* QPieSeriesPrivate::fromSeries(QPieSeries *series)
738 QPieSeriesPrivate* QPieSeriesPrivate::fromSeries(QPieSeries *series)
719 {
739 {
720 return series->d_func();
740 return series->d_func();
721 }
741 }
722
742
723 void QPieSeriesPrivate::sliceValueChanged()
743 void QPieSeriesPrivate::sliceValueChanged()
724 {
744 {
725 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
745 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
726 updateDerivativeData();
746 updateDerivativeData();
727 }
747 }
728
748
729 void QPieSeriesPrivate::sliceClicked()
749 void QPieSeriesPrivate::sliceClicked()
730 {
750 {
731 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
751 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
732 Q_ASSERT(m_slices.contains(slice));
752 Q_ASSERT(m_slices.contains(slice));
733 Q_Q(QPieSeries);
753 Q_Q(QPieSeries);
734 emit q->clicked(slice);
754 emit q->clicked(slice);
735 }
755 }
736
756
737 void QPieSeriesPrivate::sliceHovered(bool state)
757 void QPieSeriesPrivate::sliceHovered(bool state)
738 {
758 {
739 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
759 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
740 Q_ASSERT(m_slices.contains(slice));
760 Q_ASSERT(m_slices.contains(slice));
741 Q_Q(QPieSeries);
761 Q_Q(QPieSeries);
742 emit q->hovered(slice, state);
762 emit q->hovered(slice, state);
743 }
763 }
744
764
745 void QPieSeriesPrivate::scaleDomain(Domain& domain)
765 void QPieSeriesPrivate::scaleDomain(Domain& domain)
746 {
766 {
747 Q_UNUSED(domain);
767 Q_UNUSED(domain);
748 // does not apply to pie
768 // does not apply to pie
749 }
769 }
750
770
751 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
771 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
752 {
772 {
753 Q_Q(QPieSeries);
773 Q_Q(QPieSeries);
754 PieChartItem* pie = new PieChartItem(q,presenter);
774 PieChartItem* pie = new PieChartItem(q,presenter);
755 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
775 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
756 presenter->animator()->addAnimation(pie);
776 presenter->animator()->addAnimation(pie);
757 }
777 }
758 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
778 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
759 return pie;
779 return pie;
760 }
780 }
761
781
762 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
782 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
763 {
783 {
764 Q_Q(QPieSeries);
784 Q_Q(QPieSeries);
765 QList<LegendMarker*> markers;
785 QList<LegendMarker*> markers;
766 foreach(QPieSlice* slice, q->slices()) {
786 foreach(QPieSlice* slice, q->slices()) {
767 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
787 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
768 markers << marker;
788 markers << marker;
769 }
789 }
770 return markers;
790 return markers;
771 }
791 }
772
792
773 void QPieSeriesPrivate::initializeAxisX(QAbstractAxis* axis)
793 void QPieSeriesPrivate::initializeAxisX(QAbstractAxis* axis)
774 {
794 {
775 Q_UNUSED(axis);
795 Q_UNUSED(axis);
776 }
796 }
777
797
778 void QPieSeriesPrivate::initializeAxisY(QAbstractAxis* axis)
798 void QPieSeriesPrivate::initializeAxisY(QAbstractAxis* axis)
779 {
799 {
780 Q_UNUSED(axis);
800 Q_UNUSED(axis);
781 }
801 }
782
802
783 QAbstractAxis::AxisType QPieSeriesPrivate::defaultAxisXType() const
803 QAbstractAxis::AxisType QPieSeriesPrivate::defaultAxisXType() const
784 {
804 {
785 return QAbstractAxis::AxisTypeNoAxis;
805 return QAbstractAxis::AxisTypeNoAxis;
786 }
806 }
787
807
788 QAbstractAxis::AxisType QPieSeriesPrivate::defaultAxisYType() const
808 QAbstractAxis::AxisType QPieSeriesPrivate::defaultAxisYType() const
789 {
809 {
790 return QAbstractAxis::AxisTypeNoAxis;
810 return QAbstractAxis::AxisTypeNoAxis;
791 }
811 }
792
812
793 #include "moc_qpieseries.cpp"
813 #include "moc_qpieseries.cpp"
794 #include "moc_qpieseries_p.cpp"
814 #include "moc_qpieseries_p.cpp"
795
815
796 QTCOMMERCIALCHART_END_NAMESPACE
816 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,99 +1,102
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #ifndef PIESERIES_H
21 #ifndef PIESERIES_H
22 #define PIESERIES_H
22 #define PIESERIES_H
23
23
24 #include <qabstractseries.h>
24 #include <qabstractseries.h>
25
25
26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 class QPieSeriesPrivate;
27 class QPieSeriesPrivate;
28 class QPieSlice;
28 class QPieSlice;
29
29
30 class QTCOMMERCIALCHART_EXPORT QPieSeries : public QAbstractSeries
30 class QTCOMMERCIALCHART_EXPORT QPieSeries : public QAbstractSeries
31 {
31 {
32 Q_OBJECT
32 Q_OBJECT
33 Q_PROPERTY(qreal horizontalPosition READ horizontalPosition WRITE setHorizontalPosition)
33 Q_PROPERTY(qreal horizontalPosition READ horizontalPosition WRITE setHorizontalPosition)
34 Q_PROPERTY(qreal verticalPosition READ verticalPosition WRITE setVerticalPosition)
34 Q_PROPERTY(qreal verticalPosition READ verticalPosition WRITE setVerticalPosition)
35 Q_PROPERTY(qreal size READ pieSize WRITE setPieSize)
35 Q_PROPERTY(qreal size READ pieSize WRITE setPieSize)
36 Q_PROPERTY(qreal startAngle READ pieStartAngle WRITE setPieStartAngle)
36 Q_PROPERTY(qreal startAngle READ pieStartAngle WRITE setPieStartAngle)
37 Q_PROPERTY(qreal endAngle READ pieEndAngle WRITE setPieEndAngle)
37 Q_PROPERTY(qreal endAngle READ pieEndAngle WRITE setPieEndAngle)
38 Q_PROPERTY(int count READ count NOTIFY countChanged)
38 Q_PROPERTY(int count READ count NOTIFY countChanged)
39 Q_PROPERTY(qreal sum READ sum NOTIFY sumChanged)
39 Q_PROPERTY(qreal sum READ sum NOTIFY sumChanged)
40
40
41 public:
41 public:
42 explicit QPieSeries(QObject *parent = 0);
42 explicit QPieSeries(QObject *parent = 0);
43 virtual ~QPieSeries();
43 virtual ~QPieSeries();
44
44
45 QAbstractSeries::SeriesType type() const;
45 QAbstractSeries::SeriesType type() const;
46
46
47 bool append(QPieSlice* slice);
47 bool append(QPieSlice* slice);
48 bool append(QList<QPieSlice*> slices);
48 bool append(QList<QPieSlice*> slices);
49 QPieSeries& operator << (QPieSlice* slice);
49 QPieSeries& operator << (QPieSlice* slice);
50 QPieSlice* append(QString label, qreal value);
50 QPieSlice* append(QString label, qreal value);
51
51
52 bool insert(int index, QPieSlice* slice);
52 bool insert(int index, QPieSlice* slice);
53
53
54 bool remove(QPieSlice* slice);
54 bool remove(QPieSlice* slice);
55 void clear();
55 void clear();
56
56
57 QList<QPieSlice*> slices() const;
57 QList<QPieSlice*> slices() const;
58 int count() const;
58 int count() const;
59
59
60 bool isEmpty() const;
60 bool isEmpty() const;
61
61
62 qreal sum() const;
62 qreal sum() const;
63
63
64 void setDonut(bool donut = true);
64 void setDonut(bool donut = true);
65 bool donut() const;
65 bool donut() const;
66
66
67 void setDonutInnerSize(qreal innerSize);
68 qreal donutInnerSize() const;
69
67 void setHorizontalPosition(qreal relativePosition);
70 void setHorizontalPosition(qreal relativePosition);
68 qreal horizontalPosition() const;
71 qreal horizontalPosition() const;
69
72
70 void setVerticalPosition(qreal relativePosition);
73 void setVerticalPosition(qreal relativePosition);
71 qreal verticalPosition() const;
74 qreal verticalPosition() const;
72
75
73 void setPieSize(qreal relativeSize);
76 void setPieSize(qreal relativeSize);
74 qreal pieSize() const;
77 qreal pieSize() const;
75
78
76 void setPieStartAngle(qreal startAngle);
79 void setPieStartAngle(qreal startAngle);
77 qreal pieStartAngle() const;
80 qreal pieStartAngle() const;
78
81
79 void setPieEndAngle(qreal endAngle);
82 void setPieEndAngle(qreal endAngle);
80 qreal pieEndAngle() const;
83 qreal pieEndAngle() const;
81
84
82 void setLabelsVisible(bool visible = true);
85 void setLabelsVisible(bool visible = true);
83
86
84 Q_SIGNALS:
87 Q_SIGNALS:
85 void added(QList<QPieSlice*> slices);
88 void added(QList<QPieSlice*> slices);
86 void removed(QList<QPieSlice*> slices);
89 void removed(QList<QPieSlice*> slices);
87 void clicked(QPieSlice* slice);
90 void clicked(QPieSlice* slice);
88 void hovered(QPieSlice* slice, bool state);
91 void hovered(QPieSlice* slice, bool state);
89 void countChanged();
92 void countChanged();
90 void sumChanged();
93 void sumChanged();
91
94
92 private:
95 private:
93 Q_DECLARE_PRIVATE(QPieSeries)
96 Q_DECLARE_PRIVATE(QPieSeries)
94 Q_DISABLE_COPY(QPieSeries)
97 Q_DISABLE_COPY(QPieSeries)
95 };
98 };
96
99
97 QTCOMMERCIALCHART_END_NAMESPACE
100 QTCOMMERCIALCHART_END_NAMESPACE
98
101
99 #endif // PIESERIES_H
102 #endif // PIESERIES_H
@@ -1,89 +1,90
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 // W A R N I N G
21 // W A R N I N G
22 // -------------
22 // -------------
23 //
23 //
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 // implementation detail. This header file may change from version to
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
26 // version without notice, or even be removed.
27 //
27 //
28 // We mean it.
28 // We mean it.
29
29
30 #ifndef QPIESERIES_P_H
30 #ifndef QPIESERIES_P_H
31 #define QPIESERIES_P_H
31 #define QPIESERIES_P_H
32
32
33 #include "qpieseries.h"
33 #include "qpieseries.h"
34 #include "qabstractseries_p.h"
34 #include "qabstractseries_p.h"
35
35
36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 class QLegendPrivate;
37 class QLegendPrivate;
38
38
39 class QPieSeriesPrivate : public QAbstractSeriesPrivate
39 class QPieSeriesPrivate : public QAbstractSeriesPrivate
40 {
40 {
41 Q_OBJECT
41 Q_OBJECT
42
42
43 public:
43 public:
44 QPieSeriesPrivate(QPieSeries *parent);
44 QPieSeriesPrivate(QPieSeries *parent);
45 ~QPieSeriesPrivate();
45 ~QPieSeriesPrivate();
46
46
47 void scaleDomain(Domain& domain);
47 void scaleDomain(Domain& domain);
48 Chart* createGraphics(ChartPresenter *presenter);
48 Chart* createGraphics(ChartPresenter *presenter);
49 QList<LegendMarker*> createLegendMarker(QLegend *legend);
49 QList<LegendMarker*> createLegendMarker(QLegend *legend);
50 void initializeAxisX(QAbstractAxis* axis);
50 void initializeAxisX(QAbstractAxis* axis);
51 void initializeAxisY(QAbstractAxis* axis);
51 void initializeAxisY(QAbstractAxis* axis);
52 QAbstractAxis::AxisType defaultAxisXType() const;
52 QAbstractAxis::AxisType defaultAxisXType() const;
53 QAbstractAxis::AxisType defaultAxisYType() const;
53 QAbstractAxis::AxisType defaultAxisYType() const;
54
54
55 void updateDerivativeData();
55 void updateDerivativeData();
56
56
57 static QPieSeriesPrivate* fromSeries(QPieSeries *series);
57 static QPieSeriesPrivate* fromSeries(QPieSeries *series);
58
58
59 signals:
59 signals:
60 void calculatedDataChanged();
60 void calculatedDataChanged();
61 void pieSizeChanged();
61 void pieSizeChanged();
62 void pieStartAngleChanged();
62 void pieStartAngleChanged();
63 void pieEndAngleChanged();
63 void pieEndAngleChanged();
64 void horizontalPositionChanged();
64 void horizontalPositionChanged();
65 void verticalPositionChanged();
65 void verticalPositionChanged();
66
66
67 public Q_SLOTS:
67 public Q_SLOTS:
68 void sliceValueChanged();
68 void sliceValueChanged();
69 void sliceClicked();
69 void sliceClicked();
70 void sliceHovered(bool state);
70 void sliceHovered(bool state);
71
71
72 private:
72 private:
73 QList<QPieSlice*> m_slices;
73 QList<QPieSlice*> m_slices;
74 qreal m_pieRelativeHorPos;
74 qreal m_pieRelativeHorPos;
75 qreal m_pieRelativeVerPos;
75 qreal m_pieRelativeVerPos;
76 qreal m_pieRelativeSize;
76 qreal m_pieRelativeSize;
77 qreal m_pieStartAngle;
77 qreal m_pieStartAngle;
78 qreal m_pieEndAngle;
78 qreal m_pieEndAngle;
79 qreal m_sum;
79 qreal m_sum;
80 bool m_donutChart;
80 bool m_donutChart;
81 qreal m_donutRelativeInnerSize;
81
82
82 private:
83 private:
83 friend class QLegendPrivate;
84 friend class QLegendPrivate;
84 Q_DECLARE_PUBLIC(QPieSeries)
85 Q_DECLARE_PUBLIC(QPieSeries)
85 };
86 };
86
87
87 QTCOMMERCIALCHART_END_NAMESPACE
88 QTCOMMERCIALCHART_END_NAMESPACE
88
89
89 #endif // QPIESERIES_P_H
90 #endif // QPIESERIES_P_H
@@ -1,505 +1,506
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qxymodelmapper.h"
21 #include "qxymodelmapper.h"
22 #include "qxymodelmapper_p.h"
22 #include "qxymodelmapper_p.h"
23 #include "qxyseries.h"
23 #include "qxyseries.h"
24 #include <QAbstractItemModel>
24 #include <QAbstractItemModel>
25
25
26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27
27
28 /*!
28 /*!
29 Constructs a mapper object which is a child of \a parent.
29 Constructs a mapper object which is a child of \a parent.
30 */
30 */
31 QXYModelMapper::QXYModelMapper(QObject *parent):
31 QXYModelMapper::QXYModelMapper(QObject *parent):
32 QObject(parent),
32 QObject(parent),
33 d_ptr(new QXYModelMapperPrivate(this))
33 d_ptr(new QXYModelMapperPrivate(this))
34 {
34 {
35 }
35 }
36
36
37 /*!
37 /*!
38 \internal
38 \internal
39 */
39 */
40 QAbstractItemModel* QXYModelMapper::model() const
40 QAbstractItemModel* QXYModelMapper::model() const
41 {
41 {
42 Q_D(const QXYModelMapper);
42 Q_D(const QXYModelMapper);
43 return d->m_model;
43 return d->m_model;
44 }
44 }
45
45
46 /*!
46 /*!
47 \internal
47 \internal
48 */
48 */
49 void QXYModelMapper::setModel(QAbstractItemModel *model)
49 void QXYModelMapper::setModel(QAbstractItemModel *model)
50 {
50 {
51 if (model == 0)
51 if (model == 0)
52 return;
52 return;
53
53
54 Q_D(QXYModelMapper);
54 Q_D(QXYModelMapper);
55 if (d->m_model) {
55 if (d->m_model) {
56 disconnect(d->m_model, 0, d, 0);
56 disconnect(d->m_model, 0, d, 0);
57 }
57 }
58
58
59 d->m_model = model;
59 d->m_model = model;
60 d->initializeXYFromModel();
60 d->initializeXYFromModel();
61 // connect signals from the model
61 // connect signals from the model
62 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
62 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
63 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
63 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
64 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
64 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
65 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
65 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
66 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
66 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
67 connect(d->m_model, SIGNAL(destroyed()), d, SLOT(handleModelDestroyed()));
67 connect(d->m_model, SIGNAL(destroyed()), d, SLOT(handleModelDestroyed()));
68 }
68 }
69
69
70 /*!
70 /*!
71 \internal
71 \internal
72 */
72 */
73 QXYSeries* QXYModelMapper::series() const
73 QXYSeries* QXYModelMapper::series() const
74 {
74 {
75 Q_D(const QXYModelMapper);
75 Q_D(const QXYModelMapper);
76 return d->m_series;
76 return d->m_series;
77 }
77 }
78
78
79 /*!
79 /*!
80 \internal
80 \internal
81 */
81 */
82 void QXYModelMapper::setSeries(QXYSeries *series)
82 void QXYModelMapper::setSeries(QXYSeries *series)
83 {
83 {
84 Q_D(QXYModelMapper);
84 Q_D(QXYModelMapper);
85 if (d->m_series) {
85 if (d->m_series) {
86 disconnect(d->m_series, 0, d, 0);
86 disconnect(d->m_series, 0, d, 0);
87 }
87 }
88
88
89 if (series == 0)
89 if (series == 0)
90 return;
90 return;
91
91
92 d->m_series = series;
92 d->m_series = series;
93 d->initializeXYFromModel();
93 d->initializeXYFromModel();
94 // connect the signals from the series
94 // connect the signals from the series
95 connect(d->m_series, SIGNAL(pointAdded(int)), d, SLOT(handlePointAdded(int)));
95 connect(d->m_series, SIGNAL(pointAdded(int)), d, SLOT(handlePointAdded(int)));
96 connect(d->m_series, SIGNAL(pointRemoved(int)), d, SLOT(handlePointRemoved(int)));
96 connect(d->m_series, SIGNAL(pointRemoved(int)), d, SLOT(handlePointRemoved(int)));
97 connect(d->m_series, SIGNAL(pointReplaced(int)), d, SLOT(handlePointReplaced(int)));
97 connect(d->m_series, SIGNAL(pointReplaced(int)), d, SLOT(handlePointReplaced(int)));
98 connect(d->m_series, SIGNAL(destroyed()), d, SLOT(handleSeriesDestroyed()));
98 connect(d->m_series, SIGNAL(destroyed()), d, SLOT(handleSeriesDestroyed()));
99 }
99 }
100
100
101 /*!
101 /*!
102 \internal
102 \internal
103 */
103 */
104 int QXYModelMapper::first() const
104 int QXYModelMapper::first() const
105 {
105 {
106 Q_D(const QXYModelMapper);
106 Q_D(const QXYModelMapper);
107 return d->m_first;
107 return d->m_first;
108 }
108 }
109
109
110 /*!
110 /*!
111 \internal
111 \internal
112 */
112 */
113 void QXYModelMapper::setFirst(int first)
113 void QXYModelMapper::setFirst(int first)
114 {
114 {
115 Q_D(QXYModelMapper);
115 Q_D(QXYModelMapper);
116 d->m_first = qMax(first, 0);
116 d->m_first = qMax(first, 0);
117 d->initializeXYFromModel();
117 d->initializeXYFromModel();
118 }
118 }
119
119
120 /*!
120 /*!
121 \internal
121 \internal
122 */
122 */
123 int QXYModelMapper::count() const
123 int QXYModelMapper::count() const
124 {
124 {
125 Q_D(const QXYModelMapper);
125 Q_D(const QXYModelMapper);
126 return d->m_count;
126 return d->m_count;
127 }
127 }
128
128
129 /*!
129 /*!
130 \internal
130 \internal
131 */
131 */
132 void QXYModelMapper::setCount(int count)
132 void QXYModelMapper::setCount(int count)
133 {
133 {
134 Q_D(QXYModelMapper);
134 Q_D(QXYModelMapper);
135 d->m_count = qMax(count, -1);
135 d->m_count = qMax(count, -1);
136 d->initializeXYFromModel();
136 d->initializeXYFromModel();
137 }
137 }
138
138
139 /*!
139 /*!
140 Returns the orientation that is used when QXYModelMapper accesses the model.
140 Returns the orientation that is used when QXYModelMapper accesses the model.
141 This mean whether the consecutive x/y values of the QXYSeries are read from rows (Qt::Horizontal)
141 This mean whether the consecutive x/y values of the QXYSeries are read from rows (Qt::Horizontal)
142 or from columns (Qt::Vertical)
142 or from columns (Qt::Vertical)
143 */
143 */
144 Qt::Orientation QXYModelMapper::orientation() const
144 Qt::Orientation QXYModelMapper::orientation() const
145 {
145 {
146 Q_D(const QXYModelMapper);
146 Q_D(const QXYModelMapper);
147 return d->m_orientation;
147 return d->m_orientation;
148 }
148 }
149
149
150 /*!
150 /*!
151 Returns the \a orientation that is used when QXYModelMapper accesses the model.
151 Returns the \a orientation that is used when QXYModelMapper accesses the model.
152 This mean whether the consecutive x/y values of the QXYSeries are read from rows (Qt::Horizontal)
152 This mean whether the consecutive x/y values of the QXYSeries are read from rows (Qt::Horizontal)
153 or from columns (Qt::Vertical)
153 or from columns (Qt::Vertical)
154 */
154 */
155 void QXYModelMapper::setOrientation(Qt::Orientation orientation)
155 void QXYModelMapper::setOrientation(Qt::Orientation orientation)
156 {
156 {
157 Q_D(QXYModelMapper);
157 Q_D(QXYModelMapper);
158 d->m_orientation = orientation;
158 d->m_orientation = orientation;
159 d->initializeXYFromModel();
159 d->initializeXYFromModel();
160 }
160 }
161
161
162 /*!
162 /*!
163 Returns which section of the model is kept in sync with the x values of the QXYSeries
163 Returns which section of the model is kept in sync with the x values of the QXYSeries
164 */
164 */
165 int QXYModelMapper::xSection() const
165 int QXYModelMapper::xSection() const
166 {
166 {
167 Q_D(const QXYModelMapper);
167 Q_D(const QXYModelMapper);
168 return d->m_xSection;
168 return d->m_xSection;
169 }
169 }
170
170
171 /*!
171 /*!
172 Sets the model section that is kept in sync with the x values of the QXYSeries.
172 Sets the model section that is kept in sync with the x values of the QXYSeries.
173 Parameter \a xSection specifies the section of the model.
173 Parameter \a xSection specifies the section of the model.
174 */
174 */
175 void QXYModelMapper::setXSection(int xSection)
175 void QXYModelMapper::setXSection(int xSection)
176 {
176 {
177 Q_D(QXYModelMapper);
177 Q_D(QXYModelMapper);
178 d->m_xSection = qMax(-1, xSection);
178 d->m_xSection = qMax(-1, xSection);
179 d->initializeXYFromModel();
179 d->initializeXYFromModel();
180 }
180 }
181
181
182 /*!
182 /*!
183 Returns which section of the model is kept in sync with the y values of the QXYSeries
183 Returns which section of the model is kept in sync with the y values of the QXYSeries
184 */
184 */
185 int QXYModelMapper::ySection() const
185 int QXYModelMapper::ySection() const
186 {
186 {
187 Q_D(const QXYModelMapper);
187 Q_D(const QXYModelMapper);
188 return d->m_ySection;
188 return d->m_ySection;
189 }
189 }
190
190
191 /*!
191 /*!
192 Sets the model section that is kept in sync with the y values of the QXYSeries.
192 Sets the model section that is kept in sync with the y values of the QXYSeries.
193 Parameter \a ySection specifies the section of the model.
193 Parameter \a ySection specifies the section of the model.
194 */
194 */
195 void QXYModelMapper::setYSection(int ySection)
195 void QXYModelMapper::setYSection(int ySection)
196 {
196 {
197 Q_D(QXYModelMapper);
197 Q_D(QXYModelMapper);
198 d->m_ySection = qMax(-1, ySection);
198 d->m_ySection = qMax(-1, ySection);
199 d->initializeXYFromModel();
199 d->initializeXYFromModel();
200 }
200 }
201
201
202 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
202 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
203
203
204 QXYModelMapperPrivate::QXYModelMapperPrivate(QXYModelMapper *q) :
204 QXYModelMapperPrivate::QXYModelMapperPrivate(QXYModelMapper *q) :
205 QObject(q),
205 m_series(0),
206 m_series(0),
206 m_model(0),
207 m_model(0),
207 m_first(0),
208 m_first(0),
208 m_count(-1),
209 m_count(-1),
209 m_orientation(Qt::Vertical),
210 m_orientation(Qt::Vertical),
210 m_xSection(-1),
211 m_xSection(-1),
211 m_ySection(-1),
212 m_ySection(-1),
212 m_seriesSignalsBlock(false),
213 m_seriesSignalsBlock(false),
213 m_modelSignalsBlock(false),
214 m_modelSignalsBlock(false),
214 q_ptr(q)
215 q_ptr(q)
215 {
216 {
216 }
217 }
217
218
218 void QXYModelMapperPrivate::blockModelSignals(bool block)
219 void QXYModelMapperPrivate::blockModelSignals(bool block)
219 {
220 {
220 m_modelSignalsBlock = block;
221 m_modelSignalsBlock = block;
221 }
222 }
222
223
223 void QXYModelMapperPrivate::blockSeriesSignals(bool block)
224 void QXYModelMapperPrivate::blockSeriesSignals(bool block)
224 {
225 {
225 m_seriesSignalsBlock = block;
226 m_seriesSignalsBlock = block;
226 }
227 }
227
228
228 QModelIndex QXYModelMapperPrivate::xModelIndex(int xPos)
229 QModelIndex QXYModelMapperPrivate::xModelIndex(int xPos)
229 {
230 {
230 if (m_count != -1 && xPos >= m_count)
231 if (m_count != -1 && xPos >= m_count)
231 return QModelIndex(); // invalid
232 return QModelIndex(); // invalid
232
233
233 if (m_orientation == Qt::Vertical)
234 if (m_orientation == Qt::Vertical)
234 return m_model->index(xPos + m_first, m_xSection);
235 return m_model->index(xPos + m_first, m_xSection);
235 else
236 else
236 return m_model->index(m_xSection, xPos + m_first);
237 return m_model->index(m_xSection, xPos + m_first);
237 }
238 }
238
239
239 QModelIndex QXYModelMapperPrivate::yModelIndex(int yPos)
240 QModelIndex QXYModelMapperPrivate::yModelIndex(int yPos)
240 {
241 {
241 if (m_count != -1 && yPos >= m_count)
242 if (m_count != -1 && yPos >= m_count)
242 return QModelIndex(); // invalid
243 return QModelIndex(); // invalid
243
244
244 if (m_orientation == Qt::Vertical)
245 if (m_orientation == Qt::Vertical)
245 return m_model->index(yPos + m_first, m_ySection);
246 return m_model->index(yPos + m_first, m_ySection);
246 else
247 else
247 return m_model->index(m_ySection, yPos + m_first);
248 return m_model->index(m_ySection, yPos + m_first);
248 }
249 }
249
250
250 void QXYModelMapperPrivate::handlePointAdded(int pointPos)
251 void QXYModelMapperPrivate::handlePointAdded(int pointPos)
251 {
252 {
252 if (m_seriesSignalsBlock)
253 if (m_seriesSignalsBlock)
253 return;
254 return;
254
255
255 if (m_count != -1)
256 if (m_count != -1)
256 m_count += 1;
257 m_count += 1;
257
258
258 blockModelSignals();
259 blockModelSignals();
259 if (m_orientation == Qt::Vertical)
260 if (m_orientation == Qt::Vertical)
260 m_model->insertRows(pointPos + m_first, 1);
261 m_model->insertRows(pointPos + m_first, 1);
261 else
262 else
262 m_model->insertColumns(pointPos + m_first, 1);
263 m_model->insertColumns(pointPos + m_first, 1);
263
264
264 m_model->setData(xModelIndex(pointPos), m_series->points().at(pointPos).x());
265 m_model->setData(xModelIndex(pointPos), m_series->points().at(pointPos).x());
265 m_model->setData(yModelIndex(pointPos), m_series->points().at(pointPos).y());
266 m_model->setData(yModelIndex(pointPos), m_series->points().at(pointPos).y());
266 blockModelSignals(false);
267 blockModelSignals(false);
267 }
268 }
268
269
269 void QXYModelMapperPrivate::handlePointRemoved(int pointPos)
270 void QXYModelMapperPrivate::handlePointRemoved(int pointPos)
270 {
271 {
271 if (m_seriesSignalsBlock)
272 if (m_seriesSignalsBlock)
272 return;
273 return;
273
274
274 if (m_count != -1)
275 if (m_count != -1)
275 m_count -= 1;
276 m_count -= 1;
276
277
277 blockModelSignals();
278 blockModelSignals();
278 if (m_orientation == Qt::Vertical)
279 if (m_orientation == Qt::Vertical)
279 m_model->removeRow(pointPos + m_first);
280 m_model->removeRow(pointPos + m_first);
280 else
281 else
281 m_model->removeColumn(pointPos + m_first);
282 m_model->removeColumn(pointPos + m_first);
282 blockModelSignals(false);
283 blockModelSignals(false);
283 }
284 }
284
285
285 void QXYModelMapperPrivate::handlePointReplaced(int pointPos)
286 void QXYModelMapperPrivate::handlePointReplaced(int pointPos)
286 {
287 {
287 if (m_seriesSignalsBlock)
288 if (m_seriesSignalsBlock)
288 return;
289 return;
289
290
290 blockModelSignals();
291 blockModelSignals();
291 m_model->setData(xModelIndex(pointPos), m_series->points().at(pointPos).x());
292 m_model->setData(xModelIndex(pointPos), m_series->points().at(pointPos).x());
292 m_model->setData(yModelIndex(pointPos), m_series->points().at(pointPos).y());
293 m_model->setData(yModelIndex(pointPos), m_series->points().at(pointPos).y());
293 blockModelSignals(false);
294 blockModelSignals(false);
294 }
295 }
295
296
296 void QXYModelMapperPrivate::handleSeriesDestroyed()
297 void QXYModelMapperPrivate::handleSeriesDestroyed()
297 {
298 {
298 m_series = 0;
299 m_series = 0;
299 }
300 }
300
301
301 void QXYModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
302 void QXYModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
302 {
303 {
303 if (m_model == 0 || m_series == 0)
304 if (m_model == 0 || m_series == 0)
304 return;
305 return;
305
306
306 if (m_modelSignalsBlock)
307 if (m_modelSignalsBlock)
307 return;
308 return;
308
309
309 blockSeriesSignals();
310 blockSeriesSignals();
310 QModelIndex index;
311 QModelIndex index;
311 QPointF oldPoint;
312 QPointF oldPoint;
312 QPointF newPoint;
313 QPointF newPoint;
313 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
314 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
314 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
315 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
315 index = topLeft.sibling(row, column);
316 index = topLeft.sibling(row, column);
316 if (m_orientation == Qt::Vertical && (index.column() == m_xSection || index.column() == m_ySection)) {
317 if (m_orientation == Qt::Vertical && (index.column() == m_xSection || index.column() == m_ySection)) {
317 if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
318 if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
318 QModelIndex xIndex = xModelIndex(index.row() - m_first);
319 QModelIndex xIndex = xModelIndex(index.row() - m_first);
319 QModelIndex yIndex = yModelIndex(index.row() - m_first);
320 QModelIndex yIndex = yModelIndex(index.row() - m_first);
320 if (xIndex.isValid() && yIndex.isValid()) {
321 if (xIndex.isValid() && yIndex.isValid()) {
321 oldPoint = m_series->points().at(index.row() - m_first);
322 oldPoint = m_series->points().at(index.row() - m_first);
322 newPoint.setX(m_model->data(xIndex).toReal());
323 newPoint.setX(m_model->data(xIndex).toReal());
323 newPoint.setY(m_model->data(yIndex).toReal());
324 newPoint.setY(m_model->data(yIndex).toReal());
324 }
325 }
325 }
326 }
326 } else if (m_orientation == Qt::Horizontal && (index.row() == m_xSection || index.row() == m_ySection)) {
327 } else if (m_orientation == Qt::Horizontal && (index.row() == m_xSection || index.row() == m_ySection)) {
327 if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count)) {
328 if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count)) {
328 QModelIndex xIndex = xModelIndex(index.column() - m_first);
329 QModelIndex xIndex = xModelIndex(index.column() - m_first);
329 QModelIndex yIndex = yModelIndex(index.column() - m_first);
330 QModelIndex yIndex = yModelIndex(index.column() - m_first);
330 if (xIndex.isValid() && yIndex.isValid()) {
331 if (xIndex.isValid() && yIndex.isValid()) {
331 oldPoint = m_series->points().at(index.column() - m_first);
332 oldPoint = m_series->points().at(index.column() - m_first);
332 newPoint.setX(m_model->data(xIndex).toReal());
333 newPoint.setX(m_model->data(xIndex).toReal());
333 newPoint.setY(m_model->data(yIndex).toReal());
334 newPoint.setY(m_model->data(yIndex).toReal());
334 }
335 }
335 }
336 }
336 } else {
337 } else {
337 continue;
338 continue;
338 }
339 }
339 m_series->replace(oldPoint, newPoint);
340 m_series->replace(oldPoint, newPoint);
340 }
341 }
341 }
342 }
342 blockSeriesSignals(false);
343 blockSeriesSignals(false);
343 }
344 }
344
345
345 void QXYModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
346 void QXYModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
346 {
347 {
347 Q_UNUSED(parent);
348 Q_UNUSED(parent);
348 if (m_modelSignalsBlock)
349 if (m_modelSignalsBlock)
349 return;
350 return;
350
351
351 blockSeriesSignals();
352 blockSeriesSignals();
352 if (m_orientation == Qt::Vertical)
353 if (m_orientation == Qt::Vertical)
353 insertData(start, end);
354 insertData(start, end);
354 else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
355 else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
355 initializeXYFromModel();
356 initializeXYFromModel();
356 blockSeriesSignals(false);
357 blockSeriesSignals(false);
357 }
358 }
358
359
359 void QXYModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
360 void QXYModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
360 {
361 {
361 Q_UNUSED(parent);
362 Q_UNUSED(parent);
362 if (m_modelSignalsBlock)
363 if (m_modelSignalsBlock)
363 return;
364 return;
364
365
365 blockSeriesSignals();
366 blockSeriesSignals();
366 if (m_orientation == Qt::Vertical)
367 if (m_orientation == Qt::Vertical)
367 removeData(start, end);
368 removeData(start, end);
368 else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
369 else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
369 initializeXYFromModel();
370 initializeXYFromModel();
370 blockSeriesSignals(false);
371 blockSeriesSignals(false);
371 }
372 }
372
373
373 void QXYModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
374 void QXYModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
374 {
375 {
375 Q_UNUSED(parent);
376 Q_UNUSED(parent);
376 if (m_modelSignalsBlock)
377 if (m_modelSignalsBlock)
377 return;
378 return;
378
379
379 blockSeriesSignals();
380 blockSeriesSignals();
380 if (m_orientation == Qt::Horizontal)
381 if (m_orientation == Qt::Horizontal)
381 insertData(start, end);
382 insertData(start, end);
382 else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
383 else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
383 initializeXYFromModel();
384 initializeXYFromModel();
384 blockSeriesSignals(false);
385 blockSeriesSignals(false);
385 }
386 }
386
387
387 void QXYModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
388 void QXYModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
388 {
389 {
389 Q_UNUSED(parent);
390 Q_UNUSED(parent);
390 if (m_modelSignalsBlock)
391 if (m_modelSignalsBlock)
391 return;
392 return;
392
393
393 blockSeriesSignals();
394 blockSeriesSignals();
394 if (m_orientation == Qt::Horizontal)
395 if (m_orientation == Qt::Horizontal)
395 removeData(start, end);
396 removeData(start, end);
396 else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
397 else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
397 initializeXYFromModel();
398 initializeXYFromModel();
398 blockSeriesSignals(false);
399 blockSeriesSignals(false);
399 }
400 }
400
401
401 void QXYModelMapperPrivate::handleModelDestroyed()
402 void QXYModelMapperPrivate::handleModelDestroyed()
402 {
403 {
403 m_model = 0;
404 m_model = 0;
404 }
405 }
405
406
406 void QXYModelMapperPrivate::insertData(int start, int end)
407 void QXYModelMapperPrivate::insertData(int start, int end)
407 {
408 {
408 if (m_model == 0 || m_series == 0)
409 if (m_model == 0 || m_series == 0)
409 return;
410 return;
410
411
411 if (m_count != -1 && start >= m_first + m_count) {
412 if (m_count != -1 && start >= m_first + m_count) {
412 return;
413 return;
413 } else {
414 } else {
414 int addedCount = end - start + 1;
415 int addedCount = end - start + 1;
415 if (m_count != -1 && addedCount > m_count)
416 if (m_count != -1 && addedCount > m_count)
416 addedCount = m_count;
417 addedCount = m_count;
417 int first = qMax(start, m_first);
418 int first = qMax(start, m_first);
418 int last = qMin(first + addedCount - 1, m_orientation == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
419 int last = qMin(first + addedCount - 1, m_orientation == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
419 for (int i = first; i <= last; i++) {
420 for (int i = first; i <= last; i++) {
420 QPointF point;
421 QPointF point;
421 QModelIndex xIndex = xModelIndex(i - m_first);
422 QModelIndex xIndex = xModelIndex(i - m_first);
422 QModelIndex yIndex = yModelIndex(i - m_first);
423 QModelIndex yIndex = yModelIndex(i - m_first);
423 if (xIndex.isValid() && yIndex.isValid()) {
424 if (xIndex.isValid() && yIndex.isValid()) {
424 point.setX(m_model->data(xIndex, Qt::DisplayRole).toDouble());
425 point.setX(m_model->data(xIndex, Qt::DisplayRole).toDouble());
425 point.setY(m_model->data(yIndex, Qt::DisplayRole).toDouble());
426 point.setY(m_model->data(yIndex, Qt::DisplayRole).toDouble());
426 m_series->insert(i - m_first, point);
427 m_series->insert(i - m_first, point);
427 }
428 }
428 }
429 }
429
430
430 // remove excess of slices (abouve m_count)
431 // remove excess of slices (abouve m_count)
431 if (m_count != -1 && m_series->points().size() > m_count)
432 if (m_count != -1 && m_series->points().size() > m_count)
432 for (int i = m_series->points().size() - 1; i >= m_count; i--) {
433 for (int i = m_series->points().size() - 1; i >= m_count; i--) {
433 m_series->remove(m_series->points().at(i));
434 m_series->remove(m_series->points().at(i));
434 }
435 }
435 }
436 }
436 }
437 }
437
438
438 void QXYModelMapperPrivate::removeData(int start, int end)
439 void QXYModelMapperPrivate::removeData(int start, int end)
439 {
440 {
440 if (m_model == 0 || m_series == 0)
441 if (m_model == 0 || m_series == 0)
441 return;
442 return;
442
443
443 int removedCount = end - start + 1;
444 int removedCount = end - start + 1;
444 if (m_count != -1 && start >= m_first + m_count) {
445 if (m_count != -1 && start >= m_first + m_count) {
445 return;
446 return;
446 } else {
447 } else {
447 int toRemove = qMin(m_series->count(), removedCount); // first find how many items can actually be removed
448 int toRemove = qMin(m_series->count(), removedCount); // first find how many items can actually be removed
448 int first = qMax(start, m_first); // get the index of the first item that will be removed.
449 int first = qMax(start, m_first); // get the index of the first item that will be removed.
449 int last = qMin(first + toRemove - 1, m_series->count() + m_first - 1); // get the index of the last item that will be removed.
450 int last = qMin(first + toRemove - 1, m_series->count() + m_first - 1); // get the index of the last item that will be removed.
450 for (int i = last; i >= first; i--) {
451 for (int i = last; i >= first; i--) {
451 m_series->remove(m_series->points().at(i - m_first));
452 m_series->remove(m_series->points().at(i - m_first));
452 }
453 }
453
454
454 if (m_count != -1) {
455 if (m_count != -1) {
455 int itemsAvailable; // check how many are available to be added
456 int itemsAvailable; // check how many are available to be added
456 if (m_orientation == Qt::Vertical)
457 if (m_orientation == Qt::Vertical)
457 itemsAvailable = m_model->rowCount() - m_first - m_series->count();
458 itemsAvailable = m_model->rowCount() - m_first - m_series->count();
458 else
459 else
459 itemsAvailable = m_model->columnCount() - m_first - m_series->count();
460 itemsAvailable = m_model->columnCount() - m_first - m_series->count();
460 int toBeAdded = qMin(itemsAvailable, m_count - m_series->count()); // add not more items than there is space left to be filled.
461 int toBeAdded = qMin(itemsAvailable, m_count - m_series->count()); // add not more items than there is space left to be filled.
461 int currentSize = m_series->count();
462 int currentSize = m_series->count();
462 if (toBeAdded > 0)
463 if (toBeAdded > 0)
463 for (int i = m_series->count(); i < currentSize + toBeAdded; i++) {
464 for (int i = m_series->count(); i < currentSize + toBeAdded; i++) {
464 QPointF point;
465 QPointF point;
465 QModelIndex xIndex = xModelIndex(i);
466 QModelIndex xIndex = xModelIndex(i);
466 QModelIndex yIndex = yModelIndex(i);
467 QModelIndex yIndex = yModelIndex(i);
467 if (xIndex.isValid() && yIndex.isValid()) {
468 if (xIndex.isValid() && yIndex.isValid()) {
468 point.setX(m_model->data(xIndex, Qt::DisplayRole).toDouble());
469 point.setX(m_model->data(xIndex, Qt::DisplayRole).toDouble());
469 point.setY(m_model->data(yIndex, Qt::DisplayRole).toDouble());
470 point.setY(m_model->data(yIndex, Qt::DisplayRole).toDouble());
470 m_series->insert(i, point);
471 m_series->insert(i, point);
471 }
472 }
472 }
473 }
473 }
474 }
474 }
475 }
475 }
476 }
476
477
477 void QXYModelMapperPrivate::initializeXYFromModel()
478 void QXYModelMapperPrivate::initializeXYFromModel()
478 {
479 {
479 if (m_model == 0 || m_series == 0)
480 if (m_model == 0 || m_series == 0)
480 return;
481 return;
481
482
482 blockSeriesSignals();
483 blockSeriesSignals();
483 // clear current content
484 // clear current content
484 m_series->clear();
485 m_series->clear();
485
486
486 // create the initial slices set
487 // create the initial slices set
487 int pointPos = 0;
488 int pointPos = 0;
488 QModelIndex xIndex = xModelIndex(pointPos);
489 QModelIndex xIndex = xModelIndex(pointPos);
489 QModelIndex yIndex = yModelIndex(pointPos);
490 QModelIndex yIndex = yModelIndex(pointPos);
490 while (xIndex.isValid() && yIndex.isValid()) {
491 while (xIndex.isValid() && yIndex.isValid()) {
491 QPointF point;
492 QPointF point;
492 point.setX(m_model->data(xIndex, Qt::DisplayRole).toDouble());
493 point.setX(m_model->data(xIndex, Qt::DisplayRole).toDouble());
493 point.setY(m_model->data(yIndex, Qt::DisplayRole).toDouble());
494 point.setY(m_model->data(yIndex, Qt::DisplayRole).toDouble());
494 m_series->append(point);
495 m_series->append(point);
495 pointPos++;
496 pointPos++;
496 xIndex = xModelIndex(pointPos);
497 xIndex = xModelIndex(pointPos);
497 yIndex = yModelIndex(pointPos);
498 yIndex = yModelIndex(pointPos);
498 }
499 }
499 blockSeriesSignals(false);
500 blockSeriesSignals(false);
500 }
501 }
501
502
502 #include "moc_qxymodelmapper.cpp"
503 #include "moc_qxymodelmapper.cpp"
503 #include "moc_qxymodelmapper_p.cpp"
504 #include "moc_qxymodelmapper_p.cpp"
504
505
505 QTCOMMERCIALCHART_END_NAMESPACE
506 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now