##// END OF EJS Templates
QXYSeries: support for removing data from model when using custom mapping
Marek Rosa -
r1055:ab3fbe16ea33
parent child
Show More
@@ -1,487 +1,486
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 "qbarseries.h"
21 #include "qbarseries.h"
22 #include "qbarseries_p.h"
22 #include "qbarseries_p.h"
23 #include "qbarset.h"
23 #include "qbarset.h"
24 #include "qbarset_p.h"
24 #include "qbarset_p.h"
25 #include "domain_p.h"
25 #include "domain_p.h"
26 #include "legendmarker_p.h"
26 #include "legendmarker_p.h"
27 #include "chartdataset_p.h"
27 #include "chartdataset_p.h"
28 #include "charttheme_p.h"
28 #include "charttheme_p.h"
29 #include "chartanimator_p.h"
29 #include "chartanimator_p.h"
30
30
31 #include <QAbstractItemModel>
31 #include <QAbstractItemModel>
32 #include <QModelIndex>
32 #include <QModelIndex>
33
33
34 QTCOMMERCIALCHART_BEGIN_NAMESPACE
34 QTCOMMERCIALCHART_BEGIN_NAMESPACE
35
35
36 /*!
36 /*!
37 \class QBarSeries
37 \class QBarSeries
38 \brief part of QtCommercial chart API.
38 \brief part of QtCommercial chart API.
39 \mainclass
39 \mainclass
40
40
41 QBarSeries represents a series of data shown as bars. One QBarSeries can contain multiple
41 QBarSeries represents a series of data shown as bars. One QBarSeries can contain multiple
42 QBarSet data sets. QBarSeries groups the data from sets to categories, which are defined
42 QBarSet data sets. QBarSeries groups the data from sets to categories, which are defined
43 by QStringList.
43 by QStringList.
44
44
45 See the \l {BarChart Example} {bar chart example} to learn how to create a simple bar chart.
45 See the \l {BarChart Example} {bar chart example} to learn how to create a simple bar chart.
46 \image examples_barchart.png
46 \image examples_barchart.png
47
47
48 \sa QBarSet, QStackedBarSeries, QPercentBarSeries
48 \sa QBarSet, QStackedBarSeries, QPercentBarSeries
49 */
49 */
50
50
51 /*!
51 /*!
52 \fn void QBarSeries::clicked(QBarSet *barset, QString category)
52 \fn void QBarSeries::clicked(QBarSet *barset, QString category)
53
53
54 The signal is emitted if the user clicks with a mouse on top of QBarSet \a barset of category \a category
54 The signal is emitted if the user clicks with a mouse on top of QBarSet \a barset of category \a category
55 contained by the series.
55 contained by the series.
56 */
56 */
57
57
58 /*!
58 /*!
59 \fn void QBarSeries::hovered(QBarSet* barset, bool status)
59 \fn void QBarSeries::hovered(QBarSet* barset, bool status)
60
60
61 The signal is emitted if mouse is hovered on top of series.
61 The signal is emitted if mouse is hovered on top of series.
62 Parameter \a barset is the pointer of barset, where hover happened.
62 Parameter \a barset is the pointer of barset, where hover happened.
63 Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
63 Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
64 */
64 */
65
65
66 /*!
66 /*!
67 Constructs empty QBarSeries. Parameter \a categories defines the categories for chart.
67 Constructs empty QBarSeries. Parameter \a categories defines the categories for chart.
68 QBarSeries is QObject which is a child of a \a parent.
68 QBarSeries is QObject which is a child of a \a parent.
69 */
69 */
70 QBarSeries::QBarSeries(QBarCategories categories, QObject *parent) :
70 QBarSeries::QBarSeries(QBarCategories categories, QObject *parent) :
71 QAbstractSeries(*new QBarSeriesPrivate(categories, this),parent)
71 QAbstractSeries(*new QBarSeriesPrivate(categories, this),parent)
72 {
72 {
73 }
73 }
74
74
75 /*!
75 /*!
76 Destructs barseries and owned barsets.
76 Destructs barseries and owned barsets.
77 */
77 */
78 QBarSeries::~QBarSeries()
78 QBarSeries::~QBarSeries()
79 {
79 {
80 // NOTE: d_ptr destroyed by QObject
80 // NOTE: d_ptr destroyed by QObject
81 }
81 }
82
82
83 /*!
83 /*!
84 \internal
84 \internal
85 */
85 */
86 QBarSeries::QBarSeries(QBarSeriesPrivate &d, QObject *parent) :
86 QBarSeries::QBarSeries(QBarSeriesPrivate &d, QObject *parent) :
87 QAbstractSeries(d,parent)
87 QAbstractSeries(d,parent)
88 {
88 {
89 }
89 }
90
90
91 /*!
91 /*!
92 Returns the type of series. Derived classes override this.
92 Returns the type of series. Derived classes override this.
93 */
93 */
94 QAbstractSeries::QSeriesType QBarSeries::type() const
94 QAbstractSeries::QSeriesType QBarSeries::type() const
95 {
95 {
96 return QAbstractSeries::SeriesTypeBar;
96 return QAbstractSeries::SeriesTypeBar;
97 }
97 }
98
98
99 /*!
99 /*!
100 Adds a set of bars to series. Takes ownership of \a set.
100 Adds a set of bars to series. Takes ownership of \a set.
101 */
101 */
102 void QBarSeries::appendBarSet(QBarSet *set)
102 void QBarSeries::appendBarSet(QBarSet *set)
103 {
103 {
104 Q_D(QBarSeries);
104 Q_D(QBarSeries);
105 d->m_barSets.append(set);
105 d->m_barSets.append(set);
106 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), d, SLOT(barsetChanged()));
106 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), d, SLOT(barsetChanged()));
107 emit d->restructuredBars();
107 emit d->restructuredBars();
108 }
108 }
109
109
110 /*!
110 /*!
111 Removes a set of bars from series. Releases ownership of \a set. Doesn't delete \a set.
111 Removes a set of bars from series. Releases ownership of \a set. Doesn't delete \a set.
112 */
112 */
113 void QBarSeries::removeBarSet(QBarSet *set)
113 void QBarSeries::removeBarSet(QBarSet *set)
114 {
114 {
115 Q_D(QBarSeries);
115 Q_D(QBarSeries);
116 if (d->m_barSets.contains(set)) {
116 if (d->m_barSets.contains(set)) {
117 d->m_barSets.removeOne(set);
117 d->m_barSets.removeOne(set);
118 QObject::disconnect(set, SIGNAL(updatedBars()), this, SLOT(barsetChanged()));
118 QObject::disconnect(set, SIGNAL(updatedBars()), this, SLOT(barsetChanged()));
119 emit d->restructuredBars();
119 emit d->restructuredBars();
120 }
120 }
121 }
121 }
122
122
123 /*!
123 /*!
124 Adds a list of barsets to series. Takes ownership of \a sets.
124 Adds a list of barsets to series. Takes ownership of \a sets.
125 */
125 */
126 void QBarSeries::appendBarSets(QList<QBarSet* > sets)
126 void QBarSeries::appendBarSets(QList<QBarSet* > sets)
127 {
127 {
128 Q_D(QBarSeries);
128 Q_D(QBarSeries);
129 foreach (QBarSet* set, sets) {
129 foreach (QBarSet* set, sets) {
130 d->m_barSets.append(set);
130 d->m_barSets.append(set);
131 QObject::connect(set, SIGNAL(updatedBars()), this, SLOT(barsetChanged()));
131 QObject::connect(set, SIGNAL(updatedBars()), this, SLOT(barsetChanged()));
132 }
132 }
133 emit d->restructuredBars();
133 emit d->restructuredBars();
134 }
134 }
135
135
136 /*!
136 /*!
137 Removes a list of barsets from series. Releases ownership of \a sets. Doesn't delete \a sets.
137 Removes a list of barsets from series. Releases ownership of \a sets. Doesn't delete \a sets.
138 */
138 */
139 void QBarSeries::removeBarSets(QList<QBarSet* > sets)
139 void QBarSeries::removeBarSets(QList<QBarSet* > sets)
140 {
140 {
141 Q_D(QBarSeries);
141 Q_D(QBarSeries);
142
142
143 foreach (QBarSet* set, sets) {
143 foreach (QBarSet* set, sets) {
144 if (d->m_barSets.contains(set)) {
144 if (d->m_barSets.contains(set)) {
145 d->m_barSets.removeOne(set);
145 d->m_barSets.removeOne(set);
146 QObject::disconnect(set, SIGNAL(updatedBars()), this, SLOT(barsetChanged()));
146 QObject::disconnect(set, SIGNAL(updatedBars()), this, SLOT(barsetChanged()));
147 }
147 }
148 }
148 }
149 emit d->restructuredBars();
149 emit d->restructuredBars();
150 }
150 }
151
151
152 /*!
152 /*!
153 Returns number of sets in series.
153 Returns number of sets in series.
154 */
154 */
155 int QBarSeries::barsetCount() const
155 int QBarSeries::barsetCount() const
156 {
156 {
157 Q_D(const QBarSeries);
157 Q_D(const QBarSeries);
158 return d->m_barSets.count();
158 return d->m_barSets.count();
159 }
159 }
160
160
161 /*!
161 /*!
162 Returns number of categories in series
162 Returns number of categories in series
163 */
163 */
164 int QBarSeries::categoryCount() const
164 int QBarSeries::categoryCount() const
165 {
165 {
166 Q_D(const QBarSeries);
166 Q_D(const QBarSeries);
167 return d->m_categories.count();
167 return d->m_categories.count();
168 }
168 }
169
169
170 /*!
170 /*!
171 Returns a list of sets in series. Keeps ownership of sets.
171 Returns a list of sets in series. Keeps ownership of sets.
172 */
172 */
173 QList<QBarSet*> QBarSeries::barSets() const
173 QList<QBarSet*> QBarSeries::barSets() const
174 {
174 {
175 Q_D(const QBarSeries);
175 Q_D(const QBarSeries);
176 return d->m_barSets;
176 return d->m_barSets;
177 }
177 }
178
178
179 /*!
179 /*!
180 \fn bool QBarSeries::setModel(QAbstractItemModel *model)
180 \fn bool QBarSeries::setModel(QAbstractItemModel *model)
181 Sets the \a model to be used as a data source
181 Sets the \a model to be used as a data source
182 */
182 */
183 bool QBarSeries::setModel(QAbstractItemModel *model)
183 bool QBarSeries::setModel(QAbstractItemModel *model)
184 {
184 {
185 Q_D(QBarSeries);
185 Q_D(QBarSeries);
186 return d->setModel(model);
186 return d->setModel(model);
187 }
187 }
188
188
189 /*!
189 /*!
190 \fn bool QBarSeries::setModelMapping(int categories, int bottomBoundry, int topBoundry, Qt::Orientation orientation)
190 \fn bool QBarSeries::setModelMapping(int categories, int bottomBoundry, int topBoundry, Qt::Orientation orientation)
191 Sets column/row specified by \a categories to be used as a list of bar series categories.
191 Sets column/row specified by \a categories to be used as a list of bar series categories.
192 Parameter \a bottomBoundry indicates the column/row where the first bar set is located in the model.
192 Parameter \a bottomBoundry indicates the column/row where the first bar set is located in the model.
193 Parameter \a topBoundry indicates the column/row where the last bar set is located in the model.
193 Parameter \a topBoundry indicates the column/row where the last bar set is located in the model.
194 All the columns/rows inbetween those two values are also used as data for bar sets.
194 All the columns/rows inbetween those two values are also used as data for bar sets.
195 The \a orientation parameter specifies whether the data is in columns or in rows.
195 The \a orientation parameter specifies whether the data is in columns or in rows.
196 */
196 */
197 void QBarSeries::setModelMapping(int categories, int bottomBoundary, int topBoundary, Qt::Orientation orientation)
197 void QBarSeries::setModelMapping(int categories, int bottomBoundary, int topBoundary, Qt::Orientation orientation)
198 {
198 {
199 Q_D(QBarSeries);
199 Q_D(QBarSeries);
200 d->setModelMapping(categories,bottomBoundary,topBoundary,orientation);
200 d->setModelMapping(categories,bottomBoundary,topBoundary,orientation);
201 }
201 }
202
202
203 /*!
203 /*!
204 Returns the bar categories of the series.
204 Returns the bar categories of the series.
205 */
205 */
206 QBarCategories QBarSeries::categories() const
206 QBarCategories QBarSeries::categories() const
207 {
207 {
208 Q_D(const QBarSeries);
208 Q_D(const QBarSeries);
209 return d->m_categories;
209 return d->m_categories;
210 }
210 }
211
211
212 /*!
212 /*!
213 Sets the visibility of labels in series to \a visible
213 Sets the visibility of labels in series to \a visible
214 */
214 */
215 void QBarSeries::setLabelsVisible(bool visible)
215 void QBarSeries::setLabelsVisible(bool visible)
216 {
216 {
217 foreach (QBarSet* s, barSets()) {
217 foreach (QBarSet* s, barSets()) {
218 s->setLabelsVisible(visible);
218 s->setLabelsVisible(visible);
219 }
219 }
220 }
220 }
221
221
222 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
222 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
223
223
224 QBarSeriesPrivate::QBarSeriesPrivate(QBarCategories categories, QBarSeries *q) :
224 QBarSeriesPrivate::QBarSeriesPrivate(QBarCategories categories, QBarSeries *q) :
225 QAbstractSeriesPrivate(q),
225 QAbstractSeriesPrivate(q),
226 m_categories(categories),
226 m_categories(categories),
227 m_mapCategories(-1),
227 m_mapCategories(-1),
228 m_mapBarBottom(-1),
228 m_mapBarBottom(-1),
229 m_mapBarTop(-1),
229 m_mapBarTop(-1)
230 m_mapOrientation(Qt::Vertical)
231 {
230 {
232 }
231 }
233
232
234 QBarSet* QBarSeriesPrivate::barsetAt(int index)
233 QBarSet* QBarSeriesPrivate::barsetAt(int index)
235 {
234 {
236 return m_barSets.at(index);
235 return m_barSets.at(index);
237 }
236 }
238
237
239 QString QBarSeriesPrivate::categoryName(int category)
238 QString QBarSeriesPrivate::categoryName(int category)
240 {
239 {
241 return m_categories.at(category);
240 return m_categories.at(category);
242 }
241 }
243
242
244 qreal QBarSeriesPrivate::min()
243 qreal QBarSeriesPrivate::min()
245 {
244 {
246 if (m_barSets.count() <= 0) {
245 if (m_barSets.count() <= 0) {
247 return 0;
246 return 0;
248 }
247 }
249 qreal min = INT_MAX;
248 qreal min = INT_MAX;
250
249
251 for (int i = 0; i < m_barSets.count(); i++) {
250 for (int i = 0; i < m_barSets.count(); i++) {
252 int categoryCount = m_barSets.at(i)->count();
251 int categoryCount = m_barSets.at(i)->count();
253 for (int j = 0; j < categoryCount; j++) {
252 for (int j = 0; j < categoryCount; j++) {
254 qreal temp = m_barSets.at(i)->at(j);
253 qreal temp = m_barSets.at(i)->at(j);
255 if (temp < min)
254 if (temp < min)
256 min = temp;
255 min = temp;
257 }
256 }
258 }
257 }
259 return min;
258 return min;
260 }
259 }
261
260
262 qreal QBarSeriesPrivate::max()
261 qreal QBarSeriesPrivate::max()
263 {
262 {
264 if (m_barSets.count() <= 0) {
263 if (m_barSets.count() <= 0) {
265 return 0;
264 return 0;
266 }
265 }
267 qreal max = INT_MIN;
266 qreal max = INT_MIN;
268
267
269 for (int i = 0; i < m_barSets.count(); i++) {
268 for (int i = 0; i < m_barSets.count(); i++) {
270 int categoryCount = m_barSets.at(i)->count();
269 int categoryCount = m_barSets.at(i)->count();
271 for (int j = 0; j < categoryCount; j++) {
270 for (int j = 0; j < categoryCount; j++) {
272 qreal temp = m_barSets.at(i)->at(j);
271 qreal temp = m_barSets.at(i)->at(j);
273 if (temp > max)
272 if (temp > max)
274 max = temp;
273 max = temp;
275 }
274 }
276 }
275 }
277
276
278 return max;
277 return max;
279 }
278 }
280
279
281 qreal QBarSeriesPrivate::valueAt(int set, int category)
280 qreal QBarSeriesPrivate::valueAt(int set, int category)
282 {
281 {
283 if ((set < 0) || (set >= m_barSets.count())) {
282 if ((set < 0) || (set >= m_barSets.count())) {
284 // No set, no value.
283 // No set, no value.
285 return 0;
284 return 0;
286 } else if ((category < 0) || (category >= m_barSets.at(set)->count())) {
285 } else if ((category < 0) || (category >= m_barSets.at(set)->count())) {
287 // No category, no value.
286 // No category, no value.
288 return 0;
287 return 0;
289 }
288 }
290
289
291 return m_barSets.at(set)->at(category);
290 return m_barSets.at(set)->at(category);
292 }
291 }
293
292
294 qreal QBarSeriesPrivate::percentageAt(int set, int category)
293 qreal QBarSeriesPrivate::percentageAt(int set, int category)
295 {
294 {
296 if ((set < 0) || (set >= m_barSets.count())) {
295 if ((set < 0) || (set >= m_barSets.count())) {
297 // No set, no value.
296 // No set, no value.
298 return 0;
297 return 0;
299 } else if ((category < 0) || (category >= m_barSets.at(set)->count())) {
298 } else if ((category < 0) || (category >= m_barSets.at(set)->count())) {
300 // No category, no value.
299 // No category, no value.
301 return 0;
300 return 0;
302 }
301 }
303
302
304 qreal value = m_barSets.at(set)->at(category);
303 qreal value = m_barSets.at(set)->at(category);
305 qreal sum = categorySum(category);
304 qreal sum = categorySum(category);
306 if ( qFuzzyIsNull(sum) ) {
305 if ( qFuzzyIsNull(sum) ) {
307 return 0;
306 return 0;
308 }
307 }
309
308
310 return value / sum;
309 return value / sum;
311 }
310 }
312
311
313 qreal QBarSeriesPrivate::categorySum(int category)
312 qreal QBarSeriesPrivate::categorySum(int category)
314 {
313 {
315 qreal sum(0);
314 qreal sum(0);
316 int count = m_barSets.count(); // Count sets
315 int count = m_barSets.count(); // Count sets
317 for (int set = 0; set < count; set++) {
316 for (int set = 0; set < count; set++) {
318 if (category < m_barSets.at(set)->count())
317 if (category < m_barSets.at(set)->count())
319 sum += m_barSets.at(set)->at(category);
318 sum += m_barSets.at(set)->at(category);
320 }
319 }
321 return sum;
320 return sum;
322 }
321 }
323
322
324 qreal QBarSeriesPrivate::absoluteCategorySum(int category)
323 qreal QBarSeriesPrivate::absoluteCategorySum(int category)
325 {
324 {
326 qreal sum(0);
325 qreal sum(0);
327 int count = m_barSets.count(); // Count sets
326 int count = m_barSets.count(); // Count sets
328 for (int set = 0; set < count; set++) {
327 for (int set = 0; set < count; set++) {
329 if (category < m_barSets.at(set)->count())
328 if (category < m_barSets.at(set)->count())
330 sum += qAbs(m_barSets.at(set)->at(category));
329 sum += qAbs(m_barSets.at(set)->at(category));
331 }
330 }
332 return sum;
331 return sum;
333 }
332 }
334
333
335 qreal QBarSeriesPrivate::maxCategorySum()
334 qreal QBarSeriesPrivate::maxCategorySum()
336 {
335 {
337 qreal max = INT_MIN;
336 qreal max = INT_MIN;
338 int count = m_categories.count();
337 int count = m_categories.count();
339 for (int i = 0; i < count; i++) {
338 for (int i = 0; i < count; i++) {
340 qreal sum = categorySum(i);
339 qreal sum = categorySum(i);
341 if (sum > max)
340 if (sum > max)
342 max = sum;
341 max = sum;
343 }
342 }
344 return max;
343 return max;
345 }
344 }
346
345
347 bool QBarSeriesPrivate::setModel(QAbstractItemModel *model)
346 bool QBarSeriesPrivate::setModel(QAbstractItemModel *model)
348 {
347 {
349 // disconnect signals from old model
348 // disconnect signals from old model
350 if(m_model)
349 if(m_model)
351 {
350 {
352 disconnect(m_model, 0, this, 0);
351 disconnect(m_model, 0, this, 0);
353 m_mapCategories = -1;
352 m_mapCategories = -1;
354 m_mapBarBottom = -1;
353 m_mapBarBottom = -1;
355 m_mapBarTop = -1;
354 m_mapBarTop = -1;
356 m_mapOrientation = Qt::Vertical;
355 m_mapOrientation = Qt::Vertical;
357 }
356 }
358
357
359 // set new model
358 // set new model
360 if(model)
359 if(model)
361 {
360 {
362 m_model = model;
361 m_model = model;
363 return true;
362 return true;
364 }
363 }
365 else
364 else
366 {
365 {
367 m_model = 0;
366 m_model = 0;
368 return false;
367 return false;
369 }
368 }
370 }
369 }
371
370
372 void QBarSeriesPrivate::setModelMapping(int categories, int bottomBoundry, int topBoundry, Qt::Orientation orientation)
371 void QBarSeriesPrivate::setModelMapping(int categories, int bottomBoundry, int topBoundry, Qt::Orientation orientation)
373 {
372 {
374 Q_Q(QBarSeries);
373 Q_Q(QBarSeries);
375
374
376 if (m_model == 0)
375 if (m_model == 0)
377 return;
376 return;
378
377
379 m_mapCategories = categories;
378 m_mapCategories = categories;
380 m_mapBarBottom = bottomBoundry;
379 m_mapBarBottom = bottomBoundry;
381 m_mapBarTop = topBoundry;
380 m_mapBarTop = topBoundry;
382 m_mapOrientation = orientation;
381 m_mapOrientation = orientation;
383
382
384 // connect the signals
383 // connect the signals
385 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)),
384 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)),
386 this, SLOT(modelUpdated(QModelIndex,QModelIndex)));
385 this, SLOT(modelUpdated(QModelIndex,QModelIndex)));
387
386
388 // create the initial bars
387 // create the initial bars
389 m_categories.clear();
388 m_categories.clear();
390 if (m_mapOrientation == Qt::Vertical) {
389 if (m_mapOrientation == Qt::Vertical) {
391 for (int k = 0; k < m_model->rowCount(); k++) {
390 for (int k = 0; k < m_model->rowCount(); k++) {
392 m_categories << m_model->data(m_model->index(k, m_mapCategories), Qt::DisplayRole).toString();
391 m_categories << m_model->data(m_model->index(k, m_mapCategories), Qt::DisplayRole).toString();
393 }
392 }
394
393
395 for (int i = m_mapBarBottom; i <= m_mapBarTop; i++) {
394 for (int i = m_mapBarBottom; i <= m_mapBarTop; i++) {
396 QBarSet* barSet = new QBarSet(m_model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
395 QBarSet* barSet = new QBarSet(m_model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
397 for(int m = 0; m < m_model->rowCount(); m++)
396 for(int m = 0; m < m_model->rowCount(); m++)
398 *barSet << m_model->data(m_model->index(m, i), Qt::DisplayRole).toDouble();
397 *barSet << m_model->data(m_model->index(m, i), Qt::DisplayRole).toDouble();
399 q->appendBarSet(barSet);
398 q->appendBarSet(barSet);
400 }
399 }
401 } else {
400 } else {
402 for (int k = 0; k < m_model->columnCount(); k++) {
401 for (int k = 0; k < m_model->columnCount(); k++) {
403 m_categories << m_model->data(m_model->index(m_mapCategories, k), Qt::DisplayRole).toString();
402 m_categories << m_model->data(m_model->index(m_mapCategories, k), Qt::DisplayRole).toString();
404 }
403 }
405
404
406 for (int i = m_mapBarBottom; i <= m_mapBarTop; i++) {
405 for (int i = m_mapBarBottom; i <= m_mapBarTop; i++) {
407 QBarSet* barSet = new QBarSet(m_model->headerData(i, Qt::Vertical, Qt::DisplayRole).toString());
406 QBarSet* barSet = new QBarSet(m_model->headerData(i, Qt::Vertical, Qt::DisplayRole).toString());
408 for(int m = 0; m < m_model->columnCount(); m++)
407 for(int m = 0; m < m_model->columnCount(); m++)
409 *barSet << m_model->data(m_model->index(i, m), Qt::DisplayRole).toDouble();
408 *barSet << m_model->data(m_model->index(i, m), Qt::DisplayRole).toDouble();
410 q->appendBarSet(barSet);
409 q->appendBarSet(barSet);
411 }
410 }
412 }
411 }
413 }
412 }
414
413
415 void QBarSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
414 void QBarSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
416 {
415 {
417 Q_UNUSED(bottomRight)
416 Q_UNUSED(bottomRight)
418
417
419 if (m_mapOrientation == Qt::Vertical)
418 if (m_mapOrientation == Qt::Vertical)
420 {
419 {
421 // model update is relevant to BarSeries if the change was made to the part of the model that was mapped to BarSeries
420 // model update is relevant to BarSeries if the change was made to the part of the model that was mapped to BarSeries
422 if (topLeft.column() >= m_mapBarBottom && topLeft.column() <= m_mapBarTop)
421 if (topLeft.column() >= m_mapBarBottom && topLeft.column() <= m_mapBarTop)
423 barsetAt(topLeft.column() - m_mapBarBottom)->replace(topLeft.row(), m_model->data(topLeft, Qt::DisplayRole).toDouble());
422 barsetAt(topLeft.column() - m_mapBarBottom)->replace(topLeft.row(), m_model->data(topLeft, Qt::DisplayRole).toDouble());
424 }
423 }
425 else
424 else
426 {
425 {
427 // model update is relevant to BarSeries if the change was made to the part of the model that was mapped to BarSeries
426 // model update is relevant to BarSeries if the change was made to the part of the model that was mapped to BarSeries
428 if (topLeft.row() >= m_mapBarBottom && topLeft.row() <= m_mapBarTop)
427 if (topLeft.row() >= m_mapBarBottom && topLeft.row() <= m_mapBarTop)
429 barsetAt(topLeft.row() - m_mapBarBottom)->replace(topLeft.column(), m_model->data(topLeft, Qt::DisplayRole).toDouble());
428 barsetAt(topLeft.row() - m_mapBarBottom)->replace(topLeft.column(), m_model->data(topLeft, Qt::DisplayRole).toDouble());
430 }
429 }
431 }
430 }
432
431
433 void QBarSeriesPrivate::barsetChanged()
432 void QBarSeriesPrivate::barsetChanged()
434 {
433 {
435 emit updatedBars();
434 emit updatedBars();
436 }
435 }
437
436
438 void QBarSeriesPrivate::scaleDomain(Domain& domain)
437 void QBarSeriesPrivate::scaleDomain(Domain& domain)
439 {
438 {
440 qreal minX(domain.minX());
439 qreal minX(domain.minX());
441 qreal minY(domain.minY());
440 qreal minY(domain.minY());
442 qreal maxX(domain.maxX());
441 qreal maxX(domain.maxX());
443 qreal maxY(domain.maxY());
442 qreal maxY(domain.maxY());
444 int tickXCount(domain.tickXCount());
443 int tickXCount(domain.tickXCount());
445 int tickYCount(domain.tickYCount());
444 int tickYCount(domain.tickYCount());
446
445
447 qreal x = m_categories.count();
446 qreal x = m_categories.count();
448 qreal y = max();
447 qreal y = max();
449 minX = qMin(minX, x);
448 minX = qMin(minX, x);
450 minY = qMin(minY, y);
449 minY = qMin(minY, y);
451 maxX = qMax(maxX, x);
450 maxX = qMax(maxX, x);
452 maxY = qMax(maxY, y);
451 maxY = qMax(maxY, y);
453 tickXCount = x+1;
452 tickXCount = x+1;
454
453
455 domain.setRangeX(minX,maxX,tickXCount);
454 domain.setRangeX(minX,maxX,tickXCount);
456 domain.setRangeY(minY,maxY,tickYCount);
455 domain.setRangeY(minY,maxY,tickYCount);
457 }
456 }
458
457
459 Chart* QBarSeriesPrivate::createGraphics(ChartPresenter* presenter)
458 Chart* QBarSeriesPrivate::createGraphics(ChartPresenter* presenter)
460 {
459 {
461 Q_Q(QBarSeries);
460 Q_Q(QBarSeries);
462
461
463 BarChartItem* bar = new BarChartItem(q,presenter);
462 BarChartItem* bar = new BarChartItem(q,presenter);
464 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
463 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
465 presenter->animator()->addAnimation(bar);
464 presenter->animator()->addAnimation(bar);
466 }
465 }
467 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
466 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
468 return bar;
467 return bar;
469
468
470 }
469 }
471
470
472 QList<LegendMarker*> QBarSeriesPrivate::createLegendMarker(QLegend* legend)
471 QList<LegendMarker*> QBarSeriesPrivate::createLegendMarker(QLegend* legend)
473 {
472 {
474 Q_Q(QBarSeries);
473 Q_Q(QBarSeries);
475 QList<LegendMarker*> markers;
474 QList<LegendMarker*> markers;
476 foreach(QBarSet* set, q->barSets()) {
475 foreach(QBarSet* set, q->barSets()) {
477 BarLegendMarker* marker = new BarLegendMarker(q,set,legend);
476 BarLegendMarker* marker = new BarLegendMarker(q,set,legend);
478 markers << marker;
477 markers << marker;
479 }
478 }
480
479
481 return markers;
480 return markers;
482 }
481 }
483
482
484 #include "moc_qbarseries.cpp"
483 #include "moc_qbarseries.cpp"
485 #include "moc_qbarseries_p.cpp"
484 #include "moc_qbarseries_p.cpp"
486
485
487 QTCOMMERCIALCHART_END_NAMESPACE
486 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,61 +1,60
1 #ifndef QBARSERIES_P_H
1 #ifndef QBARSERIES_P_H
2 #define QBARSERIES_P_H
2 #define QBARSERIES_P_H
3
3
4 #include "qbarseries.h"
4 #include "qbarseries.h"
5 #include "qabstractseries_p.h"
5 #include "qabstractseries_p.h"
6 #include <QStringList>
6 #include <QStringList>
7 #include <QAbstractSeries>
7 #include <QAbstractSeries>
8
8
9 class QModelIndex;
9 class QModelIndex;
10
10
11 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 QTCOMMERCIALCHART_BEGIN_NAMESPACE
12
12
13 // Container for series
13 // Container for series
14 class QBarSeriesPrivate : public QAbstractSeriesPrivate
14 class QBarSeriesPrivate : public QAbstractSeriesPrivate
15 {
15 {
16 Q_OBJECT
16 Q_OBJECT
17 public:
17 public:
18 QBarSeriesPrivate(QBarCategories categories, QBarSeries *parent);
18 QBarSeriesPrivate(QBarCategories categories, QBarSeries *parent);
19
19
20 void scaleDomain(Domain& domain);
20 void scaleDomain(Domain& domain);
21 Chart* createGraphics(ChartPresenter* presenter);
21 Chart* createGraphics(ChartPresenter* presenter);
22 QList<LegendMarker*> createLegendMarker(QLegend* legend);
22 QList<LegendMarker*> createLegendMarker(QLegend* legend);
23
23
24 bool setModel(QAbstractItemModel *model);
24 bool setModel(QAbstractItemModel *model);
25 void setModelMapping(int categories, int bottomBoundry, int topBoundry, Qt::Orientation orientation = Qt::Vertical);
25 void setModelMapping(int categories, int bottomBoundry, int topBoundry, Qt::Orientation orientation = Qt::Vertical);
26
26
27 QBarSet* barsetAt(int index);
27 QBarSet* barsetAt(int index);
28 QString categoryName(int category);
28 QString categoryName(int category);
29 qreal min();
29 qreal min();
30 qreal max();
30 qreal max();
31 qreal valueAt(int set, int category);
31 qreal valueAt(int set, int category);
32 qreal percentageAt(int set, int category);
32 qreal percentageAt(int set, int category);
33 qreal categorySum(int category);
33 qreal categorySum(int category);
34 qreal absoluteCategorySum(int category);
34 qreal absoluteCategorySum(int category);
35 qreal maxCategorySum();
35 qreal maxCategorySum();
36
36
37 Q_SIGNALS:
37 Q_SIGNALS:
38 void clicked(QBarSet *barset, QString category);
38 void clicked(QBarSet *barset, QString category);
39 void updatedBars();
39 void updatedBars();
40 void restructuredBars();
40 void restructuredBars();
41
41
42 private Q_SLOTS:
42 private Q_SLOTS:
43 // slots for updating bars when data in model changes
43 // slots for updating bars when data in model changes
44 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
44 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
45 void barsetChanged();
45 void barsetChanged();
46
46
47 protected:
47 protected:
48 QList<QBarSet *> m_barSets;
48 QList<QBarSet *> m_barSets;
49 QBarCategories m_categories;
49 QBarCategories m_categories;
50
50
51 int m_mapCategories;
51 int m_mapCategories;
52 int m_mapBarBottom;
52 int m_mapBarBottom;
53 int m_mapBarTop;
53 int m_mapBarTop;
54 Qt::Orientation m_mapOrientation;
55 private:
54 private:
56 Q_DECLARE_PUBLIC(QBarSeries)
55 Q_DECLARE_PUBLIC(QBarSeries)
57 };
56 };
58
57
59 QTCOMMERCIALCHART_END_NAMESPACE
58 QTCOMMERCIALCHART_END_NAMESPACE
60
59
61 #endif // QBARSERIESPRIVATE_P_H
60 #endif // QBARSERIESPRIVATE_P_H
@@ -1,650 +1,649
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qpieseries.h"
21 #include "qpieseries.h"
22 #include "qpieseries_p.h"
22 #include "qpieseries_p.h"
23 #include "qpieslice.h"
23 #include "qpieslice.h"
24 #include "pieslicedata_p.h"
24 #include "pieslicedata_p.h"
25 #include "chartdataset_p.h"
25 #include "chartdataset_p.h"
26 #include "charttheme_p.h"
26 #include "charttheme_p.h"
27 #include "chartanimator_p.h"
27 #include "chartanimator_p.h"
28 #include "legendmarker_p.h"
28 #include "legendmarker_p.h"
29 #include <QAbstractItemModel>
29 #include <QAbstractItemModel>
30
30
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32
32
33 /*!
33 /*!
34 \class QPieSeries
34 \class QPieSeries
35 \brief Pie series API for QtCommercial Charts
35 \brief Pie series API for QtCommercial Charts
36
36
37 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
37 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
38 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
38 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
39 The actual slice size is determined by that relative value.
39 The actual slice size is determined by that relative value.
40
40
41 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
41 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
42 These relate to the actual chart rectangle.
42 These relate to the actual chart rectangle.
43
43
44 By default the pie is defined as a full pie but it can also be a partial pie.
44 By default the pie is defined as a full pie but it can also be a partial pie.
45 This can be done by setting a starting angle and angle span to the series.
45 This can be done by setting a starting angle and angle span to the series.
46 Full pie is 360 degrees where 0 is at 12 a'clock.
46 Full pie is 360 degrees where 0 is at 12 a'clock.
47
47
48 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
48 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
49 \image examples_piechart.png
49 \image examples_piechart.png
50 */
50 */
51
51
52 /*!
52 /*!
53 \property QPieSeries::horizontalPosition
53 \property QPieSeries::horizontalPosition
54 \brief Defines the horizontal position of the pie.
54 \brief Defines the horizontal position of the pie.
55
55
56 The value is a relative value to the chart rectangle where:
56 The value is a relative value to the chart rectangle where:
57
57
58 \list
58 \list
59 \o 0.0 is the absolute left.
59 \o 0.0 is the absolute left.
60 \o 1.0 is the absolute right.
60 \o 1.0 is the absolute right.
61 \endlist
61 \endlist
62
62
63 Default value is 0.5 (center).
63 Default value is 0.5 (center).
64 */
64 */
65
65
66 /*!
66 /*!
67 \property QPieSeries::verticalPosition
67 \property QPieSeries::verticalPosition
68 \brief Defines the vertical position of the pie.
68 \brief Defines the vertical 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 top.
73 \o 0.0 is the absolute top.
74 \o 1.0 is the absolute bottom.
74 \o 1.0 is the absolute bottom.
75 \endlist
75 \endlist
76
76
77 Default value is 0.5 (center).
77 Default value is 0.5 (center).
78 */
78 */
79
79
80 /*!
80 /*!
81 \property QPieSeries::size
81 \property QPieSeries::size
82 \brief Defines the pie size.
82 \brief Defines the pie size.
83
83
84 The value is a relative value to the chart rectangle where:
84 The value is a relative value to the chart rectangle where:
85
85
86 \list
86 \list
87 \o 0.0 is the minimum size (pie not drawn).
87 \o 0.0 is the minimum size (pie not drawn).
88 \o 1.0 is the maximum size that can fit the chart.
88 \o 1.0 is the maximum size that can fit the chart.
89 \endlist
89 \endlist
90
90
91 Default value is 0.7.
91 Default value is 0.7.
92 */
92 */
93
93
94 /*!
94 /*!
95 \property QPieSeries::startAngle
95 \property QPieSeries::startAngle
96 \brief Defines the starting angle of the pie.
96 \brief Defines the starting angle of the pie.
97
97
98 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
98 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
99
99
100 Default is value is 0.
100 Default is value is 0.
101 */
101 */
102
102
103 /*!
103 /*!
104 \property QPieSeries::endAngle
104 \property QPieSeries::endAngle
105 \brief Defines the ending angle of the pie.
105 \brief Defines the ending angle of the pie.
106
106
107 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
107 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
108
108
109 Default is value is 360.
109 Default is value is 360.
110 */
110 */
111
111
112
112
113 /*!
113 /*!
114 Constructs a series object which is a child of \a parent.
114 Constructs a series object which is a child of \a parent.
115 */
115 */
116 QPieSeries::QPieSeries(QObject *parent) :
116 QPieSeries::QPieSeries(QObject *parent) :
117 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
117 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
118 {
118 {
119
119
120 }
120 }
121
121
122 /*!
122 /*!
123 Destroys the series and its slices.
123 Destroys the series and its slices.
124 */
124 */
125 QPieSeries::~QPieSeries()
125 QPieSeries::~QPieSeries()
126 {
126 {
127 // NOTE: d_prt destroyed by QObject
127 // NOTE: d_prt destroyed by QObject
128 }
128 }
129
129
130 /*!
130 /*!
131 Returns QChartSeries::SeriesTypePie.
131 Returns QChartSeries::SeriesTypePie.
132 */
132 */
133 QAbstractSeries::QSeriesType QPieSeries::type() const
133 QAbstractSeries::QSeriesType QPieSeries::type() const
134 {
134 {
135 return QAbstractSeries::SeriesTypePie;
135 return QAbstractSeries::SeriesTypePie;
136 }
136 }
137
137
138 /*!
138 /*!
139 Appends an array of \a slices to the series.
139 Appends an array of \a slices to the series.
140 Slice ownership is passed to the series.
140 Slice ownership is passed to the series.
141 */
141 */
142 void QPieSeries::append(QList<QPieSlice*> slices)
142 void QPieSeries::append(QList<QPieSlice*> slices)
143 {
143 {
144 Q_D(QPieSeries);
144 Q_D(QPieSeries);
145
145
146 foreach (QPieSlice* s, slices) {
146 foreach (QPieSlice* s, slices) {
147 s->setParent(this);
147 s->setParent(this);
148 d->m_slices << s;
148 d->m_slices << s;
149 }
149 }
150
150
151 d->updateDerivativeData();
151 d->updateDerivativeData();
152
152
153 foreach (QPieSlice* s, slices) {
153 foreach (QPieSlice* s, slices) {
154 connect(s, SIGNAL(changed()), d, SLOT(sliceChanged()));
154 connect(s, SIGNAL(changed()), d, SLOT(sliceChanged()));
155 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
155 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
156 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
156 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
157 }
157 }
158
158
159 emit d->added(slices);
159 emit d->added(slices);
160 }
160 }
161
161
162 /*!
162 /*!
163 Appends a single \a slice to the series.
163 Appends a single \a slice to the series.
164 Slice ownership is passed to the series.
164 Slice ownership is passed to the series.
165 */
165 */
166 void QPieSeries::append(QPieSlice* slice)
166 void QPieSeries::append(QPieSlice* slice)
167 {
167 {
168 append(QList<QPieSlice*>() << slice);
168 append(QList<QPieSlice*>() << slice);
169 }
169 }
170
170
171 /*!
171 /*!
172 Appends a single \a slice to the series and returns a reference to the series.
172 Appends a single \a slice to the series and returns a reference to the series.
173 Slice ownership is passed to the series.
173 Slice ownership is passed to the series.
174 */
174 */
175 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
175 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
176 {
176 {
177 append(slice);
177 append(slice);
178 return *this;
178 return *this;
179 }
179 }
180
180
181
181
182 /*!
182 /*!
183 Appends a single slice to the series with give \a value and \a name.
183 Appends a single slice to the series with give \a value and \a name.
184 Slice ownership is passed to the series.
184 Slice ownership is passed to the series.
185 */
185 */
186 QPieSlice* QPieSeries::append(qreal value, QString name)
186 QPieSlice* QPieSeries::append(qreal value, QString name)
187 {
187 {
188 QPieSlice* slice = new QPieSlice(value, name);
188 QPieSlice* slice = new QPieSlice(value, name);
189 append(slice);
189 append(slice);
190 return slice;
190 return slice;
191 }
191 }
192
192
193 /*!
193 /*!
194 Inserts a single \a slice to the series before the slice at \a index position.
194 Inserts a single \a slice to the series before the slice at \a index position.
195 Slice ownership is passed to the series.
195 Slice ownership is passed to the series.
196 */
196 */
197 void QPieSeries::insert(int index, QPieSlice* slice)
197 void QPieSeries::insert(int index, QPieSlice* slice)
198 {
198 {
199 Q_D(QPieSeries);
199 Q_D(QPieSeries);
200 Q_ASSERT(index <= d->m_slices.count());
200 Q_ASSERT(index <= d->m_slices.count());
201 slice->setParent(this);
201 slice->setParent(this);
202 d->m_slices.insert(index, slice);
202 d->m_slices.insert(index, slice);
203
203
204 d->updateDerivativeData();
204 d->updateDerivativeData();
205
205
206 connect(slice, SIGNAL(changed()), d, SLOT(sliceChanged()));
206 connect(slice, SIGNAL(changed()), d, SLOT(sliceChanged()));
207 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
207 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
208 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
208 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
209
209
210 emit d->added(QList<QPieSlice*>() << slice);
210 emit d->added(QList<QPieSlice*>() << slice);
211 }
211 }
212
212
213 /*!
213 /*!
214 Removes a single \a slice from the series and deletes the slice.
214 Removes a single \a slice from the series and deletes the slice.
215
215
216 Do not reference the pointer after this call.
216 Do not reference the pointer after this call.
217 */
217 */
218 void QPieSeries::remove(QPieSlice* slice)
218 void QPieSeries::remove(QPieSlice* slice)
219 {
219 {
220 Q_D(QPieSeries);
220 Q_D(QPieSeries);
221 if (!d->m_slices.removeOne(slice)) {
221 if (!d->m_slices.removeOne(slice)) {
222 Q_ASSERT(0); // TODO: how should this be reported?
222 Q_ASSERT(0); // TODO: how should this be reported?
223 return;
223 return;
224 }
224 }
225
225
226 d->updateDerivativeData();
226 d->updateDerivativeData();
227
227
228 emit d->removed(QList<QPieSlice*>() << slice);
228 emit d->removed(QList<QPieSlice*>() << slice);
229
229
230 delete slice;
230 delete slice;
231 slice = 0;
231 slice = 0;
232 }
232 }
233
233
234 /*!
234 /*!
235 Clears all slices from the series.
235 Clears all slices from the series.
236 */
236 */
237 void QPieSeries::clear()
237 void QPieSeries::clear()
238 {
238 {
239 Q_D(QPieSeries);
239 Q_D(QPieSeries);
240 if (d->m_slices.count() == 0)
240 if (d->m_slices.count() == 0)
241 return;
241 return;
242
242
243 QList<QPieSlice*> slices = d->m_slices;
243 QList<QPieSlice*> slices = d->m_slices;
244 foreach (QPieSlice* s, d->m_slices) {
244 foreach (QPieSlice* s, d->m_slices) {
245 d->m_slices.removeOne(s);
245 d->m_slices.removeOne(s);
246 delete s;
246 delete s;
247 }
247 }
248
248
249 d->updateDerivativeData();
249 d->updateDerivativeData();
250
250
251 emit d->removed(slices);
251 emit d->removed(slices);
252 }
252 }
253
253
254 /*!
254 /*!
255 returns the number of the slices in this series.
255 returns the number of the slices in this series.
256 */
256 */
257 int QPieSeries::count() const
257 int QPieSeries::count() const
258 {
258 {
259 Q_D(const QPieSeries);
259 Q_D(const QPieSeries);
260 return d->m_slices.count();
260 return d->m_slices.count();
261 }
261 }
262
262
263 /*!
263 /*!
264 Returns true is the series is empty.
264 Returns true is the series is empty.
265 */
265 */
266 bool QPieSeries::isEmpty() const
266 bool QPieSeries::isEmpty() const
267 {
267 {
268 Q_D(const QPieSeries);
268 Q_D(const QPieSeries);
269 return d->m_slices.isEmpty();
269 return d->m_slices.isEmpty();
270 }
270 }
271
271
272 /*!
272 /*!
273 Returns a list of slices that belong to this series.
273 Returns a list of slices that belong to this series.
274 */
274 */
275 QList<QPieSlice*> QPieSeries::slices() const
275 QList<QPieSlice*> QPieSeries::slices() const
276 {
276 {
277 Q_D(const QPieSeries);
277 Q_D(const QPieSeries);
278 return d->m_slices;
278 return d->m_slices;
279 }
279 }
280
280
281 void QPieSeries::setHorizontalPosition(qreal relativePosition)
281 void QPieSeries::setHorizontalPosition(qreal relativePosition)
282 {
282 {
283 Q_D(QPieSeries);
283 Q_D(QPieSeries);
284 if (d->setRealValue(d->m_pieRelativeHorPos, relativePosition, 1.0))
284 if (d->setRealValue(d->m_pieRelativeHorPos, relativePosition, 1.0))
285 emit d->piePositionChanged();
285 emit d->piePositionChanged();
286 }
286 }
287
287
288 void QPieSeries::setVerticalPosition(qreal relativePosition)
288 void QPieSeries::setVerticalPosition(qreal relativePosition)
289 {
289 {
290 Q_D(QPieSeries);
290 Q_D(QPieSeries);
291 if (d->setRealValue(d->m_pieRelativeVerPos, relativePosition, 1.0))
291 if (d->setRealValue(d->m_pieRelativeVerPos, relativePosition, 1.0))
292 emit d->piePositionChanged();
292 emit d->piePositionChanged();
293 }
293 }
294
294
295 qreal QPieSeries::horizontalPosition() const
295 qreal QPieSeries::horizontalPosition() const
296 {
296 {
297 Q_D(const QPieSeries);
297 Q_D(const QPieSeries);
298 return d->m_pieRelativeHorPos;
298 return d->m_pieRelativeHorPos;
299 }
299 }
300
300
301 qreal QPieSeries::verticalPosition() const
301 qreal QPieSeries::verticalPosition() const
302 {
302 {
303 Q_D(const QPieSeries);
303 Q_D(const QPieSeries);
304 return d->m_pieRelativeVerPos;
304 return d->m_pieRelativeVerPos;
305 }
305 }
306
306
307 void QPieSeries::setPieSize(qreal relativeSize)
307 void QPieSeries::setPieSize(qreal relativeSize)
308 {
308 {
309 Q_D(QPieSeries);
309 Q_D(QPieSeries);
310 if (d->setRealValue(d->m_pieRelativeSize, relativeSize, 1.0))
310 if (d->setRealValue(d->m_pieRelativeSize, relativeSize, 1.0))
311 emit d->pieSizeChanged();
311 emit d->pieSizeChanged();
312 }
312 }
313
313
314 qreal QPieSeries::pieSize() const
314 qreal QPieSeries::pieSize() const
315 {
315 {
316 Q_D(const QPieSeries);
316 Q_D(const QPieSeries);
317 return d->m_pieRelativeSize;
317 return d->m_pieRelativeSize;
318 }
318 }
319
319
320
320
321 void QPieSeries::setPieStartAngle(qreal angle)
321 void QPieSeries::setPieStartAngle(qreal angle)
322 {
322 {
323 Q_D(QPieSeries);
323 Q_D(QPieSeries);
324 if (d->setRealValue(d->m_pieStartAngle, angle, d->m_pieEndAngle))
324 if (d->setRealValue(d->m_pieStartAngle, angle, d->m_pieEndAngle))
325 d->updateDerivativeData();
325 d->updateDerivativeData();
326 }
326 }
327
327
328 qreal QPieSeries::pieStartAngle() const
328 qreal QPieSeries::pieStartAngle() const
329 {
329 {
330 Q_D(const QPieSeries);
330 Q_D(const QPieSeries);
331 return d->m_pieStartAngle;
331 return d->m_pieStartAngle;
332 }
332 }
333
333
334 /*!
334 /*!
335 Sets the end angle of the pie.
335 Sets the end angle of the pie.
336
336
337 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
337 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
338
338
339 \a angle must be greater than start angle.
339 \a angle must be greater than start angle.
340
340
341 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
341 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
342 */
342 */
343 void QPieSeries::setPieEndAngle(qreal angle)
343 void QPieSeries::setPieEndAngle(qreal angle)
344 {
344 {
345 Q_D(QPieSeries);
345 Q_D(QPieSeries);
346
346
347 if (d->setRealValue(d->m_pieEndAngle, angle, 360.0, d->m_pieStartAngle))
347 if (d->setRealValue(d->m_pieEndAngle, angle, 360.0, d->m_pieStartAngle))
348 d->updateDerivativeData();
348 d->updateDerivativeData();
349 }
349 }
350
350
351 /*!
351 /*!
352 Returns the end angle of the pie.
352 Returns the end angle of the pie.
353
353
354 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
354 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
355
355
356 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
356 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
357 */
357 */
358 qreal QPieSeries::pieEndAngle() const
358 qreal QPieSeries::pieEndAngle() const
359 {
359 {
360 Q_D(const QPieSeries);
360 Q_D(const QPieSeries);
361 return d->m_pieEndAngle;
361 return d->m_pieEndAngle;
362 }
362 }
363
363
364 /*!
364 /*!
365 Sets the all the slice labels \a visible or invisible.
365 Sets the all the slice labels \a visible or invisible.
366
366
367 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
367 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
368 */
368 */
369 void QPieSeries::setLabelsVisible(bool visible)
369 void QPieSeries::setLabelsVisible(bool visible)
370 {
370 {
371 Q_D(QPieSeries);
371 Q_D(QPieSeries);
372 foreach (QPieSlice* s, d->m_slices)
372 foreach (QPieSlice* s, d->m_slices)
373 s->setLabelVisible(visible);
373 s->setLabelVisible(visible);
374 }
374 }
375
375
376 /*!
376 /*!
377 Returns the sum of all slice values in this series.
377 Returns the sum of all slice values in this series.
378
378
379 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
379 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
380 */
380 */
381 qreal QPieSeries::sum() const
381 qreal QPieSeries::sum() const
382 {
382 {
383 Q_D(const QPieSeries);
383 Q_D(const QPieSeries);
384 return d->m_sum;
384 return d->m_sum;
385 }
385 }
386
386
387 /*!
387 /*!
388 \fn void QPieSeries::clicked(QPieSlice* slice)
388 \fn void QPieSeries::clicked(QPieSlice* slice)
389
389
390 This signal is emitted when a \a slice has been clicked.
390 This signal is emitted when a \a slice has been clicked.
391
391
392 \sa QPieSlice::clicked()
392 \sa QPieSlice::clicked()
393 */
393 */
394
394
395 /*!
395 /*!
396 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
396 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
397
397
398 This signal is emitted when user has hovered over or away from the \a slice.
398 This signal is emitted when user has hovered over or away from the \a slice.
399
399
400 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
400 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
401
401
402 \sa QPieSlice::hovered()
402 \sa QPieSlice::hovered()
403 */
403 */
404
404
405 /*!
405 /*!
406 \fn bool QPieSeries::setModel(QAbstractItemModel *model)
406 \fn bool QPieSeries::setModel(QAbstractItemModel *model)
407 Sets the \a model to be used as a data source
407 Sets the \a model to be used as a data source
408 */
408 */
409 bool QPieSeries::setModel(QAbstractItemModel* model)
409 bool QPieSeries::setModel(QAbstractItemModel* model)
410 {
410 {
411 Q_D(QPieSeries);
411 Q_D(QPieSeries);
412 // disconnect signals from old model
412 // disconnect signals from old model
413 if(d->m_model)
413 if(d->m_model)
414 {
414 {
415 disconnect(d->m_model, 0, this, 0);
415 disconnect(d->m_model, 0, this, 0);
416 d->m_mapValues = -1;
416 d->m_mapValues = -1;
417 d->m_mapLabels = -1;
417 d->m_mapLabels = -1;
418 d->m_mapOrientation = Qt::Vertical;
418 d->m_mapOrientation = Qt::Vertical;
419 }
419 }
420
420
421 // set new model
421 // set new model
422 if(model)
422 if(model)
423 {
423 {
424 d->m_model = model;
424 d->m_model = model;
425 return true;
425 return true;
426 }
426 }
427 else
427 else
428 {
428 {
429 d->m_model = 0;
429 d->m_model = 0;
430 return false;
430 return false;
431 }
431 }
432 }
432 }
433
433
434 /*!
434 /*!
435 \fn bool QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
435 \fn bool QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
436 Sets column/row specified by \a modelValuesLine to be used as a list of pie slice values for the pie.
436 Sets column/row specified by \a modelValuesLine to be used as a list of pie slice values for the pie.
437 Parameter \a modelValuesLine indicates the column/row where the values for the pie slices are located in the model.
437 Parameter \a modelValuesLine indicates the column/row where the values for the pie slices are located in the model.
438 Parameter \a modelLabelsLine indicates the column/row where the labels for the pie slices are located in the model.
438 Parameter \a modelLabelsLine indicates the column/row where the labels for the pie slices are located in the model.
439 The \a orientation parameter specifies whether the data is in columns or in rows.
439 The \a orientation parameter specifies whether the data is in columns or in rows.
440 */
440 */
441 void QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
441 void QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
442 {
442 {
443 Q_D(QPieSeries);
443 Q_D(QPieSeries);
444
444
445 if (d->m_model == 0)
445 if (d->m_model == 0)
446 return;
446 return;
447
447
448 d->m_mapValues = modelValuesLine;
448 d->m_mapValues = modelValuesLine;
449 d->m_mapLabels = modelLabelsLine;
449 d->m_mapLabels = modelLabelsLine;
450 d->m_mapOrientation = orientation;
450 d->m_mapOrientation = orientation;
451
451
452 // connect the signals
452 // connect the signals
453 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
453 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
454
454
455
455
456 // create the initial slices set
456 // create the initial slices set
457 if (d->m_mapOrientation == Qt::Vertical) {
457 if (d->m_mapOrientation == Qt::Vertical) {
458 for (int i = 0; i < d->m_model->rowCount(); i++)
458 for (int i = 0; i < d->m_model->rowCount(); i++)
459 append(d->m_model->data(d->m_model->index(i, d->m_mapValues), Qt::DisplayRole).toDouble(), d->m_model->data(d->m_model->index(i, d->m_mapLabels), Qt::DisplayRole).toString());
459 append(d->m_model->data(d->m_model->index(i, d->m_mapValues), Qt::DisplayRole).toDouble(), d->m_model->data(d->m_model->index(i, d->m_mapLabels), Qt::DisplayRole).toString());
460 } else {
460 } else {
461 for (int i = 0; i < d->m_model->columnCount(); i++)
461 for (int i = 0; i < d->m_model->columnCount(); i++)
462 append(d->m_model->data(d->m_model->index(d->m_mapValues, i), Qt::DisplayRole).toDouble(), d->m_model->data(d->m_model->index(d->m_mapLabels, i), Qt::DisplayRole).toString());
462 append(d->m_model->data(d->m_model->index(d->m_mapValues, i), Qt::DisplayRole).toDouble(), d->m_model->data(d->m_model->index(d->m_mapLabels, i), Qt::DisplayRole).toString());
463 }
463 }
464 }
464 }
465
465
466 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
466 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
467
467
468
468
469 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
469 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
470 QAbstractSeriesPrivate(parent),
470 QAbstractSeriesPrivate(parent),
471 m_pieRelativeHorPos(0.5),
471 m_pieRelativeHorPos(0.5),
472 m_pieRelativeVerPos(0.5),
472 m_pieRelativeVerPos(0.5),
473 m_pieRelativeSize(0.7),
473 m_pieRelativeSize(0.7),
474 m_pieStartAngle(0),
474 m_pieStartAngle(0),
475 m_pieEndAngle(360),
475 m_pieEndAngle(360),
476 m_sum(0),
476 m_sum(0),
477 m_mapValues(0),
477 m_mapValues(0),
478 m_mapLabels(0),
478 m_mapLabels(0)
479 m_mapOrientation(Qt::Vertical)
480 {
479 {
481
480
482 }
481 }
483
482
484 QPieSeriesPrivate::~QPieSeriesPrivate()
483 QPieSeriesPrivate::~QPieSeriesPrivate()
485 {
484 {
486
485
487 }
486 }
488
487
489 void QPieSeriesPrivate::updateDerivativeData()
488 void QPieSeriesPrivate::updateDerivativeData()
490 {
489 {
491 m_sum = 0;
490 m_sum = 0;
492
491
493 // nothing to do?
492 // nothing to do?
494 if (m_slices.count() == 0)
493 if (m_slices.count() == 0)
495 return;
494 return;
496
495
497 // calculate sum of all slices
496 // calculate sum of all slices
498 foreach (QPieSlice* s, m_slices)
497 foreach (QPieSlice* s, m_slices)
499 m_sum += s->value();
498 m_sum += s->value();
500
499
501 // nothing to show..
500 // nothing to show..
502 if (qFuzzyIsNull(m_sum))
501 if (qFuzzyIsNull(m_sum))
503 return;
502 return;
504
503
505 // update slice attributes
504 // update slice attributes
506 qreal sliceAngle = m_pieStartAngle;
505 qreal sliceAngle = m_pieStartAngle;
507 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
506 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
508 QVector<QPieSlice*> changed;
507 QVector<QPieSlice*> changed;
509 foreach (QPieSlice* s, m_slices) {
508 foreach (QPieSlice* s, m_slices) {
510
509
511 PieSliceData data = PieSliceData::data(s);
510 PieSliceData data = PieSliceData::data(s);
512 data.m_percentage = s->value() / m_sum;
511 data.m_percentage = s->value() / m_sum;
513 data.m_angleSpan = pieSpan * data.m_percentage;
512 data.m_angleSpan = pieSpan * data.m_percentage;
514 data.m_startAngle = sliceAngle;
513 data.m_startAngle = sliceAngle;
515 sliceAngle += data.m_angleSpan;
514 sliceAngle += data.m_angleSpan;
516
515
517 if (PieSliceData::data(s) != data) {
516 if (PieSliceData::data(s) != data) {
518 PieSliceData::data(s) = data;
517 PieSliceData::data(s) = data;
519 changed << s;
518 changed << s;
520 }
519 }
521 }
520 }
522
521
523 // emit signals
522 // emit signals
524 foreach (QPieSlice* s, changed)
523 foreach (QPieSlice* s, changed)
525 PieSliceData::data(s).emitChangedSignal(s);
524 PieSliceData::data(s).emitChangedSignal(s);
526 }
525 }
527
526
528 QPieSeriesPrivate* QPieSeriesPrivate::seriesData(QPieSeries &series)
527 QPieSeriesPrivate* QPieSeriesPrivate::seriesData(QPieSeries &series)
529 {
528 {
530 return series.d_func();
529 return series.d_func();
531 }
530 }
532
531
533 void QPieSeriesPrivate::sliceChanged()
532 void QPieSeriesPrivate::sliceChanged()
534 {
533 {
535 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
534 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
536 updateDerivativeData();
535 updateDerivativeData();
537 }
536 }
538
537
539 void QPieSeriesPrivate::sliceClicked()
538 void QPieSeriesPrivate::sliceClicked()
540 {
539 {
541 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
540 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
542 Q_ASSERT(m_slices.contains(slice));
541 Q_ASSERT(m_slices.contains(slice));
543 Q_Q(QPieSeries);
542 Q_Q(QPieSeries);
544 emit q->clicked(slice);
543 emit q->clicked(slice);
545 }
544 }
546
545
547 void QPieSeriesPrivate::sliceHovered(bool state)
546 void QPieSeriesPrivate::sliceHovered(bool state)
548 {
547 {
549 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
548 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
550 Q_ASSERT(m_slices.contains(slice));
549 Q_ASSERT(m_slices.contains(slice));
551 Q_Q(QPieSeries);
550 Q_Q(QPieSeries);
552 emit q->hovered(slice, state);
551 emit q->hovered(slice, state);
553 }
552 }
554
553
555 void QPieSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
554 void QPieSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
556 {
555 {
557 Q_UNUSED(bottomRight)
556 Q_UNUSED(bottomRight)
558
557
559 if (m_mapOrientation == Qt::Vertical)
558 if (m_mapOrientation == Qt::Vertical)
560 {
559 {
561 if (topLeft.column() == m_mapValues)
560 if (topLeft.column() == m_mapValues)
562 if (m_mapValues == m_mapLabels)
561 if (m_mapValues == m_mapLabels)
563 {
562 {
564 m_slices.at(topLeft.row())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
563 m_slices.at(topLeft.row())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
565 m_slices.at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
564 m_slices.at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
566 }
565 }
567 else
566 else
568 {
567 {
569 m_slices.at(topLeft.row())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
568 m_slices.at(topLeft.row())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
570 }
569 }
571 else if (topLeft.column() == m_mapLabels)
570 else if (topLeft.column() == m_mapLabels)
572 m_slices.at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
571 m_slices.at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
573 }
572 }
574 else
573 else
575 {
574 {
576 if (topLeft.row() == m_mapValues)
575 if (topLeft.row() == m_mapValues)
577 if (m_mapValues == m_mapLabels)
576 if (m_mapValues == m_mapLabels)
578 {
577 {
579 m_slices.at(topLeft.column())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
578 m_slices.at(topLeft.column())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
580 m_slices.at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
579 m_slices.at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
581 }
580 }
582 else
581 else
583 {
582 {
584 m_slices.at(topLeft.column())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
583 m_slices.at(topLeft.column())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
585 }
584 }
586 else if (topLeft.row() == m_mapLabels)
585 else if (topLeft.row() == m_mapLabels)
587 m_slices.at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
586 m_slices.at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
588 }
587 }
589 }
588 }
590
589
591 bool QPieSeriesPrivate::setRealValue(qreal &value, qreal newValue, qreal max, qreal min)
590 bool QPieSeriesPrivate::setRealValue(qreal &value, qreal newValue, qreal max, qreal min)
592 {
591 {
593 // Remove rounding errors
592 // Remove rounding errors
594 qreal roundedValue = newValue;
593 qreal roundedValue = newValue;
595 if (qFuzzyIsNull(min) && qFuzzyIsNull(newValue))
594 if (qFuzzyIsNull(min) && qFuzzyIsNull(newValue))
596 roundedValue = 0.0;
595 roundedValue = 0.0;
597 else if (qFuzzyCompare(newValue, max))
596 else if (qFuzzyCompare(newValue, max))
598 roundedValue = max;
597 roundedValue = max;
599 else if (qFuzzyCompare(newValue, min))
598 else if (qFuzzyCompare(newValue, min))
600 roundedValue = min;
599 roundedValue = min;
601
600
602 // Check if the position is valid after removing the rounding errors
601 // Check if the position is valid after removing the rounding errors
603 if (roundedValue < min || roundedValue > max) {
602 if (roundedValue < min || roundedValue > max) {
604 qWarning("QPieSeries: Illegal value");
603 qWarning("QPieSeries: Illegal value");
605 return false;
604 return false;
606 }
605 }
607
606
608 if (!qFuzzyIsNull(value - roundedValue)) {
607 if (!qFuzzyIsNull(value - roundedValue)) {
609 value = roundedValue;
608 value = roundedValue;
610 return true;
609 return true;
611 }
610 }
612
611
613 // The change was so small it is considered a rounding error
612 // The change was so small it is considered a rounding error
614 return false;
613 return false;
615 }
614 }
616
615
617 void QPieSeriesPrivate::scaleDomain(Domain& domain)
616 void QPieSeriesPrivate::scaleDomain(Domain& domain)
618 {
617 {
619 Q_UNUSED(domain);
618 Q_UNUSED(domain);
620 #ifndef QT_NO_DEBUG
619 #ifndef QT_NO_DEBUG
621 qWarning() << __FILE__<<__FUNCTION__<<"not implemented";
620 qWarning() << __FILE__<<__FUNCTION__<<"not implemented";
622 #endif
621 #endif
623 }
622 }
624
623
625 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
624 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
626 {
625 {
627 Q_Q(QPieSeries);
626 Q_Q(QPieSeries);
628 PieChartItem* pie = new PieChartItem(q,presenter);
627 PieChartItem* pie = new PieChartItem(q,presenter);
629 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
628 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
630 presenter->animator()->addAnimation(pie);
629 presenter->animator()->addAnimation(pie);
631 }
630 }
632 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
631 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
633 return pie;
632 return pie;
634 }
633 }
635
634
636 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
635 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
637 {
636 {
638 Q_Q(QPieSeries);
637 Q_Q(QPieSeries);
639 QList<LegendMarker*> markers;
638 QList<LegendMarker*> markers;
640 foreach(QPieSlice* slice, q->slices()) {
639 foreach(QPieSlice* slice, q->slices()) {
641 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
640 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
642 markers << marker;
641 markers << marker;
643 }
642 }
644 return markers;
643 return markers;
645 }
644 }
646
645
647 #include "moc_qpieseries.cpp"
646 #include "moc_qpieseries.cpp"
648 #include "moc_qpieseries_p.cpp"
647 #include "moc_qpieseries_p.cpp"
649
648
650 QTCOMMERCIALCHART_END_NAMESPACE
649 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,82 +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 #ifndef QPIESERIES_P_H
21 #ifndef QPIESERIES_P_H
22 #define QPIESERIES_P_H
22 #define QPIESERIES_P_H
23
23
24 #include "qpieseries.h"
24 #include "qpieseries.h"
25 #include "qabstractseries_p.h"
25 #include "qabstractseries_p.h"
26
26
27 class QModelIndex;
27 class QModelIndex;
28
28
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 class QLegendPrivate;
30 class QLegendPrivate;
31
31
32 class QPieSeriesPrivate : public QAbstractSeriesPrivate
32 class QPieSeriesPrivate : public QAbstractSeriesPrivate
33 {
33 {
34 Q_OBJECT
34 Q_OBJECT
35
35
36 public:
36 public:
37 QPieSeriesPrivate(QPieSeries *parent);
37 QPieSeriesPrivate(QPieSeries *parent);
38 ~QPieSeriesPrivate();
38 ~QPieSeriesPrivate();
39
39
40 void scaleDomain(Domain& domain);
40 void scaleDomain(Domain& domain);
41 Chart* createGraphics(ChartPresenter *presenter);
41 Chart* createGraphics(ChartPresenter *presenter);
42 QList<LegendMarker*> createLegendMarker(QLegend *legend);
42 QList<LegendMarker*> createLegendMarker(QLegend *legend);
43
43
44 void updateDerivativeData();
44 void updateDerivativeData();
45
45
46 static QPieSeriesPrivate* seriesData(QPieSeries &series);
46 static QPieSeriesPrivate* seriesData(QPieSeries &series);
47
47
48 Q_SIGNALS:
48 Q_SIGNALS:
49 void added(QList<QPieSlice*> slices);
49 void added(QList<QPieSlice*> slices);
50 void removed(QList<QPieSlice*> slices);
50 void removed(QList<QPieSlice*> slices);
51 void piePositionChanged();
51 void piePositionChanged();
52 void pieSizeChanged();
52 void pieSizeChanged();
53
53
54 public Q_SLOTS:
54 public Q_SLOTS:
55 void sliceChanged();
55 void sliceChanged();
56 void sliceClicked();
56 void sliceClicked();
57 void sliceHovered(bool state);
57 void sliceHovered(bool state);
58 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
58 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
59 bool setRealValue(qreal &value, qreal newValue, qreal max, qreal min = 0.0);
59 bool setRealValue(qreal &value, qreal newValue, qreal max, qreal min = 0.0);
60
60
61 public:
61 public:
62 QList<QPieSlice*> m_slices;
62 QList<QPieSlice*> m_slices;
63 qreal m_pieRelativeHorPos;
63 qreal m_pieRelativeHorPos;
64 qreal m_pieRelativeVerPos;
64 qreal m_pieRelativeVerPos;
65 qreal m_pieRelativeSize;
65 qreal m_pieRelativeSize;
66 qreal m_pieStartAngle;
66 qreal m_pieStartAngle;
67 qreal m_pieEndAngle;
67 qreal m_pieEndAngle;
68 qreal m_sum;
68 qreal m_sum;
69
69
70 // model map
70 // model map
71 int m_mapValues;
71 int m_mapValues;
72 int m_mapLabels;
72 int m_mapLabels;
73 Qt::Orientation m_mapOrientation;
74
73
75 private:
74 private:
76 friend class QLegendPrivate;
75 friend class QLegendPrivate;
77 Q_DECLARE_PUBLIC(QPieSeries)
76 Q_DECLARE_PUBLIC(QPieSeries)
78 };
77 };
79
78
80 QTCOMMERCIALCHART_END_NAMESPACE
79 QTCOMMERCIALCHART_END_NAMESPACE
81
80
82 #endif // QPIESERIES_P_H
81 #endif // QPIESERIES_P_H
@@ -1,146 +1,153
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 "qabstractseries.h"
21 #include "qabstractseries.h"
22 #include "qabstractseries_p.h"
22 #include "qabstractseries_p.h"
23
23
24 QTCOMMERCIALCHART_BEGIN_NAMESPACE
24 QTCOMMERCIALCHART_BEGIN_NAMESPACE
25
25
26 /*!
26 /*!
27 \class QAbstractSeries
27 \class QAbstractSeries
28 \brief Base class for all QtCommercial Chart series.
28 \brief Base class for all QtCommercial Chart series.
29 \mainclass
29 \mainclass
30
30
31 Usually you use the series type specific inherited classes instead of the base class.
31 Usually you use the series type specific inherited classes instead of the base class.
32 \sa QXYSeries, QLineSeries, QSplineSeries, QScatterSeries, QAreaSeries, QBarSeries, QStackedBarSeries,
32 \sa QXYSeries, QLineSeries, QSplineSeries, QScatterSeries, QAreaSeries, QBarSeries, QStackedBarSeries,
33 QPercentBarSeries, QPieSeries
33 QPercentBarSeries, QPieSeries
34 */
34 */
35
35
36 /*!
36 /*!
37 \enum QAbstractSeries::QSeriesType
37 \enum QAbstractSeries::QSeriesType
38
38
39 The type of the series object.
39 The type of the series object.
40
40
41 \value SeriesTypeLine
41 \value SeriesTypeLine
42 \value SeriesTypeArea
42 \value SeriesTypeArea
43 \value SeriesTypeBar
43 \value SeriesTypeBar
44 \value SeriesTypeStackedBar
44 \value SeriesTypeStackedBar
45 \value SeriesTypePercentBar
45 \value SeriesTypePercentBar
46 \value SeriesTypePie
46 \value SeriesTypePie
47 \value SeriesTypeScatter
47 \value SeriesTypeScatter
48 \value SeriesTypeSpline
48 \value SeriesTypeSpline
49 */
49 */
50
50
51 /*!
51 /*!
52 \fn QSeriesType QAbstractSeries::type() const
52 \fn QSeriesType QAbstractSeries::type() const
53 \brief The type of the series.
53 \brief The type of the series.
54 */
54 */
55
55
56 /*!
56 /*!
57 \fn bool QAbstractSeries::setModel(QAbstractItemModel *model)
57 \fn bool QAbstractSeries::setModel(QAbstractItemModel *model)
58 \brief Use the \a model to provide data for the series. The model overrides possible user data
58 \brief Use the \a model to provide data for the series. The model overrides possible user data
59 set with QChartSeries type specific data setters. For example if you call both
59 set with QChartSeries type specific data setters. For example if you call both
60 QScatterSeries::addData() and QScatterSeries::setModel, only the data provided by the model is
60 QScatterSeries::addData() and QScatterSeries::setModel, only the data provided by the model is
61 used by the series. Returns true if the model is valid for the series.
61 used by the series. Returns true if the model is valid for the series.
62 */
62 */
63
63
64 /*!
64 /*!
65 \property QAbstractSeries::name
65 \property QAbstractSeries::name
66 \brief name of the series property
66 \brief name of the series property
67 */
67 */
68
68
69 /*!
69 /*!
70 \fn void QAbstractSeries::setName(const QString& name)
70 \fn void QAbstractSeries::setName(const QString& name)
71 \brief Sets a \a name for the series.
71 \brief Sets a \a name for the series.
72
72
73 The name of a series is shown in the legend for QXYSeries.
73 The name of a series is shown in the legend for QXYSeries.
74 \sa QChart::setTitle()
74 \sa QChart::setTitle()
75 \sa QPieSlice::setLabel()
75 \sa QPieSlice::setLabel()
76 \sa QBarSet::setName()
76 \sa QBarSet::setName()
77 */
77 */
78
78
79 /*!
79 /*!
80 \internal
80 \internal
81 \brief Constructs ChartSeries object with \a parent.
81 \brief Constructs ChartSeries object with \a parent.
82 */
82 */
83 QAbstractSeries::QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent) :
83 QAbstractSeries::QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent) :
84 QObject(parent),
84 QObject(parent),
85 d_ptr(&d)
85 d_ptr(&d)
86 {
86 {
87 }
87 }
88
88
89 /*!
89 /*!
90 \brief Virtual destructor for the chart series.
90 \brief Virtual destructor for the chart series.
91 */
91 */
92 QAbstractSeries::~QAbstractSeries()
92 QAbstractSeries::~QAbstractSeries()
93 {
93 {
94 }
94 }
95
95
96 /*!
96 /*!
97 \brief Returns the pointer to the model that is used as the series data source
97 \brief Returns the pointer to the model that is used as the series data source
98 */
98 */
99 QAbstractItemModel* QAbstractSeries::model() const
99 QAbstractItemModel* QAbstractSeries::model() const
100 {
100 {
101 return d_ptr->m_model;
101 return d_ptr->m_model;
102 }
102 }
103
103
104 int QAbstractSeries::mapFirst() const
104 int QAbstractSeries::mapFirst() const
105 {
105 {
106 return d_ptr->m_mapFirst;
106 return d_ptr->m_mapFirst;
107 }
107 }
108
108 int QAbstractSeries::mapCount() const
109 int QAbstractSeries::mapCount() const
109 {
110 {
110 return d_ptr->m_mapCount;
111 return d_ptr->m_mapCount;
111 }
112 }
112
113
114 int QAbstractSeries::mapOrientation() const
115 {
116 return d_ptr->m_mapOrientation;
117 }
118
113 void QAbstractSeries::setName(const QString& name)
119 void QAbstractSeries::setName(const QString& name)
114 {
120 {
115 d_ptr->m_name = name;
121 d_ptr->m_name = name;
116 }
122 }
117
123
118 /*!
124 /*!
119 \brief Returns the name of the series.
125 \brief Returns the name of the series.
120 \sa setName()
126 \sa setName()
121 */
127 */
122 QString QAbstractSeries::name() const
128 QString QAbstractSeries::name() const
123 {
129 {
124 return d_ptr->m_name;
130 return d_ptr->m_name;
125 }
131 }
126
132
127 ///////////////////////////////////////////////////////////////////////////////////////////////////
133 ///////////////////////////////////////////////////////////////////////////////////////////////////
128
134
129 QAbstractSeriesPrivate::QAbstractSeriesPrivate(QAbstractSeries* q):
135 QAbstractSeriesPrivate::QAbstractSeriesPrivate(QAbstractSeries* q):
130 q_ptr(q),
136 q_ptr(q),
131 m_model(0),
137 m_model(0),
132 m_mapFirst(0),
138 m_mapFirst(0),
133 m_mapCount(-1)
139 m_mapCount(-1),
140 m_mapOrientation(Qt::Vertical)
134 {
141 {
135 }
142 }
136
143
137 QAbstractSeriesPrivate::~QAbstractSeriesPrivate()
144 QAbstractSeriesPrivate::~QAbstractSeriesPrivate()
138 {
145 {
139 }
146 }
140
147
141 #include "moc_qabstractseries.cpp"
148 #include "moc_qabstractseries.cpp"
142 #include "moc_qabstractseries_p.cpp"
149 #include "moc_qabstractseries_p.cpp"
143
150
144 QTCOMMERCIALCHART_END_NAMESPACE
151 QTCOMMERCIALCHART_END_NAMESPACE
145
152
146
153
@@ -1,74 +1,75
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 QABSTRACTSERIES_H
21 #ifndef QABSTRACTSERIES_H
22 #define QABSTRACTSERIES_H
22 #define QABSTRACTSERIES_H
23
23
24 #include <qchartglobal.h>
24 #include <qchartglobal.h>
25 #include <QObject>
25 #include <QObject>
26 #include <QPen>
26 #include <QPen>
27
27
28 class QAbstractItemModel;
28 class QAbstractItemModel;
29
29
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
31
32 class QAbstractSeriesPrivate;
32 class QAbstractSeriesPrivate;
33
33
34 class QTCOMMERCIALCHART_EXPORT QAbstractSeries : public QObject
34 class QTCOMMERCIALCHART_EXPORT QAbstractSeries : public QObject
35 {
35 {
36 Q_OBJECT
36 Q_OBJECT
37 Q_PROPERTY(QString name READ name WRITE setName)
37 Q_PROPERTY(QString name READ name WRITE setName)
38 Q_ENUMS(QSeriesType)
38 Q_ENUMS(QSeriesType)
39
39
40 public:
40 public:
41 enum QSeriesType {
41 enum QSeriesType {
42 SeriesTypeLine,
42 SeriesTypeLine,
43 SeriesTypeArea,
43 SeriesTypeArea,
44 SeriesTypeBar,
44 SeriesTypeBar,
45 SeriesTypeStackedBar,
45 SeriesTypeStackedBar,
46 SeriesTypePercentBar,
46 SeriesTypePercentBar,
47 SeriesTypePie,
47 SeriesTypePie,
48 SeriesTypeScatter,
48 SeriesTypeScatter,
49 SeriesTypeSpline
49 SeriesTypeSpline
50 };
50 };
51
51
52 protected:
52 protected:
53 QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent = 0);
53 QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent = 0);
54
54
55 public:
55 public:
56 ~QAbstractSeries();
56 ~QAbstractSeries();
57 virtual QSeriesType type() const = 0;
57 virtual QSeriesType type() const = 0;
58 virtual bool setModel(QAbstractItemModel* model) = 0;
58 virtual bool setModel(QAbstractItemModel* model) = 0;
59 QAbstractItemModel* model() const;
59 QAbstractItemModel* model() const;
60 int mapFirst() const;
60 int mapFirst() const;
61 int mapCount() const;
61 int mapCount() const;
62 int mapOrientation() const;
62 void setName(const QString& name);
63 void setName(const QString& name);
63 QString name() const;
64 QString name() const;
64
65
65 protected:
66 protected:
66 QScopedPointer<QAbstractSeriesPrivate> d_ptr;
67 QScopedPointer<QAbstractSeriesPrivate> d_ptr;
67 friend class ChartDataSet;
68 friend class ChartDataSet;
68 friend class ChartPresenter;
69 friend class ChartPresenter;
69 friend class QLegendPrivate;
70 friend class QLegendPrivate;
70 };
71 };
71
72
72 QTCOMMERCIALCHART_END_NAMESPACE
73 QTCOMMERCIALCHART_END_NAMESPACE
73
74
74 #endif
75 #endif
@@ -1,68 +1,69
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 QABSTRACTSERIES_P_H
30 #ifndef QABSTRACTSERIES_P_H
31 #define QABSTRACTSERIES_P_H
31 #define QABSTRACTSERIES_P_H
32
32
33 #include "qabstractseries.h"
33 #include "qabstractseries.h"
34
34
35 class QAbstractItemModel;
35 class QAbstractItemModel;
36
36
37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38
38
39 class Domain;
39 class Domain;
40 class ChartPresenter;
40 class ChartPresenter;
41 class Chart;
41 class Chart;
42 class LegendMarker;
42 class LegendMarker;
43 class QLegend;
43 class QLegend;
44
44
45 class QAbstractSeriesPrivate : public QObject
45 class QAbstractSeriesPrivate : public QObject
46 {
46 {
47 Q_OBJECT
47 Q_OBJECT
48 public:
48 public:
49 QAbstractSeriesPrivate(QAbstractSeries *q);
49 QAbstractSeriesPrivate(QAbstractSeries *q);
50 ~QAbstractSeriesPrivate();
50 ~QAbstractSeriesPrivate();
51
51
52 virtual void scaleDomain(Domain& domain) = 0;
52 virtual void scaleDomain(Domain& domain) = 0;
53 virtual Chart* createGraphics(ChartPresenter* presenter) = 0;
53 virtual Chart* createGraphics(ChartPresenter* presenter) = 0;
54 virtual QList<LegendMarker*> createLegendMarker(QLegend* legend) = 0;
54 virtual QList<LegendMarker*> createLegendMarker(QLegend* legend) = 0;
55
55
56 protected:
56 protected:
57 QAbstractSeries *q_ptr;
57 QAbstractSeries *q_ptr;
58 QAbstractItemModel *m_model;
58 QAbstractItemModel *m_model;
59 int m_mapFirst;
59 int m_mapFirst;
60 int m_mapCount;
60 int m_mapCount;
61 Qt::Orientation m_mapOrientation;
61 QString m_name;
62 QString m_name;
62
63
63 friend class QAbstractSeries;
64 friend class QAbstractSeries;
64 };
65 };
65
66
66 QTCOMMERCIALCHART_END_NAMESPACE
67 QTCOMMERCIALCHART_END_NAMESPACE
67
68
68 #endif
69 #endif
@@ -1,504 +1,503
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 "qxyseries.h"
21 #include "qxyseries.h"
22 #include "qxyseries_p.h"
22 #include "qxyseries_p.h"
23 #include "domain_p.h"
23 #include "domain_p.h"
24 #include "legendmarker_p.h"
24 #include "legendmarker_p.h"
25 #include <QAbstractItemModel>
25 #include <QAbstractItemModel>
26
26
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28
28
29 /*!
29 /*!
30 \class QXYSeries
30 \class QXYSeries
31 \brief The QXYSeries class is a base class for line, spline and scatter series.
31 \brief The QXYSeries class is a base class for line, spline and scatter series.
32 */
32 */
33
33
34 /*!
34 /*!
35 \fn QPen QXYSeries::pen() const
35 \fn QPen QXYSeries::pen() const
36 \brief Returns pen used to draw points for series.
36 \brief Returns pen used to draw points for series.
37 \sa setPen()
37 \sa setPen()
38 */
38 */
39
39
40 /*!
40 /*!
41 \fn QBrush QXYSeries::brush() const
41 \fn QBrush QXYSeries::brush() const
42 \brief Returns brush used to draw points for series.
42 \brief Returns brush used to draw points for series.
43 \sa setBrush()
43 \sa setBrush()
44 */
44 */
45
45
46 /*!
46 /*!
47 \fn void QXYSeries::clicked(const QPointF& point)
47 \fn void QXYSeries::clicked(const QPointF& point)
48 \brief Signal is emitted when user clicks the \a point on chart.
48 \brief Signal is emitted when user clicks the \a point on chart.
49 */
49 */
50
50
51 /*!
51 /*!
52 \fn void QXYSeries::selected()
52 \fn void QXYSeries::selected()
53
53
54 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
54 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
55 implemented by the user of QXYSeries API.
55 implemented by the user of QXYSeries API.
56 */
56 */
57
57
58 /*!
58 /*!
59 \fn void QXYSeriesPrivate::pointReplaced(int index)
59 \fn void QXYSeriesPrivate::pointReplaced(int index)
60 \brief \internal \a index
60 \brief \internal \a index
61 */
61 */
62
62
63 /*!
63 /*!
64 \fn void QXYSeriesPrivate::pointAdded(int index)
64 \fn void QXYSeriesPrivate::pointAdded(int index)
65 \brief \internal \a index
65 \brief \internal \a index
66 */
66 */
67
67
68 /*!
68 /*!
69 \fn void QXYSeriesPrivate::pointRemoved(int index)
69 \fn void QXYSeriesPrivate::pointRemoved(int index)
70 \brief \internal \a index
70 \brief \internal \a index
71 */
71 */
72
72
73 /*!
73 /*!
74 \fn void QXYSeriesPrivate::updated()
74 \fn void QXYSeriesPrivate::updated()
75 \brief \internal
75 \brief \internal
76 */
76 */
77
77
78 /*!
78 /*!
79 \internal
79 \internal
80
80
81 Constructs empty series object which is a child of \a parent.
81 Constructs empty series object which is a child of \a parent.
82 When series object is added to QChartView or QChart instance ownerships is transferred.
82 When series object is added to QChartView or QChart instance ownerships is transferred.
83 */
83 */
84 QXYSeries::QXYSeries(QXYSeriesPrivate &d,QObject *parent) : QAbstractSeries(d, parent)
84 QXYSeries::QXYSeries(QXYSeriesPrivate &d,QObject *parent) : QAbstractSeries(d, parent)
85 {
85 {
86
86
87 }
87 }
88 /*!
88 /*!
89 Destroys the object. Series added to QChartView or QChart instances are owned by those,
89 Destroys the object. Series added to QChartView or QChart instances are owned by those,
90 and are deleted when mentioned object are destroyed.
90 and are deleted when mentioned object are destroyed.
91 */
91 */
92 QXYSeries::~QXYSeries()
92 QXYSeries::~QXYSeries()
93 {
93 {
94 }
94 }
95
95
96 /*!
96 /*!
97 Adds data point \a x \a y to the series. Points are connected with lines on the chart.
97 Adds data point \a x \a y to the series. Points are connected with lines on the chart.
98 */
98 */
99 void QXYSeries::append(qreal x,qreal y)
99 void QXYSeries::append(qreal x,qreal y)
100 {
100 {
101 Q_D(QXYSeries);
101 Q_D(QXYSeries);
102 Q_ASSERT(d->m_x.size() == d->m_y.size());
102 Q_ASSERT(d->m_x.size() == d->m_y.size());
103 d->m_x<<x;
103 d->m_x<<x;
104 d->m_y<<y;
104 d->m_y<<y;
105 emit d->pointAdded(d->m_x.size()-1);
105 emit d->pointAdded(d->m_x.size()-1);
106 }
106 }
107
107
108 /*!
108 /*!
109 This is an overloaded function.
109 This is an overloaded function.
110 Adds data \a point to the series. Points are connected with lines on the chart.
110 Adds data \a point to the series. Points are connected with lines on the chart.
111 */
111 */
112 void QXYSeries::append(const QPointF &point)
112 void QXYSeries::append(const QPointF &point)
113 {
113 {
114 append(point.x(),point.y());
114 append(point.x(),point.y());
115 }
115 }
116
116
117 /*!
117 /*!
118 This is an overloaded function.
118 This is an overloaded function.
119 Adds list of data \a points to the series. Points are connected with lines on the chart.
119 Adds list of data \a points to the series. Points are connected with lines on the chart.
120 */
120 */
121 void QXYSeries::append(const QList<QPointF> points)
121 void QXYSeries::append(const QList<QPointF> points)
122 {
122 {
123 foreach(const QPointF& point , points) {
123 foreach(const QPointF& point , points) {
124 append(point.x(),point.y());
124 append(point.x(),point.y());
125 }
125 }
126 }
126 }
127
127
128 /*!
128 /*!
129 Modifies \a y value for given \a x a value.
129 Modifies \a y value for given \a x a value.
130 */
130 */
131 void QXYSeries::replace(qreal x,qreal y)
131 void QXYSeries::replace(qreal x,qreal y)
132 {
132 {
133 Q_D(QXYSeries);
133 Q_D(QXYSeries);
134 int index = d->m_x.indexOf(x);
134 int index = d->m_x.indexOf(x);
135 d->m_x[index] = x;
135 d->m_x[index] = x;
136 d->m_y[index] = y;
136 d->m_y[index] = y;
137 emit d->pointReplaced(index);
137 emit d->pointReplaced(index);
138 }
138 }
139
139
140 /*!
140 /*!
141 This is an overloaded function.
141 This is an overloaded function.
142 Replaces current y value of for given \a point x value with \a point y value.
142 Replaces current y value of for given \a point x value with \a point y value.
143 */
143 */
144 void QXYSeries::replace(const QPointF &point)
144 void QXYSeries::replace(const QPointF &point)
145 {
145 {
146 replace(point.x(),point.y());
146 replace(point.x(),point.y());
147 }
147 }
148
148
149 /*!
149 /*!
150 Removes first \a x value and related y value.
150 Removes first \a x value and related y value.
151 */
151 */
152 void QXYSeries::remove(qreal x)
152 void QXYSeries::remove(qreal x)
153 {
153 {
154 Q_D(QXYSeries);
154 Q_D(QXYSeries);
155 int index = d->m_x.indexOf(x);
155 int index = d->m_x.indexOf(x);
156
156
157 if (index == -1) return;
157 if (index == -1) return;
158
158
159 d->m_x.remove(index);
159 d->m_x.remove(index);
160 d->m_y.remove(index);
160 d->m_y.remove(index);
161
161
162 emit d->pointRemoved(index);
162 emit d->pointRemoved(index);
163 }
163 }
164
164
165 /*!
165 /*!
166 Removes current \a x and \a y value.
166 Removes current \a x and \a y value.
167 */
167 */
168 void QXYSeries::remove(qreal x,qreal y)
168 void QXYSeries::remove(qreal x,qreal y)
169 {
169 {
170 Q_D(QXYSeries);
170 Q_D(QXYSeries);
171 int index =-1;
171 int index =-1;
172 do {
172 do {
173 index = d->m_x.indexOf(x,index+1);
173 index = d->m_x.indexOf(x,index+1);
174 } while (index !=-1 && d->m_y.at(index)!=y);
174 } while (index !=-1 && d->m_y.at(index)!=y);
175
175
176 if (index==-1) return;
176 if (index==-1) return;
177
177
178 d->m_x.remove(index);
178 d->m_x.remove(index);
179 d->m_y.remove(index);
179 d->m_y.remove(index);
180 emit d->pointRemoved(index);
180 emit d->pointRemoved(index);
181 }
181 }
182
182
183 /*!
183 /*!
184 Removes current \a point x value. Note \a point y value is ignored.
184 Removes current \a point x value. Note \a point y value is ignored.
185 */
185 */
186 void QXYSeries::remove(const QPointF &point)
186 void QXYSeries::remove(const QPointF &point)
187 {
187 {
188 remove(point.x(),point.y());
188 remove(point.x(),point.y());
189 }
189 }
190
190
191 /*!
191 /*!
192 Removes all data points from the series.
192 Removes all data points from the series.
193 */
193 */
194 void QXYSeries::removeAll()
194 void QXYSeries::removeAll()
195 {
195 {
196 Q_D(QXYSeries);
196 Q_D(QXYSeries);
197 d->m_x.clear();
197 d->m_x.clear();
198 d->m_y.clear();
198 d->m_y.clear();
199 }
199 }
200
200
201 /*!
201 /*!
202 \internal \a pos
202 \internal \a pos
203 */
203 */
204 qreal QXYSeries::x(int pos) const
204 qreal QXYSeries::x(int pos) const
205 {
205 {
206 Q_D(const QXYSeries);
206 Q_D(const QXYSeries);
207 if (d->m_model) {
207 if (d->m_model) {
208 if (d->m_mapOrientation == Qt::Vertical)
208 if (d->m_mapOrientation == Qt::Vertical)
209 // consecutive data is read from model's column
209 // consecutive data is read from model's column
210 return d->m_model->data(d->m_model->index(pos + d->m_mapFirst, d->m_mapX), Qt::DisplayRole).toDouble();
210 return d->m_model->data(d->m_model->index(pos + d->m_mapFirst, d->m_mapX), Qt::DisplayRole).toDouble();
211 else
211 else
212 // consecutive data is read from model's row
212 // consecutive data is read from model's row
213 return d->m_model->data(d->m_model->index(d->m_mapX, pos + d->m_mapFirst), Qt::DisplayRole).toDouble();
213 return d->m_model->data(d->m_model->index(d->m_mapX, pos + d->m_mapFirst), Qt::DisplayRole).toDouble();
214 } else {
214 } else {
215 // model is not specified, return the data from series' internal data store
215 // model is not specified, return the data from series' internal data store
216 return d->m_x.at(pos);
216 return d->m_x.at(pos);
217 }
217 }
218 }
218 }
219
219
220 /*!
220 /*!
221 \internal \a pos
221 \internal \a pos
222 */
222 */
223 qreal QXYSeries::y(int pos) const
223 qreal QXYSeries::y(int pos) const
224 {
224 {
225 Q_D(const QXYSeries);
225 Q_D(const QXYSeries);
226 if (d->m_model) {
226 if (d->m_model) {
227 if (d->m_mapOrientation == Qt::Vertical)
227 if (d->m_mapOrientation == Qt::Vertical)
228 // consecutive data is read from model's column
228 // consecutive data is read from model's column
229 return d->m_model->data(d->m_model->index(pos + d->m_mapFirst, d->m_mapY), Qt::DisplayRole).toDouble();
229 return d->m_model->data(d->m_model->index(pos + d->m_mapFirst, d->m_mapY), Qt::DisplayRole).toDouble();
230 else
230 else
231 // consecutive data is read from model's row
231 // consecutive data is read from model's row
232 return d->m_model->data(d->m_model->index(d->m_mapY, pos + d->m_mapFirst), Qt::DisplayRole).toDouble();
232 return d->m_model->data(d->m_model->index(d->m_mapY, pos + d->m_mapFirst), Qt::DisplayRole).toDouble();
233 } else {
233 } else {
234 // model is not specified, return the data from series' internal data store
234 // model is not specified, return the data from series' internal data store
235 return d->m_y.at(pos);
235 return d->m_y.at(pos);
236 }
236 }
237 }
237 }
238
238
239 /*!
239 /*!
240 Returns number of data points within series.
240 Returns number of data points within series.
241 */
241 */
242 int QXYSeries::count() const
242 int QXYSeries::count() const
243 {
243 {
244 Q_D(const QXYSeries);
244 Q_D(const QXYSeries);
245
245
246 Q_ASSERT(d->m_x.size() == d->m_y.size());
246 Q_ASSERT(d->m_x.size() == d->m_y.size());
247
247
248 if (d->m_model) {
248 if (d->m_model) {
249 if (d->m_mapOrientation == Qt::Vertical) {
249 if (d->m_mapOrientation == Qt::Vertical) {
250 // data is in a column. Return the number of mapped items if the model's column have enough items
250 // data is in a column. Return the number of mapped items if the model's column have enough items
251 // or the number of items that can be mapped
251 // or the number of items that can be mapped
252 if (d->m_mapCount != -1)
252 if (d->m_mapCount != -1)
253 return qMin(d->m_mapCount, qMax(d->m_model->rowCount() - d->m_mapFirst, 0));
253 return qMin(d->m_mapCount, qMax(d->m_model->rowCount() - d->m_mapFirst, 0));
254 else
254 else
255 return qMax(d->m_model->rowCount() - d->m_mapFirst, 0);
255 return qMax(d->m_model->rowCount() - d->m_mapFirst, 0);
256 } else {
256 } else {
257 // data is in a row. Return the number of mapped items if the model's row have enough items
257 // data is in a row. Return the number of mapped items if the model's row have enough items
258 // or the number of items that can be mapped
258 // or the number of items that can be mapped
259 if (d->m_mapCount != -1)
259 if (d->m_mapCount != -1)
260 return qMin(d->m_mapCount, qMax(d->m_model->columnCount() - d->m_mapFirst, 0));
260 return qMin(d->m_mapCount, qMax(d->m_model->columnCount() - d->m_mapFirst, 0));
261 else
261 else
262 return qMax(d->m_model->columnCount() - d->m_mapFirst, 0);
262 return qMax(d->m_model->columnCount() - d->m_mapFirst, 0);
263 }
263 }
264 }
264 }
265
265
266 // model is not specified, return the number of points in the series internal data store
266 // model is not specified, return the number of points in the series internal data store
267 return d->m_x.size();
267 return d->m_x.size();
268 }
268 }
269
269
270 /*!
270 /*!
271 Returns the data points of the series.
271 Returns the data points of the series.
272 */
272 */
273 QList<QPointF> QXYSeries::data()
273 QList<QPointF> QXYSeries::data()
274 {
274 {
275 Q_D(QXYSeries);
275 Q_D(QXYSeries);
276 QList<QPointF> data;
276 QList<QPointF> data;
277 for (int i(0); i < d->m_x.count() && i < d->m_y.count(); i++)
277 for (int i(0); i < d->m_x.count() && i < d->m_y.count(); i++)
278 data.append(QPointF(d->m_x.at(i), d->m_y.at(i)));
278 data.append(QPointF(d->m_x.at(i), d->m_y.at(i)));
279 return data;
279 return data;
280 }
280 }
281
281
282
282
283 /*!
283 /*!
284 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
284 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
285 pen from chart theme is used.
285 pen from chart theme is used.
286 \sa QChart::setTheme()
286 \sa QChart::setTheme()
287 */
287 */
288 void QXYSeries::setPen(const QPen &pen)
288 void QXYSeries::setPen(const QPen &pen)
289 {
289 {
290 Q_D(QXYSeries);
290 Q_D(QXYSeries);
291 if (d->m_pen!=pen) {
291 if (d->m_pen!=pen) {
292 d->m_pen = pen;
292 d->m_pen = pen;
293 emit d->updated();
293 emit d->updated();
294 }
294 }
295 }
295 }
296
296
297 QPen QXYSeries::pen() const
297 QPen QXYSeries::pen() const
298 {
298 {
299 Q_D(const QXYSeries);
299 Q_D(const QXYSeries);
300 return d->m_pen;
300 return d->m_pen;
301 }
301 }
302
302
303 /*!
303 /*!
304 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
304 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
305 from chart theme setting is used.
305 from chart theme setting is used.
306 \sa QChart::setTheme()
306 \sa QChart::setTheme()
307 */
307 */
308 void QXYSeries::setBrush(const QBrush &brush)
308 void QXYSeries::setBrush(const QBrush &brush)
309 {
309 {
310 Q_D(QXYSeries);
310 Q_D(QXYSeries);
311 if (d->m_brush!=brush) {
311 if (d->m_brush!=brush) {
312 d->m_brush = brush;
312 d->m_brush = brush;
313 emit d->updated();
313 emit d->updated();
314 }
314 }
315 }
315 }
316
316
317 QBrush QXYSeries::brush() const
317 QBrush QXYSeries::brush() const
318 {
318 {
319 Q_D(const QXYSeries);
319 Q_D(const QXYSeries);
320 return d->m_brush;
320 return d->m_brush;
321 }
321 }
322
322
323
323
324 /*!
324 /*!
325 Sets if data points are \a visible and should be drawn on line.
325 Sets if data points are \a visible and should be drawn on line.
326 */
326 */
327 void QXYSeries::setPointsVisible(bool visible)
327 void QXYSeries::setPointsVisible(bool visible)
328 {
328 {
329 Q_D(QXYSeries);
329 Q_D(QXYSeries);
330 if (d->m_pointsVisible != visible){
330 if (d->m_pointsVisible != visible){
331 d->m_pointsVisible = visible;
331 d->m_pointsVisible = visible;
332 emit d->updated();
332 emit d->updated();
333 }
333 }
334 }
334 }
335
335
336 /*!
336 /*!
337 Returns true if drawing the data points of the series is enabled.
337 Returns true if drawing the data points of the series is enabled.
338 */
338 */
339 bool QXYSeries::pointsVisible() const
339 bool QXYSeries::pointsVisible() const
340 {
340 {
341 Q_D(const QXYSeries);
341 Q_D(const QXYSeries);
342 return d->m_pointsVisible;
342 return d->m_pointsVisible;
343 }
343 }
344
344
345
345
346 /*!
346 /*!
347 Stream operator for adding a data \a point to the series.
347 Stream operator for adding a data \a point to the series.
348 \sa append()
348 \sa append()
349 */
349 */
350 QXYSeries& QXYSeries::operator<< (const QPointF &point)
350 QXYSeries& QXYSeries::operator<< (const QPointF &point)
351 {
351 {
352 append(point);
352 append(point);
353 return *this;
353 return *this;
354 }
354 }
355
355
356
356
357 /*!
357 /*!
358 Stream operator for adding a list of \a points to the series.
358 Stream operator for adding a list of \a points to the series.
359 \sa append()
359 \sa append()
360 */
360 */
361
361
362 QXYSeries& QXYSeries::operator<< (const QList<QPointF> points)
362 QXYSeries& QXYSeries::operator<< (const QList<QPointF> points)
363 {
363 {
364 append(points);
364 append(points);
365 return *this;
365 return *this;
366 }
366 }
367
367
368 /*!
368 /*!
369 \fn bool QXYSeries::setModel(QAbstractItemModel *model)
369 \fn bool QXYSeries::setModel(QAbstractItemModel *model)
370 Sets the \a model to be used as a data source
370 Sets the \a model to be used as a data source
371 \sa setModelMapping()
371 \sa setModelMapping()
372 */
372 */
373 bool QXYSeries::setModel(QAbstractItemModel *model)
373 bool QXYSeries::setModel(QAbstractItemModel *model)
374 {
374 {
375 Q_D(QXYSeries);
375 Q_D(QXYSeries);
376 // disconnect signals from old model
376 // disconnect signals from old model
377 if (d->m_model) {
377 if (d->m_model) {
378 QObject::disconnect(d->m_model, 0, this, 0);
378 QObject::disconnect(d->m_model, 0, this, 0);
379 d->m_mapX = -1;
379 d->m_mapX = -1;
380 d->m_mapY = -1;
380 d->m_mapY = -1;
381 d->m_mapOrientation = Qt::Vertical;
381 d->m_mapOrientation = Qt::Vertical;
382 }
382 }
383
383
384 // set new model
384 // set new model
385 if (model) {
385 if (model) {
386 d->m_model = model;
386 d->m_model = model;
387 return true;
387 return true;
388 } else {
388 } else {
389 d->m_model = 0;
389 d->m_model = 0;
390 return false;
390 return false;
391 }
391 }
392 }
392 }
393
393
394 /*!
394 /*!
395 Sets the \a modelX to be used as a data source for x coordinate and \a modelY to be used
395 Sets the \a modelX to be used as a data source for x coordinate and \a modelY to be used
396 as a data source for y coordinate. The \a orientation parameter specifies whether the data
396 as a data source for y coordinate. The \a orientation parameter specifies whether the data
397 is in columns or in rows.
397 is in columns or in rows.
398 \sa setModel()
398 \sa setModel()
399 */
399 */
400 void QXYSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
400 void QXYSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
401 {
401 {
402 Q_D(QXYSeries);
402 Q_D(QXYSeries);
403 if (d->m_model == 0)
403 if (d->m_model == 0)
404 return;
404 return;
405 d->m_mapX = modelX;
405 d->m_mapX = modelX;
406 d->m_mapY = modelY;
406 d->m_mapY = modelY;
407 d->m_mapOrientation = orientation;
407 d->m_mapOrientation = orientation;
408
408
409 // connect the signals from the model
409 // connect the signals from the model
410 connect(d->m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
410 connect(d->m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
411 if (d->m_mapOrientation == Qt::Vertical) {
411 if (d->m_mapOrientation == Qt::Vertical) {
412 connect(d->m_model,SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
412 connect(d->m_model,SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
413 connect(d->m_model,SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
413 connect(d->m_model,SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
414 } else {
414 } else {
415 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
415 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
416 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
416 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
417 }
417 }
418 }
418 }
419
419
420 void QXYSeries::setModelMappingRange(int first, int count)
420 void QXYSeries::setModelMappingRange(int first, int count)
421 {
421 {
422 Q_D(QXYSeries);
422 Q_D(QXYSeries);
423 d->m_mapFirst = first;
423 d->m_mapFirst = first;
424 d->m_mapCount = count;
424 d->m_mapCount = count;
425 }
425 }
426
426
427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
428
428
429
429
430 QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q) : QAbstractSeriesPrivate(q),
430 QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q) : QAbstractSeriesPrivate(q),
431 m_mapX(-1),
431 m_mapX(-1),
432 m_mapY(-1),
432 m_mapY(-1),
433 m_mapOrientation( Qt::Vertical),
434 m_pointsVisible(false)
433 m_pointsVisible(false)
435 {
434 {
436 }
435 }
437
436
438 void QXYSeriesPrivate::scaleDomain(Domain& domain)
437 void QXYSeriesPrivate::scaleDomain(Domain& domain)
439 {
438 {
440 qreal minX(domain.minX());
439 qreal minX(domain.minX());
441 qreal minY(domain.minY());
440 qreal minY(domain.minY());
442 qreal maxX(domain.maxX());
441 qreal maxX(domain.maxX());
443 qreal maxY(domain.maxY());
442 qreal maxY(domain.maxY());
444 int tickXCount(domain.tickXCount());
443 int tickXCount(domain.tickXCount());
445 int tickYCount(domain.tickYCount());
444 int tickYCount(domain.tickYCount());
446
445
447 Q_Q(QXYSeries);
446 Q_Q(QXYSeries);
448 for (int i = 0; i < q->count(); i++)
447 for (int i = 0; i < q->count(); i++)
449 {
448 {
450 qreal x = q->x(i);
449 qreal x = q->x(i);
451 qreal y = q->y(i);
450 qreal y = q->y(i);
452 minX = qMin(minX, x);
451 minX = qMin(minX, x);
453 minY = qMin(minY, y);
452 minY = qMin(minY, y);
454 maxX = qMax(maxX, x);
453 maxX = qMax(maxX, x);
455 maxY = qMax(maxY, y);
454 maxY = qMax(maxY, y);
456 }
455 }
457
456
458 domain.setRangeX(minX,maxX,tickXCount);
457 domain.setRangeX(minX,maxX,tickXCount);
459 domain.setRangeY(minY,maxY,tickYCount);
458 domain.setRangeY(minY,maxY,tickYCount);
460 }
459 }
461
460
462 QList<LegendMarker*> QXYSeriesPrivate::createLegendMarker(QLegend* legend)
461 QList<LegendMarker*> QXYSeriesPrivate::createLegendMarker(QLegend* legend)
463 {
462 {
464 Q_Q(QXYSeries);
463 Q_Q(QXYSeries);
465 QList<LegendMarker*> list;
464 QList<LegendMarker*> list;
466 return list << new XYLegendMarker(q,legend);
465 return list << new XYLegendMarker(q,legend);
467 }
466 }
468
467
469 void QXYSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
468 void QXYSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
470 {
469 {
471 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
470 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
472 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
471 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
473 if (m_mapOrientation == Qt::Vertical) {
472 if (m_mapOrientation == Qt::Vertical) {
474 if ((column == m_mapX || column == m_mapY) // modified item is in a mapped column
473 if ((column == m_mapX || column == m_mapY) // modified item is in a mapped column
475 && row >= m_mapFirst // modfied item in not before first item
474 && row >= m_mapFirst // modfied item in not before first item
476 && (m_mapCount == -1 || row < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
475 && (m_mapCount == -1 || row < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
477 emit pointReplaced(row - m_mapFirst);
476 emit pointReplaced(row - m_mapFirst);
478 } else {
477 } else {
479 if ((row == m_mapX || row == m_mapY) // modified item is in a mapped row
478 if ((row == m_mapX || row == m_mapY) // modified item is in a mapped row
480 && column >= m_mapFirst // modfied item in not before first item
479 && column >= m_mapFirst // modfied item in not before first item
481 && (m_mapCount == -1 || column < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
480 && (m_mapCount == -1 || column < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
482 emit pointReplaced(column - m_mapFirst);
481 emit pointReplaced(column - m_mapFirst);
483 }
482 }
484 }
483 }
485 }
484 }
486 }
485 }
487
486
488
487
489 void QXYSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end)
488 void QXYSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end)
490 {
489 {
491 Q_UNUSED(parent);
490 Q_UNUSED(parent);
492 emit pointsAdded(start, end);
491 emit pointsAdded(start, end);
493 }
492 }
494
493
495 void QXYSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
494 void QXYSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
496 {
495 {
497 Q_UNUSED(parent);
496 Q_UNUSED(parent);
498 emit pointsRemoved(start, end);
497 emit pointsRemoved(start, end);
499 }
498 }
500
499
501 #include "moc_qxyseries.cpp"
500 #include "moc_qxyseries.cpp"
502 #include "moc_qxyseries_p.cpp"
501 #include "moc_qxyseries_p.cpp"
503
502
504 QTCOMMERCIALCHART_END_NAMESPACE
503 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,84 +1,83
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 QXYSERIES_P_H
30 #ifndef QXYSERIES_P_H
31 #define QXYSERIES_P_H
31 #define QXYSERIES_P_H
32
32
33 #include "qabstractseries_p.h"
33 #include "qabstractseries_p.h"
34
34
35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36
36
37 class QXYSeries;
37 class QXYSeries;
38
38
39 class QXYSeriesPrivate: public QAbstractSeriesPrivate
39 class QXYSeriesPrivate: public QAbstractSeriesPrivate
40 {
40 {
41 Q_OBJECT
41 Q_OBJECT
42
42
43 public:
43 public:
44 QXYSeriesPrivate(QXYSeries* q);
44 QXYSeriesPrivate(QXYSeries* q);
45
45
46 void scaleDomain(Domain& domain);
46 void scaleDomain(Domain& domain);
47 QList<LegendMarker*> createLegendMarker(QLegend* legend);
47 QList<LegendMarker*> createLegendMarker(QLegend* legend);
48
48
49 private Q_SLOTS:
49 private Q_SLOTS:
50 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
50 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
51 void modelDataAdded(QModelIndex parent, int start, int end);
51 void modelDataAdded(QModelIndex parent, int start, int end);
52 void modelDataRemoved(QModelIndex parent, int start, int end);
52 void modelDataRemoved(QModelIndex parent, int start, int end);
53
53
54 Q_SIGNALS:
54 Q_SIGNALS:
55 void updated();
55 void updated();
56 void pointReplaced(int index);
56 void pointReplaced(int index);
57 void pointRemoved(int index);
57 void pointRemoved(int index);
58 void pointsRemoved(int start, int end);
58 void pointsRemoved(int start, int end);
59 void pointAdded(int index);
59 void pointAdded(int index);
60 void pointsAdded(int start, int end);
60 void pointsAdded(int start, int end);
61
61
62
62
63
63
64 protected:
64 protected:
65 QVector<qreal> m_x;
65 QVector<qreal> m_x;
66 QVector<qreal> m_y;
66 QVector<qreal> m_y;
67
67
68 QPen m_pen;
68 QPen m_pen;
69 QBrush m_brush;
69 QBrush m_brush;
70
70
71 int m_mapX;
71 int m_mapX;
72 int m_mapY;
72 int m_mapY;
73 Qt::Orientation m_mapOrientation;
74 bool m_pointsVisible;
73 bool m_pointsVisible;
75
74
76 private:
75 private:
77 Q_DECLARE_PUBLIC(QXYSeries);
76 Q_DECLARE_PUBLIC(QXYSeries);
78 friend class QScatterSeries;
77 friend class QScatterSeries;
79
78
80 };
79 };
81
80
82 QTCOMMERCIALCHART_END_NAMESPACE
81 QTCOMMERCIALCHART_END_NAMESPACE
83
82
84 #endif
83 #endif
@@ -1,244 +1,306
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 "xychartitem_p.h"
21 #include "xychartitem_p.h"
22 #include "qxyseries.h"
22 #include "qxyseries.h"
23 #include "qxyseries_p.h"
23 #include "qxyseries_p.h"
24 #include "chartpresenter_p.h"
24 #include "chartpresenter_p.h"
25 #include "chartanimator_p.h"
25 #include "chartanimator_p.h"
26 #include <QPainter>
26 #include <QPainter>
27 #include <QGraphicsSceneMouseEvent>
27 #include <QGraphicsSceneMouseEvent>
28 #include <QAbstractItemModel>
28
29
29
30
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
32
32 //TODO: optimize : remove points which are not visible
33 //TODO: optimize : remove points which are not visible
33
34
34 XYChartItem::XYChartItem(QXYSeries *series, ChartPresenter *presenter):ChartItem(presenter),
35 XYChartItem::XYChartItem(QXYSeries *series, ChartPresenter *presenter):ChartItem(presenter),
35 m_minX(0),
36 m_minX(0),
36 m_maxX(0),
37 m_maxX(0),
37 m_minY(0),
38 m_minY(0),
38 m_maxY(0),
39 m_maxY(0),
39 m_series(series)
40 m_series(series)
40 {
41 {
41 connect(series->d_func(),SIGNAL(pointReplaced(int)),this,SLOT(handlePointReplaced(int)));
42 connect(series->d_func(),SIGNAL(pointReplaced(int)),this,SLOT(handlePointReplaced(int)));
42 connect(series->d_func(),SIGNAL(pointAdded(int)),this,SLOT(handlePointAdded(int)));
43 connect(series->d_func(),SIGNAL(pointAdded(int)),this,SLOT(handlePointAdded(int)));
43 connect(series->d_func(),SIGNAL(pointsAdded(int, int)),this,SLOT(handlePointsAdded(int, int)));
44 connect(series->d_func(),SIGNAL(pointsAdded(int, int)),this,SLOT(handlePointsAdded(int, int)));
44 connect(series->d_func(),SIGNAL(pointRemoved(int)),this,SLOT(handlePointRemoved(int)));
45 connect(series->d_func(),SIGNAL(pointRemoved(int)),this,SLOT(handlePointRemoved(int)));
45 connect(series->d_func(),SIGNAL(pointsRemoved(int, int)),this,SLOT(handlePointsRemoved(int, int)));
46 connect(series->d_func(),SIGNAL(pointsRemoved(int, int)),this,SLOT(handlePointsRemoved(int, int)));
46 connect(this,SIGNAL(clicked(QPointF)),series,SIGNAL(clicked(QPointF)));
47 connect(this,SIGNAL(clicked(QPointF)),series,SIGNAL(clicked(QPointF)));
47 }
48 }
48
49
49 QPointF XYChartItem::calculateGeometryPoint(const QPointF &point) const
50 QPointF XYChartItem::calculateGeometryPoint(const QPointF &point) const
50 {
51 {
51 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
52 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
52 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
53 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
53 qreal x = (point.x() - m_minX)* deltaX;
54 qreal x = (point.x() - m_minX)* deltaX;
54 qreal y = (point.y() - m_minY)*-deltaY + m_size.height();
55 qreal y = (point.y() - m_minY)*-deltaY + m_size.height();
55 return QPointF(x,y);
56 return QPointF(x,y);
56 }
57 }
57
58
58
59
59 QPointF XYChartItem::calculateGeometryPoint(int index) const
60 QPointF XYChartItem::calculateGeometryPoint(int index) const
60 {
61 {
61 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
62 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
62 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
63 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
63 qreal x = (m_series->x(index) - m_minX)* deltaX;
64 qreal x = (m_series->x(index) - m_minX)* deltaX;
64 qreal y = (m_series->y(index) - m_minY)*-deltaY + m_size.height();
65 qreal y = (m_series->y(index) - m_minY)*-deltaY + m_size.height();
65 return QPointF(x,y);
66 return QPointF(x,y);
66 }
67 }
67
68
68 QVector<QPointF> XYChartItem::calculateGeometryPoints() const
69 QVector<QPointF> XYChartItem::calculateGeometryPoints() const
69 {
70 {
70 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
71 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
71 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
72 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
72
73
73 QVector<QPointF> points;
74 QVector<QPointF> points;
74 points.reserve(m_series->count());
75 points.reserve(m_series->count());
75 for (int i = 0; i < m_series->count(); ++i) {
76 for (int i = 0; i < m_series->count(); ++i) {
76 qreal x = (m_series->x(i) - m_minX)* deltaX;
77 qreal x = (m_series->x(i) - m_minX)* deltaX;
77 qreal y = (m_series->y(i) - m_minY)*-deltaY + m_size.height();
78 qreal y = (m_series->y(i) - m_minY)*-deltaY + m_size.height();
78 points << QPointF(x,y);
79 points << QPointF(x,y);
79 }
80 }
80 return points;
81 return points;
81 }
82 }
82
83
83 QPointF XYChartItem::calculateDomainPoint(const QPointF &point) const
84 QPointF XYChartItem::calculateDomainPoint(const QPointF &point) const
84 {
85 {
85 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
86 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
86 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
87 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
87 qreal x = point.x()/deltaX +m_minX;
88 qreal x = point.x()/deltaX +m_minX;
88 qreal y = (point.y()-m_size.height())/(-deltaY)+ m_minY;
89 qreal y = (point.y()-m_size.height())/(-deltaY)+ m_minY;
89 return QPointF(x,y);
90 return QPointF(x,y);
90 }
91 }
91
92
92 void XYChartItem::updateLayout(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints,int index)
93 void XYChartItem::updateLayout(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints,int index)
93 {
94 {
94 if (animator()) {
95 if (animator()) {
95 animator()->updateLayout(this,oldPoints,newPoints,index);
96 animator()->updateLayout(this,oldPoints,newPoints,index);
96 } else {
97 } else {
97 setLayout(newPoints);
98 setLayout(newPoints);
98 }
99 }
99 }
100 }
100
101
101 void XYChartItem::setLayout(QVector<QPointF> &points)
102 void XYChartItem::setLayout(QVector<QPointF> &points)
102 {
103 {
103 m_points = points;
104 m_points = points;
104 update();
105 update();
105 }
106 }
106
107
107 //handlers
108 //handlers
108
109
109 void XYChartItem::handlePointAdded(int index)
110 void XYChartItem::handlePointAdded(int index)
110 {
111 {
111 if (m_series->model() == 0) {
112 if (m_series->model() == 0) {
112 Q_ASSERT(index<m_series->count());
113 Q_ASSERT(index<m_series->count());
113 Q_ASSERT(index>=0);
114 Q_ASSERT(index>=0);
114 }
115 }
115 QVector<QPointF> points = m_points;
116 QVector<QPointF> points = m_points;
116 QPointF point;
117 QPointF point;
117 point = calculateGeometryPoint(index);
118 point = calculateGeometryPoint(index);
118 points.insert(index, point);
119 points.insert(index, point);
119 updateLayout(m_points, points, index);
120 updateLayout(m_points, points, index);
120 update();
121 update();
121 }
122 }
122
123
123 void XYChartItem::handlePointsAdded(int start, int end)
124 void XYChartItem::handlePointsAdded(int start, int end)
124 {
125 {
125 if (m_series->model() == 0) {
126 if (m_series->model() == 0) {
126 for (int i = start; i <= end; i++)
127 for (int i = start; i <= end; i++)
127 handlePointAdded(i);
128 handlePointAdded(i);
128 } else {
129 } else {
129 // series uses model as a data source
130 // series uses model as a data source
130 int first = m_series->mapFirst();
131 int first = m_series->mapFirst();
131 int count = m_series->mapCount();
132 int count = m_series->mapCount();
132 int addedCount = end - start + 1;
133 int addedCount = end - start + 1;
133 if (count != -1 && start >= first + count) {
134 if (count != -1 && start >= first + count) {
134 return;
135 return;
135 }
136 }
136
137
137 // adding items to unlimited map
138 // adding items to unlimited map
138 else if (count == -1 && start >= first) {
139 else if (count == -1 && start >= first) {
139 for (int i = start; i <= end; i++)
140 for (int i = start; i <= end; i++)
140 handlePointAdded(i - first);
141 handlePointAdded(i - first);
141 } else if (count == - 1 && start < first) {
142 } else if (count == - 1 && start < first) {
142 // not all newly added items
143 // not all newly added items
143 for (int i = first; i < first + addedCount; i++)
144 for (int i = first; i < first + addedCount; i++)
144 handlePointAdded(i - first);
145 handlePointAdded(i - first);
145 }
146 }
146 // commented out code below does the same thing, but its more confusing.
147 // commented out code below does the same thing, but its more confusing.
147 // } else if (count == -1) {
148 // } else if (count == -1) {
148 // int begin = qMax(start, first);
149 // int begin = qMax(start, first);
149 // for (int i = begin; i < begin + (end - start + 1); i++)
150 // for (int i = begin; i < begin + (end - start + 1); i++)
150 // handlePointAdded(i - first);
151 // handlePointAdded(i - first);
151 // }
152 // }
152
153
153 // adding items to limited map
154 // adding items to limited map
154 else if (start >= first) {
155 else if (start >= first) {
155 // remove the items that will no longer fit into the map
156 // remove the items that will no longer fit into the map
156 // int toRemove = addedCount - (count - points().size());
157 // int toRemove = addedCount - (count - points().size());
157 for (int i = start; i <= end; i++) {
158 for (int i = start; i <= end; i++) {
158 handlePointAdded(i - first);
159 handlePointAdded(i - first);
159 }
160 }
160 if (m_points.size() > count)
161 if (m_points.size() > count)
161 for (int i = m_points.size() - 1; i >= count; i--)
162 for (int i = m_points.size() - 1; i >= count; i--)
162 handlePointRemoved(i);
163 handlePointRemoved(i);
163 // update();
164 // update();
164 } else {
165 } else {
165 //
166 //
166 for (int i = first; i < first + addedCount; i++) {
167 for (int i = first; i < first + addedCount; i++) {
167 handlePointAdded(i - first);
168 handlePointAdded(i - first);
168 }
169 }
169 if (m_points.size() > count)
170 if (m_points.size() > count)
170 for (int i = m_points.size() - 1; i >= count; i--)
171 for (int i = m_points.size() - 1; i >= count; i--)
171 handlePointRemoved(i);
172 handlePointRemoved(i);
172 }
173 }
173 }
174 }
174 }
175 }
175
176
176 void XYChartItem::handlePointRemoved(int index)
177 void XYChartItem::handlePointRemoved(int index)
177 {
178 {
178 if (m_series->model() == 0) {
179 if (m_series->model() == 0) {
179 Q_ASSERT(index<m_series->count() + 1);
180 Q_ASSERT(index<m_series->count() + 1);
180 Q_ASSERT(index>=0);
181 Q_ASSERT(index>=0);
181 }
182 }
182 QVector<QPointF> points = m_points;
183 QVector<QPointF> points = m_points;
183 points.remove(index);
184 points.remove(index);
184 updateLayout(m_points, points, index);
185 updateLayout(m_points, points, index);
185 update();
186 update();
186 }
187 }
187
188
188 void XYChartItem::handlePointsRemoved(int start, int end)
189 void XYChartItem::handlePointsRemoved(int start, int end)
189 {
190 {
190 Q_UNUSED(start)
191 Q_UNUSED(start)
191 Q_UNUSED(end)
192 Q_UNUSED(end)
193 if (m_series->model() == 0) {
194 for (int i = end; i >= start; i--)
195 handlePointRemoved(i);
196 } else {
197 // series uses model as a data source
198 int first = m_series->mapFirst();
199 int count = m_series->mapCount();
200 int removedCount = end - start + 1;
201 if (count != -1 && start >= first + count) {
202 return;
203 }
204
205 // removing items from unlimited map
206 else if (count == -1 && start >= first) {
207 for (int i = end; i >= start; i--)
208 handlePointRemoved(i - first);
209 } else if (count == - 1 && start < first) {
210 // not all removed items
211 for (int i = first + removedCount - 1; i >= first; i--)
212 handlePointRemoved(i - first);
213 }
214
215 // removing items from limited map
216 else if (start >= first) {
217 //
218 int lastExisting = qMin(first + m_points.size() - 1, end);
219 for (int i = lastExisting; i >= start; i--) {
220 handlePointRemoved(i - first);
221 }
222
223 // the map is limited, so after removing the items some new items may have fall into the map
224 int itemsAvailable;
225 if (m_series->mapOrientation() == Qt::Vertical)
226 itemsAvailable = m_series->model()->rowCount() - first - m_points.size();
227 else
228 itemsAvailable = m_series->model()->columnCount() - first - m_points.size();
229 int toBeAdded = qMin(itemsAvailable, count - m_points.size());
230 int currentSize = m_points.size();
231 if (itemsAvailable > 0)
232 for (int i = m_points.size(); i < currentSize + toBeAdded; i++)
233 handlePointAdded(i);
234 } else {
235 // TODO:
236 int toRemove = qMin(m_points.size() - 1, removedCount);
237 for (int i = first; i < first + toRemove; i++)
238 handlePointRemoved(0);
239
240 // the map is limited, so after removing the items some new items may have fall into the map
241 int itemsAvailable;
242 if (m_series->mapOrientation() == Qt::Vertical)
243 itemsAvailable = m_series->model()->rowCount() - first - m_points.size();
244 else
245 itemsAvailable = m_series->model()->columnCount() - first - m_points.size();
246 int toBeAdded = qMin(itemsAvailable, count - m_points.size());
247 int currentSize = m_points.size();
248 if (itemsAvailable > 0)
249 for (int i = m_points.size(); i < currentSize + toBeAdded; i++)
250 handlePointAdded(i);
251 }
252 }
253
192 }
254 }
193
255
194 void XYChartItem::handlePointReplaced(int index)
256 void XYChartItem::handlePointReplaced(int index)
195 {
257 {
196 Q_ASSERT(index<m_series->count());
258 Q_ASSERT(index<m_series->count());
197 Q_ASSERT(index>=0);
259 Q_ASSERT(index>=0);
198 QPointF point = calculateGeometryPoint(index);
260 QPointF point = calculateGeometryPoint(index);
199 QVector<QPointF> points = m_points;
261 QVector<QPointF> points = m_points;
200 points.replace(index,point);
262 points.replace(index,point);
201 updateLayout(m_points,points,index);
263 updateLayout(m_points,points,index);
202 update();
264 update();
203 }
265 }
204
266
205 void XYChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
267 void XYChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
206 {
268 {
207 m_minX=minX;
269 m_minX=minX;
208 m_maxX=maxX;
270 m_maxX=maxX;
209 m_minY=minY;
271 m_minY=minY;
210 m_maxY=maxY;
272 m_maxY=maxY;
211
273
212 if (isEmpty()) return;
274 if (isEmpty()) return;
213 QVector<QPointF> points = calculateGeometryPoints();
275 QVector<QPointF> points = calculateGeometryPoints();
214 updateLayout(m_points,points);
276 updateLayout(m_points,points);
215 update();
277 update();
216 }
278 }
217
279
218 void XYChartItem::handleGeometryChanged(const QRectF &rect)
280 void XYChartItem::handleGeometryChanged(const QRectF &rect)
219 {
281 {
220 Q_ASSERT(rect.isValid());
282 Q_ASSERT(rect.isValid());
221 m_size=rect.size();
283 m_size=rect.size();
222 m_clipRect=rect.translated(-rect.topLeft());
284 m_clipRect=rect.translated(-rect.topLeft());
223 setPos(rect.topLeft());
285 setPos(rect.topLeft());
224
286
225 if (isEmpty()) return;
287 if (isEmpty()) return;
226 QVector<QPointF> points = calculateGeometryPoints();
288 QVector<QPointF> points = calculateGeometryPoints();
227 updateLayout(m_points,points);
289 updateLayout(m_points,points);
228 update();
290 update();
229 }
291 }
230
292
231
293
232 bool XYChartItem::isEmpty()
294 bool XYChartItem::isEmpty()
233 {
295 {
234 return !m_clipRect.isValid() || qFuzzyIsNull(m_maxX - m_minX) || qFuzzyIsNull(m_maxY - m_minY);
296 return !m_clipRect.isValid() || qFuzzyIsNull(m_maxX - m_minX) || qFuzzyIsNull(m_maxY - m_minY);
235 }
297 }
236
298
237 void XYChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
299 void XYChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
238 {
300 {
239 emit clicked(calculateDomainPoint(event->pos()));
301 emit clicked(calculateDomainPoint(event->pos()));
240 }
302 }
241
303
242 #include "moc_xychartitem_p.cpp"
304 #include "moc_xychartitem_p.cpp"
243
305
244 QTCOMMERCIALCHART_END_NAMESPACE
306 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now