##// END OF EJS Templates
Model mappers docs updated
Marek Rosa -
r1378:cb1c9eed2618
parent child
Show More
@@ -1,482 +1,482
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qbarmodelmapper.h"
22 22 #include "qbarmodelmapper_p.h"
23 23 #include "qbarseries.h"
24 24 #include "qbarset.h"
25 25 #include "qchart.h"
26 26 #include <QAbstractItemModel>
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 /*!
31 \class QBarModelMapper
32 \brief part of QtCommercial chart API.
33 \mainclass
34
35 The instance of this class cannot be created directly. QHBarModelMapper of QVBarModelMapper should be used instead. This class is used to create a connection between QBarSeries and QAbstractItemModel derived model object.
36 Curently it is NOT possible to use both QAbstractItemModel and QBarSeries model API.
37 When the series is set to the mapper the QBarSeries and QBarSet API that affect the data (append, setValue, remove) should not be used.
38 The model and the QBarSeries won't be kept in sync. Model API should be used to insert,remove,modify BarSets.
39 NOTE: used model has to support adding/removing rows/columns and modifying the data of the cells.
40 */
41
42 /*!
31 43 \property QBarModelMapper::series
32 44 \brief Defines the QPieSeries object that is used by the mapper.
33 45
34 All the data in the series in the series is discarded when it is set to the mapper.
46 All the data in the series is discarded when it is set to the mapper.
35 47 When new series is specified the old series is disconnected (it preserves its data)
36 48 */
37 49
38 50 /*!
39 51 \property QBarModelMapper::model
40 52 \brief Defines the model that is used by the mapper.
41 53 */
42 54
43 55 /*!
44 56 \property QBarModelMapper::first
45 57 \brief Defines which item of the model's row/column should be mapped as the value of the first QBarSet in the series.
46 58
47 59 Minimal and default value is: 0
48 60 */
49 61
50 62 /*!
51 63 \property QBarModelMapper::count
52 64 \brief Defines the number of rows/columns of the model that are mapped as the data for QBarSeries
53 65
54 66 Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
55 67 */
56 68
57 69 /*!
58 \class QBarModelMapper
59 \brief part of QtCommercial chart API.
60 \mainclass
61
62 The instance of this class cannot be created directly. QHBarModelMapper of QVBarModelMapper should be used instead. This class is used to create a connection between QBarSeries and QAbstractItemModel derived model object.
63 Curently it is NOT possible to use both QAbstractItemModel and QXYSeries model API.
64 When the series is set to the mapper the QBarSeries and QBarSet API that affect the data (append, setValue, remove) should not be used.
65 The model and the QBarSeries won't be kept in sync. Model API should be used to insert,remove,modify BarSets.
66 NOTE: used model has to support adding/removing rows/columns and modifying the data of the cells.
67 */
68
69 /*!
70 70 Constructs a mapper object which is a child of \a parent.
71 71 */
72 72 QBarModelMapper::QBarModelMapper(QObject *parent) :
73 73 QObject(parent),
74 74 d_ptr(new QBarModelMapperPrivate(this))
75 75 {
76 76 }
77 77
78 78 QAbstractItemModel* QBarModelMapper::model() const
79 79 {
80 80 Q_D(const QBarModelMapper);
81 81 return d->m_model;
82 82 }
83 83
84 84 void QBarModelMapper::setModel(QAbstractItemModel *model)
85 85 {
86 86 if (model == 0)
87 87 return;
88 88
89 89 Q_D(QBarModelMapper);
90 90 if (d->m_model) {
91 91 disconnect(d->m_model, 0, d, 0);
92 92 }
93 93
94 94 d->m_model = model;
95 95 d->initializeBarFromModel();
96 96 // connect signals from the model
97 97 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
98 98 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
99 99 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
100 100 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
101 101 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
102 102 }
103 103
104 104 QBarSeries* QBarModelMapper::series() const
105 105 {
106 106 Q_D(const QBarModelMapper);
107 107 return d->m_series;
108 108 }
109 109
110 110 void QBarModelMapper::setSeries(QBarSeries *series)
111 111 {
112 112 Q_D(QBarModelMapper);
113 113 if (d->m_series) {
114 114 disconnect(d->m_series, 0, d, 0);
115 115 }
116 116
117 117 if (series == 0)
118 118 return;
119 119
120 120 d->m_series = series;
121 121 d->initializeBarFromModel();
122 122 // connect the signals from the series
123 123 // connect(d->m_series, SIGNAL(pointAdded(int)), d, SLOT(handlePointAdded(int)));
124 124 // connect(d->m_series, SIGNAL(pointRemoved(int)), d, SLOT(handlePointRemoved(int)));
125 125 // connect(d->m_series, SIGNAL(pointReplaced(int)), d, SLOT(handlePointReplaced(int)));
126 126 }
127 127
128 128 int QBarModelMapper::first() const
129 129 {
130 130 Q_D(const QBarModelMapper);
131 131 return d->m_first;
132 132 }
133 133
134 134 void QBarModelMapper::setFirst(int first)
135 135 {
136 136 Q_D(QBarModelMapper);
137 137 d->m_first = qMax(first, 0);
138 138 d->initializeBarFromModel();
139 139 }
140 140
141 141 int QBarModelMapper::count() const
142 142 {
143 143 Q_D(const QBarModelMapper);
144 144 return d->m_count;
145 145 }
146 146
147 147 void QBarModelMapper::setCount(int count)
148 148 {
149 149 Q_D(QBarModelMapper);
150 150 d->m_count = qMax(count, -1);
151 151 d->initializeBarFromModel();
152 152 }
153 153
154 154 /*!
155 155 Returns the orientation that is used when QBarModelMapper accesses the model.
156 156 This mean whether the consecutive values of the bar set are read from row (Qt::Horizontal)
157 157 or from columns (Qt::Vertical)
158 158 */
159 159 Qt::Orientation QBarModelMapper::orientation() const
160 160 {
161 161 Q_D(const QBarModelMapper);
162 162 return d->m_orientation;
163 163 }
164 164
165 165 /*!
166 166 Returns the \a orientation that is used when QBarModelMapper accesses the model.
167 167 This mean whether the consecutive values of the pie are read from row (Qt::Horizontal)
168 168 or from columns (Qt::Vertical)
169 169 */
170 170 void QBarModelMapper::setOrientation(Qt::Orientation orientation)
171 171 {
172 172 Q_D(QBarModelMapper);
173 173 d->m_orientation = orientation;
174 174 d->initializeBarFromModel();
175 175 }
176 176
177 177 /*!
178 178 Returns which section of the model is used as the data source for the first bar set
179 179 */
180 180 int QBarModelMapper::firstBarSetSection() const
181 181 {
182 182 Q_D(const QBarModelMapper);
183 183 return d->m_firstBarSetSection;
184 184 }
185 185
186 186 /*!
187 187 Sets the model section that is used as the data source for the first bar set
188 188 Parameter \a firstBarSetSection specifies the section of the model.
189 189 */
190 190 void QBarModelMapper::setFirstBarSetSection(int firstBarSetSection)
191 191 {
192 192 Q_D(QBarModelMapper);
193 193 d->m_firstBarSetSection = qMax(-1, firstBarSetSection);
194 194 d->initializeBarFromModel();
195 195 }
196 196
197 197 /*!
198 198 Returns which section of the model is used as the data source for the last bar set
199 199 */
200 200 int QBarModelMapper::lastBarSetSection() const
201 201 {
202 202 Q_D(const QBarModelMapper);
203 203 return d->m_lastBarSetSection;
204 204 }
205 205
206 206 /*!
207 207 Sets the model section that is used as the data source for the last bar set
208 208 Parameter \a lastBarSetSection specifies the section of the model.
209 209 */
210 210 void QBarModelMapper::setLastBarSetSection(int lastBarSetSection)
211 211 {
212 212 Q_D(QBarModelMapper);
213 213 d->m_lastBarSetSection = qMax(-1, lastBarSetSection);
214 214 d->initializeBarFromModel();
215 215 }
216 216
217 217 /*!
218 218 Resets the QBarModelMapper to the default state.
219 219 first: 0; count: -1; firstBarSetSection: -1; lastBarSetSection: -1; categoriesSection: -1
220 220 */
221 221 void QBarModelMapper::reset()
222 222 {
223 223 Q_D(QBarModelMapper);
224 224 d->m_first = 0;
225 225 d->m_count = -1;
226 226 d->m_firstBarSetSection = -1;
227 227 d->m_lastBarSetSection = -1;
228 228 d->initializeBarFromModel();
229 229 }
230 230
231 231 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
232 232
233 233 QBarModelMapperPrivate::QBarModelMapperPrivate(QBarModelMapper *q) :
234 234 m_series(0),
235 235 m_model(0),
236 236 m_first(0),
237 237 m_count(-1),
238 238 m_orientation(Qt::Vertical),
239 239 m_firstBarSetSection(-1),
240 240 m_lastBarSetSection(-1),
241 241 m_seriesSignalsBlock(false),
242 242 m_modelSignalsBlock(false),
243 243 q_ptr(q)
244 244 {
245 245 }
246 246
247 247 void QBarModelMapperPrivate::blockModelSignals(bool block)
248 248 {
249 249 m_modelSignalsBlock = block;
250 250 }
251 251
252 252 void QBarModelMapperPrivate::blockSeriesSignals(bool block)
253 253 {
254 254 m_seriesSignalsBlock = block;
255 255 }
256 256
257 257 QBarSet* QBarModelMapperPrivate::barSet(QModelIndex index)
258 258 {
259 259 if (!index.isValid())
260 260 return 0;
261 261
262 262 if (m_orientation == Qt::Vertical && index.column() >= m_firstBarSetSection && index.column() <= m_lastBarSetSection) {
263 263 if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
264 264 // if (m_model->index(index.row(), m_valuesSection).isValid() && m_model->index(index.row(), m_labelsSection).isValid())
265 265 return m_series->barSets().at(index.column() - m_firstBarSetSection);
266 266 // else
267 267 // return 0;
268 268 }
269 269 } else if (m_orientation == Qt::Horizontal && index.row() >= m_firstBarSetSection && index.row() <= m_lastBarSetSection) {
270 270 if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count))
271 271 return m_series->barSets().at(index.row() - m_firstBarSetSection);
272 272 }
273 273 return 0; // This part of model has not been mapped to any slice
274 274 }
275 275
276 276 QModelIndex QBarModelMapperPrivate::barModelIndex(int barSection, int posInBar)
277 277 {
278 278 if (m_count != -1 && posInBar >= m_count)
279 279 return QModelIndex(); // invalid
280 280
281 281 if (barSection < m_firstBarSetSection || barSection > m_lastBarSetSection)
282 282 return QModelIndex(); // invalid
283 283
284 284 if (m_orientation == Qt::Vertical)
285 285 return m_model->index(posInBar + m_first, barSection);
286 286 else
287 287 return m_model->index(barSection, posInBar + m_first);
288 288 }
289 289
290 290 void QBarModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
291 291 {
292 292 Q_UNUSED(topLeft)
293 293 Q_UNUSED(bottomRight)
294 294
295 295 if (m_model == 0 || m_series == 0)
296 296 return;
297 297
298 298 if (m_modelSignalsBlock)
299 299 return;
300 300
301 301 blockSeriesSignals();
302 302 QModelIndex index;
303 303 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
304 304 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
305 305 index = topLeft.sibling(row, column);
306 306 QBarSet* bar = barSet(index);
307 307 if (bar) {
308 308 if (m_orientation == Qt::Vertical)
309 309 bar->replace(row - m_first, m_model->data(index).toReal());
310 310 else
311 311 bar->replace(column - m_first, m_model->data(index).toReal());
312 312 }
313 313 }
314 314 }
315 315 blockSeriesSignals(false);
316 316 }
317 317
318 318 void QBarModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
319 319 {
320 320 Q_UNUSED(parent);
321 321 Q_UNUSED(end)
322 322 if (m_modelSignalsBlock)
323 323 return;
324 324
325 325 blockSeriesSignals();
326 326 if (m_orientation == Qt::Vertical)
327 327 // insertData(start, end);
328 328 initializeBarFromModel();
329 329 else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
330 330 initializeBarFromModel();
331 331 blockSeriesSignals(false);
332 332 }
333 333
334 334 void QBarModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
335 335 {
336 336 Q_UNUSED(parent);
337 337 Q_UNUSED(end)
338 338 if (m_modelSignalsBlock)
339 339 return;
340 340
341 341 blockSeriesSignals();
342 342 if (m_orientation == Qt::Vertical)
343 343 // removeData(start, end);
344 344 initializeBarFromModel();
345 345 else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
346 346 initializeBarFromModel();
347 347 blockSeriesSignals(false);
348 348 }
349 349
350 350 void QBarModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
351 351 {
352 352 Q_UNUSED(parent);
353 353 Q_UNUSED(end)
354 354 if (m_modelSignalsBlock)
355 355 return;
356 356
357 357 blockSeriesSignals();
358 358 if (m_orientation == Qt::Horizontal)
359 359 // insertData(start, end);
360 360 initializeBarFromModel();
361 361 else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
362 362 initializeBarFromModel();
363 363 blockSeriesSignals(false);
364 364 }
365 365
366 366 void QBarModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
367 367 {
368 368 Q_UNUSED(parent);
369 369 Q_UNUSED(end)
370 370 if (m_modelSignalsBlock)
371 371 return;
372 372
373 373 blockSeriesSignals();
374 374 if (m_orientation == Qt::Horizontal)
375 375 // removeData(start, end);
376 376 initializeBarFromModel();
377 377 else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) // if the changes affect the map - reinitialize
378 378 initializeBarFromModel();
379 379 blockSeriesSignals(false);
380 380 }
381 381
382 382 void QBarModelMapperPrivate::insertData(int start, int end)
383 383 {
384 384 Q_UNUSED(end)
385 385 if (m_model == 0 || m_series == 0)
386 386 return;
387 387
388 388 if (m_count != -1 && start >= m_first + m_count) {
389 389 return;
390 390 } /*else {
391 391 int addedCount = end - start + 1;
392 392 if (m_count != -1 && addedCount > m_count)
393 393 addedCount = m_count;
394 394 int first = qMax(start, m_first);
395 395 int last = qMin(first + addedCount - 1, m_orientation == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
396 396 for (int k = 0; k < m_series->barSets().count(); k++) {
397 397 for (int i = first; i <= last; i++) {
398 398 QBar point;
399 399 point.setX(m_model->data(xModelIndex(i - m_first), Qt::DisplayRole).toDouble());
400 400 point.setY(m_model->data(yModelIndex(i - m_first), Qt::DisplayRole).toDouble());
401 401 m_series->insert(i - m_first, point);
402 402 }
403 403 >>>>>>> Stashed changes
404 404 }
405 405
406 406 // remove excess of slices (abouve m_count)
407 407 if (m_count != -1 && m_series->points().size() > m_count)
408 408 for (int i = m_series->points().size() - 1; i >= m_count; i--) {
409 409 m_series->remove(m_series->points().at(i));
410 410 }
411 411 }*/
412 412 }
413 413
414 414 void QBarModelMapperPrivate::removeData(int start, int end)
415 415 {
416 416 Q_UNUSED(end)
417 417 if (m_model == 0 || m_series == 0)
418 418 return;
419 419
420 420 // int removedCount = end - start + 1;
421 421 if (m_count != -1 && start >= m_first + m_count) {
422 422 return;
423 423 } /*else {
424 424 int toRemove = qMin(m_series->count(), removedCount); // first find how many items can actually be removed
425 425 int first = qMax(start, m_first); // get the index of the first item that will be removed.
426 426 int last = qMin(first + toRemove - 1, m_series->count() + m_first - 1); // get the index of the last item that will be removed.
427 427 for (int i = last; i >= first; i--) {
428 428 m_series->remove(m_series->points().at(i - m_first));
429 429 }
430 430
431 431 if (m_count != -1) {
432 432 int itemsAvailable; // check how many are available to be added
433 433 if (m_orientation == Qt::Vertical)
434 434 itemsAvailable = m_model->rowCount() - m_first - m_series->count();
435 435 else
436 436 itemsAvailable = m_model->columnCount() - m_first - m_series->count();
437 437 int toBeAdded = qMin(itemsAvailable, m_count - m_series->count()); // add not more items than there is space left to be filled.
438 438 int currentSize = m_series->count();
439 439 if (toBeAdded > 0)
440 440 for (int i = m_series->count(); i < currentSize + toBeAdded; i++) {
441 441 QPointF point;
442 442 point.setX(m_model->data(xModelIndex(i), Qt::DisplayRole).toDouble());
443 443 point.setY(m_model->data(yModelIndex(i), Qt::DisplayRole).toDouble());
444 444 m_series->insert(i, point);
445 445 }
446 446 }
447 447 }*/
448 448 }
449 449
450 450 void QBarModelMapperPrivate::initializeBarFromModel()
451 451 {
452 452 if (m_model == 0 || m_series == 0)
453 453 return;
454 454
455 455 blockSeriesSignals();
456 456 // clear current content
457 457 m_series->clear();
458 458
459 459 // create the initial bar sets
460 460 for (int i = m_firstBarSetSection; i <= m_lastBarSetSection; i++) {
461 461 int posInBar = 0;
462 462 QModelIndex barIndex = barModelIndex(i, posInBar);
463 463 // check if there is such model index
464 464 if (barIndex.isValid()) {
465 465 QBarSet *barSet = new QBarSet(m_model->headerData(i, Qt::Horizontal).toString());
466 466 while (barIndex.isValid()) {
467 467 barSet->append(m_model->data(barIndex, Qt::DisplayRole).toDouble());
468 468 posInBar++;
469 469 barIndex = barModelIndex(i, posInBar);
470 470 }
471 471 m_series->append(barSet);
472 472 } else {
473 473 break;
474 474 }
475 475 }
476 476 blockSeriesSignals(false);
477 477 }
478 478
479 479 #include "moc_qbarmodelmapper.cpp"
480 480 #include "moc_qbarmodelmapper_p.cpp"
481 481
482 482 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,78 +1,82
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qhbarmodelmapper.h"
22 22
23 23 QTCOMMERCIALCHART_BEGIN_NAMESPACE
24 24
25 25 /*!
26 26 \class QHBarModelMapper
27 27 \brief part of QtCommercial chart API.
28 28 \mainclass
29 29
30 Nothing here yet
30 Horizontal model mapper is used to create a connection between QBarSeries and QAbstractItemModel derived model object.
31 Curently it is NOT possible to use both QAbstractItemModel and QBarSeries model API.
32 When the series is set to the mapper the QBarSeries and QBarSet API that affect the data (append, setValue, remove) should not be used.
33 The model and the QBarSeries won't be kept in sync. Model API should be used to insert,remove,modify BarSets.
34 NOTE: used model has to support adding/removing rows/columns and modifying the data of the cells.
31 35 */
32 36
33 37 /*!
34 38 \property QHBarModelMapper::firstBarSetRow
35 39 \brief Defines which column of the model is used as the data source for the first bar set
36 40
37 41 Default value is: -1 (invalid mapping)
38 42 */
39 43
40 44 /*!
41 45 \property QHBarModelMapper::lastBarSetRow
42 46 \brief Defines which column of the model is used as the data source for the last bar set
43 47
44 48 Default value is: -1 (invalid mapping)
45 49 */
46 50
47 51 /*!
48 52 Constructs a mapper object which is a child of \a parent.
49 53 */
50 54 QHBarModelMapper::QHBarModelMapper(QObject *parent) :
51 55 QBarModelMapper(parent)
52 56 {
53 57 QBarModelMapper::setOrientation(Qt::Horizontal);
54 58 }
55 59
56 60 int QHBarModelMapper::firstBarSetRow() const
57 61 {
58 62 return QBarModelMapper::firstBarSetSection();
59 63 }
60 64
61 65 void QHBarModelMapper::setFirstBarSetRow(int firstBarSetRow)
62 66 {
63 67 return QBarModelMapper::setFirstBarSetSection(firstBarSetRow);
64 68 }
65 69
66 70 int QHBarModelMapper::lastBarSetRow() const
67 71 {
68 72 return QBarModelMapper::lastBarSetSection();
69 73 }
70 74
71 75 void QHBarModelMapper::setLastBarSetRow(int lastBarSetRow)
72 76 {
73 77 return QBarModelMapper::setLastBarSetSection(lastBarSetRow);
74 78 }
75 79
76 80 #include "moc_qhbarmodelmapper.cpp"
77 81
78 82 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,78 +1,82
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qvbarmodelmapper.h"
22 22
23 23 QTCOMMERCIALCHART_BEGIN_NAMESPACE
24 24
25 25 /*!
26 26 \class QVBarModelMapper
27 27 \brief part of QtCommercial chart API.
28 28 \mainclass
29 29
30 Nothing here yet
30 Vertical model mapper is used to create a connection between QBarSeries and QAbstractItemModel derived model object.
31 Curently it is NOT possible to use both QAbstractItemModel and QBarSeries model API.
32 When the series is set to the mapper the QBarSeries and QBarSet API that affect the data (append, setValue, remove) should not be used.
33 The model and the QBarSeries won't be kept in sync. Model API should be used to insert,remove,modify BarSets.
34 NOTE: used model has to support adding/removing rows/columns and modifying the data of the cells.
31 35 */
32 36
33 37 /*!
34 38 \property QVBarModelMapper::firstBarSetColumn
35 39 \brief Defines which column of the model is used as the data source for the first bar set
36 40
37 41 Default value is: -1 (invalid mapping)
38 42 */
39 43
40 44 /*!
41 45 \property QVBarModelMapper::lastBarSetColumn
42 46 \brief Defines which column of the model is used as the data source for the last bar set
43 47
44 48 Default value is: -1 (invalid mapping)
45 49 */
46 50
47 51 /*!
48 52 Constructs a mapper object which is a child of \a parent.
49 53 */
50 54 QVBarModelMapper::QVBarModelMapper(QObject *parent) :
51 55 QBarModelMapper(parent)
52 56 {
53 57 QBarModelMapper::setOrientation(Qt::Vertical);
54 58 }
55 59
56 60 int QVBarModelMapper::firstBarSetColumn() const
57 61 {
58 62 return QBarModelMapper::firstBarSetSection();
59 63 }
60 64
61 65 void QVBarModelMapper::setFirstBarSetColumn(int firstBarSetColumn)
62 66 {
63 67 return QBarModelMapper::setFirstBarSetSection(firstBarSetColumn);
64 68 }
65 69
66 70 int QVBarModelMapper::lastBarSetColumn() const
67 71 {
68 72 return QBarModelMapper::lastBarSetSection();
69 73 }
70 74
71 75 void QVBarModelMapper::setLastBarSetColumn(int lastBarSetColumn)
72 76 {
73 77 return QBarModelMapper::setLastBarSetSection(lastBarSetColumn);
74 78 }
75 79
76 80 #include "moc_qvbarmodelmapper.cpp"
77 81
78 82 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,94 +1,94
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qhpiemodelmapper.h"
22 22
23 23 QTCOMMERCIALCHART_BEGIN_NAMESPACE
24 24
25 25 /*!
26 26 \class QHPieModelMapper
27 27 \brief part of QtCommercial chart API.
28 28 \mainclass
29 29
30 This class is used to create a connection between QPieSeries and QAbstractItemModel derived model object that keeps the consecutive pie slices data in rows.
30 Horizontal model mapper is used to create a connection between QPieSeries and QAbstractItemModel derived model object that keeps the consecutive pie slices data in rows.
31 31 It is possible to use both QAbstractItemModel and QPieSeries model API. QHPieModelMapper makes sure that Pie and the model are kept in sync.
32 32 NOTE: used model has to support adding/removing rows/columns and modifying the data of the cells.
33 33 */
34 34
35 35 /*!
36 36 \property QHPieModelMapper::valuesRow
37 37 \brief Defines which row of the model is kept in sync with the values of the pie's slices
38 38
39 39 Default value is: -1 (invalid mapping)
40 40 */
41 41
42 42 /*!
43 43 \property QHPieModelMapper::labelsRow
44 44 \brief Defines which row of the model is kept in sync with the labels of the pie's slices
45 45
46 46 Default value is: -1 (invalid mapping)
47 47 */
48 48
49 49 /*!
50 50 Constructs a mapper object which is a child of \a parent.
51 51 */
52 52 QHPieModelMapper::QHPieModelMapper(QObject *parent) :
53 53 QPieModelMapper(parent)
54 54 {
55 55 QPieModelMapper::setOrientation(Qt::Horizontal);
56 56 }
57 57
58 58 /*!
59 59 Returns which row of the model is kept in sync with the values of the pie's slices
60 60 */
61 61 int QHPieModelMapper::valuesRow() const
62 62 {
63 63 return QPieModelMapper::valuesSection();
64 64 }
65 65
66 66 /*!
67 67 Sets the model row that is kept in sync with the pie slices values.
68 68 Parameter \a valuesRow specifies the row of the model.
69 69 */
70 70 void QHPieModelMapper::setValuesRow(int valuesRow)
71 71 {
72 72 QPieModelMapper::setValuesSection(valuesRow);
73 73 }
74 74
75 75 /*!
76 76 Returns which row of the model is kept in sync with the labels of the pie's slices
77 77 */
78 78 int QHPieModelMapper::labelsRow() const
79 79 {
80 80 return QPieModelMapper::labelsSection();
81 81 }
82 82
83 83 /*!
84 84 Sets the model row that is kept in sync with the pie's slices labels.
85 85 Parameter \a labelsRow specifies the row of the model.
86 86 */
87 87 void QHPieModelMapper::setLabelsRow(int labelsRow)
88 88 {
89 89 QPieModelMapper::setLabelsSection(labelsRow);
90 90 }
91 91
92 92 #include "moc_qhpiemodelmapper.cpp"
93 93
94 94 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,596 +1,596
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qpiemodelmapper_p.h"
22 22 #include "qpiemodelmapper.h"
23 23 #include "qpieseries.h"
24 24 #include "qpieslice.h"
25 25 #include <QAbstractItemModel>
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 /*!
30 30 \property QPieModelMapper::series
31 31 \brief Defines the QPieSeries object that is used by the mapper.
32 32
33 All the data in the series in the series is discarded when it is set to the mapper.
33 All the data in the series is discarded when it is set to the mapper.
34 34 When new series is specified the old series is disconnected (it preserves its data)
35 35 */
36 36
37 37 /*!
38 38 \property QPieModelMapper::model
39 39 \brief Defines the model that is used by the mapper.
40 40 */
41 41
42 42 /*!
43 43 \property QPieModelMapper::first
44 44 \brief Defines which item of the model's row/column should be mapped as the value/label of the first slice of the pie
45 45
46 46 Minimal and default value is: 0
47 47 */
48 48
49 49 /*!
50 50 \property QPieModelMapper::count
51 51 \brief Defines the number of rows/columns of the model that are mapped as the data for the pie.
52 52
53 53 Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
54 54 */
55 55
56 56 /*!
57 57 \class QPieModelMapper
58 58 \brief part of QtCommercial chart API.
59 59 \mainclass
60 60
61 61 The instance of this class cannot be created directly. QHPieModelMapper of QVPieModelMapper should be used instead. This class is used to create a connection between QPieSeries and QAbstractItemModel derived model object.
62 62 It is possible to use both QAbstractItemModel and QPieSeries model API. QPieModelMapper makes sure that Pie and the model are kept in sync.
63 63 NOTE: used model has to support adding/removing rows/columns and modifying the data of the cells.
64 64 */
65 65
66 66 /*!
67 67 Constructs a mapper object which is a child of \a parent.
68 68 */
69 69 QPieModelMapper::QPieModelMapper(QObject *parent) :
70 70 QObject(parent),
71 71 d_ptr(new QPieModelMapperPrivate(this))
72 72 {
73 73 }
74 74
75 75 QAbstractItemModel* QPieModelMapper::model() const
76 76 {
77 77 Q_D(const QPieModelMapper);
78 78 return d->m_model;
79 79 }
80 80
81 81 void QPieModelMapper::setModel(QAbstractItemModel *model)
82 82 {
83 83 if (model == 0)
84 84 return;
85 85
86 86 Q_D(QPieModelMapper);
87 87 if (d->m_model) {
88 88 disconnect(d->m_model, 0, d, 0);
89 89 }
90 90
91 91 d->m_model = model;
92 92 d->initializePieFromModel();
93 93 // connect signals from the model
94 94 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
95 95 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
96 96 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
97 97 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
98 98 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
99 99 }
100 100
101 101 QPieSeries* QPieModelMapper::series() const
102 102 {
103 103 Q_D(const QPieModelMapper);
104 104 return d->m_series;
105 105 }
106 106
107 107 void QPieModelMapper::setSeries(QPieSeries *series)
108 108 {
109 109 Q_D(QPieModelMapper);
110 110 if (d->m_series) {
111 111 disconnect(d->m_series, 0, d, 0);
112 112 }
113 113
114 114 if (series == 0)
115 115 return;
116 116
117 117 d->m_series = series;
118 118 d->initializePieFromModel();
119 119 // connect the signals from the series
120 120 connect(d->m_series, SIGNAL(added(QList<QPieSlice*>)), d, SLOT(slicesAdded(QList<QPieSlice*>)));
121 121 connect(d->m_series, SIGNAL(removed(QList<QPieSlice*>)), d, SLOT(slicesRemoved(QList<QPieSlice*>)));
122 122 }
123 123
124 124 int QPieModelMapper::first() const
125 125 {
126 126 Q_D(const QPieModelMapper);
127 127 return d->m_first;
128 128 }
129 129
130 130 void QPieModelMapper::setFirst(int first)
131 131 {
132 132 Q_D(QPieModelMapper);
133 133 d->m_first = qMax(first, 0);
134 134 d->initializePieFromModel();
135 135 }
136 136
137 137 int QPieModelMapper::count() const
138 138 {
139 139 Q_D(const QPieModelMapper);
140 140 return d->m_count;
141 141 }
142 142
143 143 void QPieModelMapper::setCount(int count)
144 144 {
145 145 Q_D(QPieModelMapper);
146 146 d->m_count = qMax(count, -1);
147 147 d->initializePieFromModel();
148 148 }
149 149
150 150 /*!
151 151 Returns the orientation that is used when QPieModelMapper accesses the model.
152 152 This mean whether the consecutive values/labels of the pie are read from row (Qt::Horizontal)
153 153 or from columns (Qt::Vertical)
154 154 */
155 155 Qt::Orientation QPieModelMapper::orientation() const
156 156 {
157 157 Q_D(const QPieModelMapper);
158 158 return d->m_orientation;
159 159 }
160 160
161 161 /*!
162 162 Returns the \a orientation that is used when QPieModelMapper accesses the model.
163 163 This mean whether the consecutive values/labels of the pie are read from row (Qt::Horizontal)
164 164 or from columns (Qt::Vertical)
165 165 */
166 166 void QPieModelMapper::setOrientation(Qt::Orientation orientation)
167 167 {
168 168 Q_D(QPieModelMapper);
169 169 d->m_orientation = orientation;
170 170 d->initializePieFromModel();
171 171 }
172 172
173 173 /*!
174 174 Returns which section of the model is kept in sync with the values of the pie's slices
175 175 */
176 176 int QPieModelMapper::valuesSection() const
177 177 {
178 178 Q_D(const QPieModelMapper);
179 179 return d->m_valuesSection;
180 180 }
181 181
182 182 /*!
183 183 Sets the model section that is kept in sync with the pie slices values.
184 184 Parameter \a valuesSection specifies the section of the model.
185 185 */
186 186 void QPieModelMapper::setValuesSection(int valuesSection)
187 187 {
188 188 Q_D(QPieModelMapper);
189 189 d->m_valuesSection = qMax(-1, valuesSection);
190 190 d->initializePieFromModel();
191 191 }
192 192
193 193 /*!
194 194 Returns which section of the model is kept in sync with the labels of the pie's slices
195 195 */
196 196 int QPieModelMapper::labelsSection() const
197 197 {
198 198 Q_D(const QPieModelMapper);
199 199 return d->m_labelsSection;
200 200 }
201 201
202 202 /*!
203 203 Sets the model section that is kept in sync with the pie slices labels.
204 204 Parameter \a labelsSection specifies the section of the model.
205 205 */
206 206 void QPieModelMapper::setLabelsSection(int labelsSection)
207 207 {
208 208 Q_D(QPieModelMapper);
209 209 d->m_labelsSection = qMax(-1, labelsSection);
210 210 d->initializePieFromModel();
211 211 }
212 212
213 213 /*!
214 214 Resets the QPieModelMapper to the default state.
215 215 first: 0; count: -1; valuesSection: -1; labelsSection: -1;
216 216 */
217 217 void QPieModelMapper::reset()
218 218 {
219 219 Q_D(QPieModelMapper);
220 220 d->m_first = 0;
221 221 d->m_count = -1;
222 222 d->m_valuesSection = -1;
223 223 d->m_labelsSection = -1;
224 224 }
225 225
226 226 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
227 227
228 228 QPieModelMapperPrivate::QPieModelMapperPrivate(QPieModelMapper *q) :
229 229 m_series(0),
230 230 m_model(0),
231 231 m_first(0),
232 232 m_count(-1),
233 233 m_orientation(Qt::Vertical),
234 234 m_valuesSection(-1),
235 235 m_labelsSection(-1),
236 236 m_seriesSignalsBlock(false),
237 237 m_modelSignalsBlock(false),
238 238 q_ptr(q)
239 239 {
240 240 }
241 241
242 242 void QPieModelMapperPrivate::blockModelSignals(bool block)
243 243 {
244 244 m_modelSignalsBlock = block;
245 245 }
246 246
247 247 void QPieModelMapperPrivate::blockSeriesSignals(bool block)
248 248 {
249 249 m_seriesSignalsBlock = block;
250 250 }
251 251
252 252
253 253 QPieSlice* QPieModelMapperPrivate::pieSlice(QModelIndex index) const
254 254 {
255 255 if (!index.isValid())
256 256 return 0; // index is invalid
257 257
258 258 if (m_orientation == Qt::Vertical && (index.column() == m_valuesSection || index.column() == m_labelsSection)) {
259 259 if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
260 260 if (m_model->index(index.row(), m_valuesSection).isValid() && m_model->index(index.row(), m_labelsSection).isValid())
261 261 return m_series->slices().at(index.row() - m_first);
262 262 else
263 263 return 0;
264 264 }
265 265 } else if (m_orientation == Qt::Horizontal && (index.row() == m_valuesSection || index.row() == m_labelsSection)) {
266 266 if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count)) {
267 267 if (m_model->index(m_valuesSection, index.column()).isValid() && m_model->index(m_labelsSection, index.column()).isValid())
268 268 return m_series->slices().at(index.column() - m_first);
269 269 else
270 270 return 0;
271 271 }
272 272 }
273 273 return 0; // This part of model has not been mapped to any slice
274 274 }
275 275
276 276 QModelIndex QPieModelMapperPrivate::valueModelIndex(int slicePos)
277 277 {
278 278 if (m_count != -1 && slicePos >= m_count)
279 279 return QModelIndex(); // invalid
280 280
281 281 if (m_orientation == Qt::Vertical)
282 282 return m_model->index(slicePos + m_first, m_valuesSection);
283 283 else
284 284 return m_model->index(m_valuesSection, slicePos + m_first);
285 285 }
286 286
287 287 QModelIndex QPieModelMapperPrivate::labelModelIndex(int slicePos)
288 288 {
289 289 if (m_count != -1 && slicePos >= m_count)
290 290 return QModelIndex(); // invalid
291 291
292 292 if (m_orientation == Qt::Vertical)
293 293 return m_model->index(slicePos + m_first, m_labelsSection);
294 294 else
295 295 return m_model->index(m_labelsSection, slicePos + m_first);
296 296 }
297 297
298 298 bool QPieModelMapperPrivate::isLabelIndex(QModelIndex index) const
299 299 {
300 300 if (m_orientation == Qt::Vertical && index.column() == m_labelsSection)
301 301 return true;
302 302 else if (m_orientation == Qt::Horizontal && index.row() == m_labelsSection)
303 303 return true;
304 304
305 305 return false;
306 306 }
307 307
308 308 bool QPieModelMapperPrivate::isValueIndex(QModelIndex index) const
309 309 {
310 310 if (m_orientation == Qt::Vertical && index.column() == m_valuesSection)
311 311 return true;
312 312 else if (m_orientation == Qt::Horizontal && index.row() == m_valuesSection)
313 313 return true;
314 314
315 315 return false;
316 316 }
317 317
318 318 void QPieModelMapperPrivate::slicesAdded(QList<QPieSlice*> slices)
319 319 {
320 320 if (m_seriesSignalsBlock)
321 321 return;
322 322
323 323 if (slices.count() == 0)
324 324 return;
325 325
326 326 int firstIndex = m_series->slices().indexOf(slices.at(0));
327 327 if (firstIndex == -1)
328 328 return;
329 329
330 330 if (m_count != -1)
331 331 m_count += slices.count();
332 332
333 333 for (int i = firstIndex; i < firstIndex + slices.count(); i++) {
334 334 m_slices.insert(i, slices.at(i - firstIndex));
335 335 connect(slices.at(i - firstIndex), SIGNAL(labelChanged()), this, SLOT(sliceLabelChanged()));
336 336 connect(slices.at(i - firstIndex), SIGNAL(valueChanged()), this, SLOT(sliceValueChanged()));
337 337 }
338 338
339 339 blockModelSignals();
340 340 if (m_orientation == Qt::Vertical)
341 341 m_model->insertRows(firstIndex + m_first, slices.count());
342 342 else
343 343 m_model->insertColumns(firstIndex + m_first, slices.count());
344 344
345 345 for(int i = firstIndex; i < firstIndex + slices.count(); i++) {
346 346 m_model->setData(valueModelIndex(i), slices.at(i - firstIndex)->value());
347 347 m_model->setData(labelModelIndex(i), slices.at(i - firstIndex)->label());
348 348 }
349 349 blockModelSignals(false);
350 350 }
351 351
352 352 void QPieModelMapperPrivate::slicesRemoved(QList<QPieSlice*> slices)
353 353 {
354 354 if (m_seriesSignalsBlock)
355 355 return;
356 356
357 357 if (slices.count() == 0)
358 358 return;
359 359
360 360 int firstIndex = m_slices.indexOf(slices.at(0));
361 361 if (firstIndex == -1)
362 362 return;
363 363
364 364 if (m_count != -1)
365 365 m_count -= slices.count();
366 366
367 367 for (int i = firstIndex + slices.count() - 1; i >= firstIndex; i--)
368 368 m_slices.removeAt(i);
369 369
370 370 blockModelSignals();
371 371 if (m_orientation == Qt::Vertical)
372 372 m_model->removeRows(firstIndex + m_first, slices.count());
373 373 else
374 374 m_model->removeColumns(firstIndex + m_first, slices.count());
375 375 blockModelSignals(false);
376 376 }
377 377
378 378 void QPieModelMapperPrivate::sliceLabelChanged()
379 379 {
380 380 if (m_seriesSignalsBlock)
381 381 return;
382 382
383 383 blockModelSignals();
384 384 QPieSlice *slice = qobject_cast<QPieSlice *>(QObject::sender());
385 385 m_model->setData(labelModelIndex(m_series->slices().indexOf(slice)), slice->label());
386 386 blockModelSignals(false);
387 387 }
388 388
389 389 void QPieModelMapperPrivate::sliceValueChanged()
390 390 {
391 391 if (m_seriesSignalsBlock)
392 392 return;
393 393
394 394 blockModelSignals();
395 395 QPieSlice *slice = qobject_cast<QPieSlice *>(QObject::sender());
396 396 m_model->setData(valueModelIndex(m_series->slices().indexOf(slice)), slice->value());
397 397 blockModelSignals(false);
398 398 }
399 399
400 400 void QPieModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
401 401 {
402 402 if (m_model == 0 || m_series == 0)
403 403 return;
404 404
405 405 if (m_modelSignalsBlock)
406 406 return;
407 407
408 408 blockSeriesSignals();
409 409 QModelIndex index;
410 410 QPieSlice *slice;
411 411 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
412 412 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
413 413 index = topLeft.sibling(row, column);
414 414 slice = pieSlice(index);
415 415 if (slice) {
416 416 if (isValueIndex(index))
417 417 slice->setValue(m_model->data(index, Qt::DisplayRole).toReal());
418 418 if (isLabelIndex(index))
419 419 slice->setLabel(m_model->data(index, Qt::DisplayRole).toString());
420 420 }
421 421 }
422 422 }
423 423 blockSeriesSignals(false);
424 424 }
425 425
426 426
427 427 void QPieModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
428 428 {
429 429 Q_UNUSED(parent);
430 430 if (m_modelSignalsBlock)
431 431 return;
432 432
433 433 blockSeriesSignals();
434 434 if (m_orientation == Qt::Vertical)
435 435 insertData(start, end);
436 436 else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
437 437 initializePieFromModel();
438 438 blockSeriesSignals(false);
439 439 }
440 440
441 441 void QPieModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
442 442 {
443 443 Q_UNUSED(parent);
444 444 if (m_modelSignalsBlock)
445 445 return;
446 446
447 447 blockSeriesSignals();
448 448 if (m_orientation == Qt::Vertical)
449 449 removeData(start, end);
450 450 else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
451 451 initializePieFromModel();
452 452 blockSeriesSignals(false);
453 453 }
454 454
455 455 void QPieModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
456 456 {
457 457 Q_UNUSED(parent);
458 458 if (m_modelSignalsBlock)
459 459 return;
460 460
461 461 blockSeriesSignals();
462 462 if (m_orientation == Qt::Horizontal)
463 463 insertData(start, end);
464 464 else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
465 465 initializePieFromModel();
466 466 blockSeriesSignals(false);
467 467 }
468 468
469 469 void QPieModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
470 470 {
471 471 Q_UNUSED(parent);
472 472 if (m_modelSignalsBlock)
473 473 return;
474 474
475 475 blockSeriesSignals();
476 476 if (m_orientation == Qt::Horizontal)
477 477 removeData(start, end);
478 478 else if (start <= m_valuesSection || start <= m_labelsSection) // if the changes affect the map - reinitialize the pie
479 479 initializePieFromModel();
480 480 blockSeriesSignals(false);
481 481 }
482 482
483 483 void QPieModelMapperPrivate::insertData(int start, int end)
484 484 {
485 485 if (m_model == 0 || m_series == 0)
486 486 return;
487 487
488 488 if (m_count != -1 && start >= m_first + m_count) {
489 489 return;
490 490 } else {
491 491 int addedCount = end - start + 1;
492 492 if (m_count != -1 && addedCount > m_count)
493 493 addedCount = m_count;
494 494 int first = qMax(start, m_first);
495 495 int last = qMin(first + addedCount - 1, m_orientation == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
496 496 for (int i = first; i <= last; i++) {
497 497 QModelIndex valueIndex = valueModelIndex(i - m_first);
498 498 QModelIndex labelIndex = labelModelIndex(i - m_first);
499 499 if (valueIndex.isValid() && labelIndex.isValid()) {
500 500 QPieSlice *slice = new QPieSlice;
501 501 slice->setValue(m_model->data(valueIndex, Qt::DisplayRole).toDouble());
502 502 slice->setLabel(m_model->data(labelIndex, Qt::DisplayRole).toString());
503 503 slice->setLabelVisible();
504 504 connect(slice, SIGNAL(labelChanged()), this, SLOT(sliceLabelChanged()));
505 505 connect(slice, SIGNAL(valueChanged()), this, SLOT(sliceValueChanged()));
506 506 m_series->insert(i - m_first, slice);
507 507 m_slices.insert(i - m_first, slice);
508 508 }
509 509 }
510 510
511 511 // remove excess of slices (abouve m_count)
512 512 if (m_count != -1 && m_series->slices().size() > m_count)
513 513 for (int i = m_series->slices().size() - 1; i >= m_count; i--) {
514 514 m_series->remove(m_series->slices().at(i));
515 515 m_slices.removeAt(i);
516 516 }
517 517 }
518 518 }
519 519
520 520 void QPieModelMapperPrivate::removeData(int start, int end)
521 521 {
522 522 if (m_model == 0 || m_series == 0)
523 523 return;
524 524
525 525 int removedCount = end - start + 1;
526 526 if (m_count != -1 && start >= m_first + m_count) {
527 527 return;
528 528 } else {
529 529 int toRemove = qMin(m_series->slices().size(), removedCount); // first find how many items can actually be removed
530 530 int first = qMax(start, m_first); // get the index of the first item that will be removed.
531 531 int last = qMin(first + toRemove - 1, m_series->slices().size() + m_first - 1); // get the index of the last item that will be removed.
532 532 for (int i = last; i >= first; i--) {
533 533 m_series->remove(m_series->slices().at(i - m_first));
534 534 m_slices.removeAt(i - m_first);
535 535 }
536 536
537 537 if (m_count != -1) {
538 538 int itemsAvailable; // check how many are available to be added
539 539 if (m_orientation == Qt::Vertical)
540 540 itemsAvailable = m_model->rowCount() - m_first - m_series->slices().size();
541 541 else
542 542 itemsAvailable = m_model->columnCount() - m_first - m_series->slices().size();
543 543 int toBeAdded = qMin(itemsAvailable, m_count - m_series->slices().size()); // add not more items than there is space left to be filled.
544 544 int currentSize = m_series->slices().size();
545 545 if (toBeAdded > 0)
546 546 for (int i = m_series->slices().size(); i < currentSize + toBeAdded; i++) {
547 547 QModelIndex valueIndex = valueModelIndex(i - m_first);
548 548 QModelIndex labelIndex = labelModelIndex(i - m_first);
549 549 if (valueIndex.isValid() && labelIndex.isValid()) {
550 550 QPieSlice *slice = new QPieSlice;
551 551 slice->setValue(m_model->data(valueIndex, Qt::DisplayRole).toDouble());
552 552 slice->setLabel(m_model->data(labelIndex, Qt::DisplayRole).toString());
553 553 slice->setLabelVisible();
554 554 m_series->insert(i, slice);
555 555 m_slices.insert(i, slice);
556 556 }
557 557 }
558 558 }
559 559 }
560 560 }
561 561
562 562 void QPieModelMapperPrivate::initializePieFromModel()
563 563 {
564 564 if (m_model == 0 || m_series == 0)
565 565 return;
566 566
567 567 blockSeriesSignals();
568 568 // clear current content
569 569 m_series->clear();
570 570 m_slices.clear();
571 571
572 572 // create the initial slices set
573 573 int slicePos = 0;
574 574 QModelIndex valueIndex = valueModelIndex(slicePos);
575 575 QModelIndex labelIndex = labelModelIndex(slicePos);
576 576 while (valueIndex.isValid() && labelIndex.isValid()) {
577 577 QPieSlice *slice = new QPieSlice;
578 578 slice->setLabel(m_model->data(labelIndex, Qt::DisplayRole).toString());
579 579 slice->setValue(m_model->data(valueIndex, Qt::DisplayRole).toDouble());
580 580 connect(slice, SIGNAL(labelChanged()), this, SLOT(sliceLabelChanged()));
581 581 connect(slice, SIGNAL(valueChanged()), this, SLOT(sliceValueChanged()));
582 582 m_series->append(slice);
583 583 m_slices.append(slice);
584 584 // m_series->append(m_model->data(labelIndex, Qt::DisplayRole).toString(), m_model->data(valueIndex, Qt::DisplayRole).toDouble());
585 585 slicePos++;
586 586 valueIndex = valueModelIndex(slicePos);
587 587 labelIndex = labelModelIndex(slicePos);
588 588 }
589 589 m_series->setLabelsVisible(true);
590 590 blockSeriesSignals(false);
591 591 }
592 592
593 593 #include "moc_qpiemodelmapper_p.cpp"
594 594 #include "moc_qpiemodelmapper.cpp"
595 595
596 596 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,94 +1,94
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qvpiemodelmapper.h"
22 22
23 23 QTCOMMERCIALCHART_BEGIN_NAMESPACE
24 24
25 25 /*!
26 26 \class QVPieModelMapper
27 27 \brief part of QtCommercial chart API.
28 28 \mainclass
29 29
30 This class is used to create a connection between QPieSeries and QAbstractItemModel derived model object that keeps the consecutive pie slices data in columns.
30 Vertical model mapper is used to create a connection between QPieSeries and QAbstractItemModel derived model object that keeps the consecutive pie slices data in columns.
31 31 It is possible to use both QAbstractItemModel and QPieSeries model API. QVPieModelMapper makes sure that Pie and the model are kept in sync.
32 32 NOTE: used model has to support adding/removing rows/columns and modifying the data of the cells.
33 33 */
34 34
35 35 /*!
36 36 \property QVPieModelMapper::valuesColumn
37 37 \brief Defines which column of the model is kept in sync with the values of the pie's slices
38 38
39 39 Default value is: -1 (invalid mapping)
40 40 */
41 41
42 42 /*!
43 43 \property QVPieModelMapper::labelsColumn
44 44 \brief Defines which column of the model is kept in sync with the labels of the pie's slices
45 45
46 46 Default value is: -1 (invalid mapping)
47 47 */
48 48
49 49 /*!
50 50 Constructs a mapper object which is a child of \a parent.
51 51 */
52 52 QVPieModelMapper::QVPieModelMapper(QObject *parent) :
53 53 QPieModelMapper(parent)
54 54 {
55 55 QPieModelMapper::setOrientation(Qt::Vertical);
56 56 }
57 57
58 58 /*!
59 59 Returns which column of the model is kept in sync with the values of the pie's slices
60 60 */
61 61 int QVPieModelMapper::valuesColumn() const
62 62 {
63 63 return QPieModelMapper::valuesSection();
64 64 }
65 65
66 66 /*!
67 67 Sets the model column that is kept in sync with the pie slices values.
68 68 Parameter \a valuesColumn specifies the row of the model.
69 69 */
70 70 void QVPieModelMapper::setValuesColumn(int valuesColumn)
71 71 {
72 72 QPieModelMapper::setValuesSection(valuesColumn);
73 73 }
74 74
75 75 /*!
76 76 Returns which column of the model is kept in sync with the labels of the pie's slices
77 77 */
78 78 int QVPieModelMapper::labelsColumn() const
79 79 {
80 80 return QPieModelMapper::labelsSection();
81 81 }
82 82
83 83 /*!
84 84 Sets the model column that is kept in sync with the pie's slices labels.
85 85 Parameter \a labelsColumn specifies the row of the model.
86 86 */
87 87 void QVPieModelMapper::setLabelsColumn(int labelsColumn)
88 88 {
89 89 QPieModelMapper::setLabelsSection(labelsColumn);
90 90 }
91 91
92 92 #include "moc_qvpiemodelmapper.cpp"
93 93
94 94 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,77 +1,79
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qhxymodelmapper.h"
22 22
23 23 QTCOMMERCIALCHART_BEGIN_NAMESPACE
24 24
25 25 /*!
26 26 \class QHXYModelMapper
27 27 \brief part of QtCommercial chart API.
28 28 \mainclass
29 29
30 Nothing here yet
30 Horizontal model mapper is used to create a connection between QXYSeries and QAbstractItemModel derived model object.
31 It is possible to use both QAbstractItemModel and QXYSeries model API. QXYModelMapper makes sure that QXYSeries and the model are kept in sync.
32 NOTE: used model has to support adding/removing rows/columns and modifying the data of the cells.
31 33 */
32 34
33 35 /*!
34 36 \property QHXYModelMapper::xRow
35 37 \brief Defines which row of the model is kept in sync with the x values of the QXYSeries
36 38 Default value is: -1 (invalid mapping)
37 39 */
38 40
39 41 /*!
40 42 \property QHXYModelMapper::yRow
41 43 \brief Defines which row of the model is kept in sync with the y values of the QXYSeries
42 44
43 45 Default value is: -1 (invalid mapping)
44 46 */
45 47
46 48 /*!
47 49 Constructs a mapper object which is a child of \a parent.
48 50 */
49 51 QHXYModelMapper::QHXYModelMapper(QObject *parent) :
50 52 QXYModelMapper(parent)
51 53 {
52 54 QXYModelMapper::setOrientation(Qt::Horizontal);
53 55 }
54 56
55 57 int QHXYModelMapper::xRow() const
56 58 {
57 59 return QXYModelMapper::xSection();
58 60 }
59 61
60 62 void QHXYModelMapper::setXRow(int xRow)
61 63 {
62 64 return QXYModelMapper::setXSection(xRow);
63 65 }
64 66
65 67 int QHXYModelMapper::yRow() const
66 68 {
67 69 return QXYModelMapper::ySection();
68 70 }
69 71
70 72 void QHXYModelMapper::setYRow(int yRow)
71 73 {
72 74 return QXYModelMapper::setYSection(yRow);
73 75 }
74 76
75 77 #include "moc_qhxymodelmapper.cpp"
76 78
77 79 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,521 +1,521
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qxymodelmapper.h"
22 22 #include "qxymodelmapper_p.h"
23 23 #include "qxyseries.h"
24 24 #include <QAbstractItemModel>
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 /*!
29 \class QXYModelMapper
30 \brief part of QtCommercial chart API.
31 \mainclass
32
33 The instance of this class cannot be created directly. QHXYModelMapper of QVXYModelMapper should be used instead. This class is used to create a connection between QXYSeries and QAbstractItemModel derived model object.
34 It is possible to use both QAbstractItemModel and QXYSeries model API. QXYModelMapper makes sure that QXYSeries and the model are kept in sync.
35 NOTE: used model has to support adding/removing rows/columns and modifying the data of the cells.
36 */
37
38 /*!
29 39 \property QXYModelMapper::series
30 40 \brief Defines the QPieSeries object that is used by the mapper.
31 41
32 All the data in the series in the series is discarded when it is set to the mapper.
42 All the data in the series is discarded when it is set to the mapper.
33 43 When new series is specified the old series is disconnected (it preserves its data)
34 44 */
35 45
36 46 /*!
37 47 \property QXYModelMapper::model
38 48 \brief Defines the model that is used by the mapper.
39 49 */
40 50
41 51 /*!
42 52 \property QXYModelMapper::first
43 53 \brief Defines which item of the model's row/column should be mapped as the first x/y pair
44 54
45 55 Minimal and default value is: 0
46 56 */
47 57
48 58 /*!
49 59 \property QXYModelMapper::count
50 60 \brief Defines the number of rows/columns of the model that are mapped as the data for QXYSeries
51 61
52 62 Minimal and default value is: -1 (count limited by the number of rows/columns in the model)
53 63 */
54 64
55 65 /*!
56 \class QXYModelMapper
57 \brief part of QtCommercial chart API.
58 \mainclass
59
60 The instance of this class cannot be created directly. QHXYModelMapper of QVXYModelMapper should be used instead. This class is used to create a connection between QXYSeries and QAbstractItemModel derived model object.
61 It is possible to use both QAbstractItemModel and QXYSeries model API. QXYModelMapper makes sure that QXYSeries and the model are kept in sync.
62 NOTE: used model has to support adding/removing rows/columns and modifying the data of the cells.
63 */
64
65 /*!
66 66 Constructs a mapper object which is a child of \a parent.
67 67 */
68 68 QXYModelMapper::QXYModelMapper(QObject *parent):
69 69 QObject(parent),
70 70 d_ptr(new QXYModelMapperPrivate(this))
71 71 {
72 72 }
73 73
74 74 QAbstractItemModel* QXYModelMapper::model() const
75 75 {
76 76 Q_D(const QXYModelMapper);
77 77 return d->m_model;
78 78 }
79 79
80 80 void QXYModelMapper::setModel(QAbstractItemModel *model)
81 81 {
82 82 if (model == 0)
83 83 return;
84 84
85 85 Q_D(QXYModelMapper);
86 86 if (d->m_model) {
87 87 disconnect(d->m_model, 0, d, 0);
88 88 }
89 89
90 90 d->m_model = model;
91 91 d->initializeXYFromModel();
92 92 // connect signals from the model
93 93 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
94 94 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
95 95 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
96 96 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
97 97 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
98 98 }
99 99
100 100 QXYSeries* QXYModelMapper::series() const
101 101 {
102 102 Q_D(const QXYModelMapper);
103 103 return d->m_series;
104 104 }
105 105
106 106 void QXYModelMapper::setSeries(QXYSeries *series)
107 107 {
108 108 Q_D(QXYModelMapper);
109 109 if (d->m_series) {
110 110 disconnect(d->m_series, 0, d, 0);
111 111 }
112 112
113 113 if (series == 0)
114 114 return;
115 115
116 116 d->m_series = series;
117 117 d->initializeXYFromModel();
118 118 // connect the signals from the series
119 119 connect(d->m_series, SIGNAL(pointAdded(int)), d, SLOT(handlePointAdded(int)));
120 120 connect(d->m_series, SIGNAL(pointRemoved(int)), d, SLOT(handlePointRemoved(int)));
121 121 connect(d->m_series, SIGNAL(pointReplaced(int)), d, SLOT(handlePointReplaced(int)));
122 122 }
123 123
124 124 int QXYModelMapper::first() const
125 125 {
126 126 Q_D(const QXYModelMapper);
127 127 return d->m_first;
128 128 }
129 129
130 130 void QXYModelMapper::setFirst(int first)
131 131 {
132 132 Q_D(QXYModelMapper);
133 133 d->m_first = qMax(first, 0);
134 134 d->initializeXYFromModel();
135 135 }
136 136
137 137 int QXYModelMapper::count() const
138 138 {
139 139 Q_D(const QXYModelMapper);
140 140 return d->m_count;
141 141 }
142 142
143 143 void QXYModelMapper::setCount(int count)
144 144 {
145 145 Q_D(QXYModelMapper);
146 146 d->m_count = qMax(count, -1);
147 147 d->initializeXYFromModel();
148 148 }
149 149
150 150 /*!
151 151 Returns the orientation that is used when QXYModelMapper accesses the model.
152 152 This mean whether the consecutive x/y values of the QXYSeries are read from rows (Qt::Horizontal)
153 153 or from columns (Qt::Vertical)
154 154 */
155 155 Qt::Orientation QXYModelMapper::orientation() const
156 156 {
157 157 Q_D(const QXYModelMapper);
158 158 return d->m_orientation;
159 159 }
160 160
161 161 /*!
162 162 Returns the \a orientation that is used when QXYModelMapper accesses the model.
163 163 This mean whether the consecutive x/y values of the QXYSeries are read from rows (Qt::Horizontal)
164 164 or from columns (Qt::Vertical)
165 165 */
166 166 void QXYModelMapper::setOrientation(Qt::Orientation orientation)
167 167 {
168 168 Q_D(QXYModelMapper);
169 169 d->m_orientation = orientation;
170 170 d->initializeXYFromModel();
171 171 }
172 172
173 173 /*!
174 174 Returns which section of the model is kept in sync with the x values of the QXYSeries
175 175 */
176 176 int QXYModelMapper::xSection() const
177 177 {
178 178 Q_D(const QXYModelMapper);
179 179 return d->m_xSection;
180 180 }
181 181
182 182 /*!
183 183 Sets the model section that is kept in sync with the x values of the QXYSeries.
184 184 Parameter \a xSection specifies the section of the model.
185 185 */
186 186 void QXYModelMapper::setXSection(int xSection)
187 187 {
188 188 Q_D(QXYModelMapper);
189 189 d->m_xSection = qMax(-1, xSection);
190 190 d->initializeXYFromModel();
191 191 }
192 192
193 193 /*!
194 194 Returns which section of the model is kept in sync with the y values of the QXYSeries
195 195 */
196 196 int QXYModelMapper::ySection() const
197 197 {
198 198 Q_D(const QXYModelMapper);
199 199 return d->m_ySection;
200 200 }
201 201
202 202 /*!
203 203 Sets the model section that is kept in sync with the y values of the QXYSeries.
204 204 Parameter \a ySection specifies the section of the model.
205 205 */
206 206 void QXYModelMapper::setYSection(int ySection)
207 207 {
208 208 Q_D(QXYModelMapper);
209 209 d->m_ySection = qMax(-1, ySection);
210 210 d->initializeXYFromModel();
211 211 }
212 212
213 213 /*!
214 214 Resets the QXYModelMapper to the default state.
215 215 first: 0; count: -1; xSection: -1; ySection: -1;
216 216 */
217 217 void QXYModelMapper::reset()
218 218 {
219 219 Q_D(QXYModelMapper);
220 220 d->m_first = 0;
221 221 d->m_count = -1;
222 222 d->m_orientation = Qt::Vertical;
223 223 d->m_xSection = -1;
224 224 d->m_ySection = -1;
225 225 d->initializeXYFromModel();
226 226 }
227 227
228 228 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
229 229
230 230 QXYModelMapperPrivate::QXYModelMapperPrivate(QXYModelMapper *q) :
231 231 m_series(0),
232 232 m_model(0),
233 233 m_first(0),
234 234 m_count(-1),
235 235 m_orientation(Qt::Vertical),
236 236 m_xSection(-1),
237 237 m_ySection(-1),
238 238 m_seriesSignalsBlock(false),
239 239 m_modelSignalsBlock(false),
240 240 q_ptr(q)
241 241 {
242 242 }
243 243
244 244 void QXYModelMapperPrivate::blockModelSignals(bool block)
245 245 {
246 246 m_modelSignalsBlock = block;
247 247 }
248 248
249 249 void QXYModelMapperPrivate::blockSeriesSignals(bool block)
250 250 {
251 251 m_seriesSignalsBlock = block;
252 252 }
253 253
254 254 QModelIndex QXYModelMapperPrivate::xModelIndex(int xPos)
255 255 {
256 256 if (m_count != -1 && xPos >= m_count)
257 257 return QModelIndex(); // invalid
258 258
259 259 if (m_orientation == Qt::Vertical)
260 260 return m_model->index(xPos + m_first, m_xSection);
261 261 else
262 262 return m_model->index(m_xSection, xPos + m_first);
263 263 }
264 264
265 265 QModelIndex QXYModelMapperPrivate::yModelIndex(int yPos)
266 266 {
267 267 if (m_count != -1 && yPos >= m_count)
268 268 return QModelIndex(); // invalid
269 269
270 270 if (m_orientation == Qt::Vertical)
271 271 return m_model->index(yPos + m_first, m_ySection);
272 272 else
273 273 return m_model->index(m_ySection, yPos + m_first);
274 274 }
275 275
276 276 void QXYModelMapperPrivate::handlePointAdded(int pointPos)
277 277 {
278 278 if (m_seriesSignalsBlock)
279 279 return;
280 280
281 281 if (m_count != -1)
282 282 m_count += 1;
283 283
284 284 blockModelSignals();
285 285 if (m_orientation == Qt::Vertical)
286 286 m_model->insertRows(pointPos + m_first, 1);
287 287 else
288 288 m_model->insertColumns(pointPos + m_first, 1);
289 289
290 290 m_model->setData(xModelIndex(pointPos), m_series->points().at(pointPos).x());
291 291 m_model->setData(yModelIndex(pointPos), m_series->points().at(pointPos).y());
292 292 blockModelSignals(false);
293 293 }
294 294
295 295 void QXYModelMapperPrivate::handlePointRemoved(int pointPos)
296 296 {
297 297 if (m_seriesSignalsBlock)
298 298 return;
299 299
300 300 if (m_count != -1)
301 301 m_count -= 1;
302 302
303 303 blockModelSignals();
304 304 if (m_orientation == Qt::Vertical)
305 305 m_model->removeRow(pointPos + m_first);
306 306 else
307 307 m_model->removeColumn(pointPos + m_first);
308 308 blockModelSignals(false);
309 309 }
310 310
311 311 void QXYModelMapperPrivate::handlePointReplaced(int pointPos)
312 312 {
313 313 if (m_seriesSignalsBlock)
314 314 return;
315 315
316 316 blockModelSignals();
317 317 m_model->setData(xModelIndex(pointPos), m_series->points().at(pointPos).x());
318 318 m_model->setData(yModelIndex(pointPos), m_series->points().at(pointPos).y());
319 319 blockModelSignals(false);
320 320 }
321 321
322 322 void QXYModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
323 323 {
324 324 if (m_model == 0 || m_series == 0)
325 325 return;
326 326
327 327 if (m_modelSignalsBlock)
328 328 return;
329 329
330 330 blockSeriesSignals();
331 331 QModelIndex index;
332 332 QPointF oldPoint;
333 333 QPointF newPoint;
334 334 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
335 335 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
336 336 index = topLeft.sibling(row, column);
337 337 if (m_orientation == Qt::Vertical && (index.column() == m_xSection || index.column() == m_ySection)) {
338 338 if (index.row() >= m_first && (m_count == - 1 || index.row() < m_first + m_count)) {
339 339 QModelIndex xIndex = xModelIndex(index.row() - m_first);
340 340 QModelIndex yIndex = yModelIndex(index.row() - m_first);
341 341 if (xIndex.isValid() && yIndex.isValid()) {
342 342 oldPoint = m_series->points().at(index.row() - m_first);
343 343 newPoint.setX(m_model->data(xIndex).toReal());
344 344 newPoint.setY(m_model->data(yIndex).toReal());
345 345 }
346 346 }
347 347 } else if (m_orientation == Qt::Horizontal && (index.row() == m_xSection || index.row() == m_ySection)) {
348 348 if (index.column() >= m_first && (m_count == - 1 || index.column() < m_first + m_count)) {
349 349 QModelIndex xIndex = xModelIndex(index.column() - m_first);
350 350 QModelIndex yIndex = yModelIndex(index.column() - m_first);
351 351 if (xIndex.isValid() && yIndex.isValid()) {
352 352 oldPoint = m_series->points().at(index.column() - m_first);
353 353 newPoint.setX(m_model->data(xIndex).toReal());
354 354 newPoint.setY(m_model->data(yIndex).toReal());
355 355 }
356 356 }
357 357 } else {
358 358 continue;
359 359 }
360 360 m_series->replace(oldPoint, newPoint);
361 361 }
362 362 }
363 363 blockSeriesSignals(false);
364 364 }
365 365
366 366 void QXYModelMapperPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
367 367 {
368 368 Q_UNUSED(parent);
369 369 if (m_modelSignalsBlock)
370 370 return;
371 371
372 372 blockSeriesSignals();
373 373 if (m_orientation == Qt::Vertical)
374 374 insertData(start, end);
375 375 else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
376 376 initializeXYFromModel();
377 377 blockSeriesSignals(false);
378 378 }
379 379
380 380 void QXYModelMapperPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
381 381 {
382 382 Q_UNUSED(parent);
383 383 if (m_modelSignalsBlock)
384 384 return;
385 385
386 386 blockSeriesSignals();
387 387 if (m_orientation == Qt::Vertical)
388 388 removeData(start, end);
389 389 else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
390 390 initializeXYFromModel();
391 391 blockSeriesSignals(false);
392 392 }
393 393
394 394 void QXYModelMapperPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
395 395 {
396 396 Q_UNUSED(parent);
397 397 if (m_modelSignalsBlock)
398 398 return;
399 399
400 400 blockSeriesSignals();
401 401 if (m_orientation == Qt::Horizontal)
402 402 insertData(start, end);
403 403 else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
404 404 initializeXYFromModel();
405 405 blockSeriesSignals(false);
406 406 }
407 407
408 408 void QXYModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
409 409 {
410 410 Q_UNUSED(parent);
411 411 if (m_modelSignalsBlock)
412 412 return;
413 413
414 414 blockSeriesSignals();
415 415 if (m_orientation == Qt::Horizontal)
416 416 removeData(start, end);
417 417 else if (start <= m_xSection || start <= m_ySection) // if the changes affect the map - reinitialize the xy
418 418 initializeXYFromModel();
419 419 blockSeriesSignals(false);
420 420 }
421 421
422 422 void QXYModelMapperPrivate::insertData(int start, int end)
423 423 {
424 424 if (m_model == 0 || m_series == 0)
425 425 return;
426 426
427 427 if (m_count != -1 && start >= m_first + m_count) {
428 428 return;
429 429 } else {
430 430 int addedCount = end - start + 1;
431 431 if (m_count != -1 && addedCount > m_count)
432 432 addedCount = m_count;
433 433 int first = qMax(start, m_first);
434 434 int last = qMin(first + addedCount - 1, m_orientation == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
435 435 for (int i = first; i <= last; i++) {
436 436 QPointF point;
437 437 QModelIndex xIndex = xModelIndex(i - m_first);
438 438 QModelIndex yIndex = yModelIndex(i - m_first);
439 439 if (xIndex.isValid() && yIndex.isValid()) {
440 440 point.setX(m_model->data(xIndex, Qt::DisplayRole).toDouble());
441 441 point.setY(m_model->data(yIndex, Qt::DisplayRole).toDouble());
442 442 m_series->insert(i - m_first, point);
443 443 }
444 444 }
445 445
446 446 // remove excess of slices (abouve m_count)
447 447 if (m_count != -1 && m_series->points().size() > m_count)
448 448 for (int i = m_series->points().size() - 1; i >= m_count; i--) {
449 449 m_series->remove(m_series->points().at(i));
450 450 }
451 451 }
452 452 }
453 453
454 454 void QXYModelMapperPrivate::removeData(int start, int end)
455 455 {
456 456 if (m_model == 0 || m_series == 0)
457 457 return;
458 458
459 459 int removedCount = end - start + 1;
460 460 if (m_count != -1 && start >= m_first + m_count) {
461 461 return;
462 462 } else {
463 463 int toRemove = qMin(m_series->count(), removedCount); // first find how many items can actually be removed
464 464 int first = qMax(start, m_first); // get the index of the first item that will be removed.
465 465 int last = qMin(first + toRemove - 1, m_series->count() + m_first - 1); // get the index of the last item that will be removed.
466 466 for (int i = last; i >= first; i--) {
467 467 m_series->remove(m_series->points().at(i - m_first));
468 468 }
469 469
470 470 if (m_count != -1) {
471 471 int itemsAvailable; // check how many are available to be added
472 472 if (m_orientation == Qt::Vertical)
473 473 itemsAvailable = m_model->rowCount() - m_first - m_series->count();
474 474 else
475 475 itemsAvailable = m_model->columnCount() - m_first - m_series->count();
476 476 int toBeAdded = qMin(itemsAvailable, m_count - m_series->count()); // add not more items than there is space left to be filled.
477 477 int currentSize = m_series->count();
478 478 if (toBeAdded > 0)
479 479 for (int i = m_series->count(); i < currentSize + toBeAdded; i++) {
480 480 QPointF point;
481 481 QModelIndex xIndex = xModelIndex(i);
482 482 QModelIndex yIndex = yModelIndex(i);
483 483 if (xIndex.isValid() && yIndex.isValid()) {
484 484 point.setX(m_model->data(xIndex, Qt::DisplayRole).toDouble());
485 485 point.setY(m_model->data(yIndex, Qt::DisplayRole).toDouble());
486 486 m_series->insert(i, point);
487 487 }
488 488 }
489 489 }
490 490 }
491 491 }
492 492
493 493 void QXYModelMapperPrivate::initializeXYFromModel()
494 494 {
495 495 if (m_model == 0 || m_series == 0)
496 496 return;
497 497
498 498 blockSeriesSignals();
499 499 // clear current content
500 500 m_series->clear();
501 501
502 502 // create the initial slices set
503 503 int pointPos = 0;
504 504 QModelIndex xIndex = xModelIndex(pointPos);
505 505 QModelIndex yIndex = yModelIndex(pointPos);
506 506 while (xIndex.isValid() && yIndex.isValid()) {
507 507 QPointF point;
508 508 point.setX(m_model->data(xIndex, Qt::DisplayRole).toDouble());
509 509 point.setY(m_model->data(yIndex, Qt::DisplayRole).toDouble());
510 510 m_series->append(point);
511 511 pointPos++;
512 512 xIndex = xModelIndex(pointPos);
513 513 yIndex = yModelIndex(pointPos);
514 514 }
515 515 blockSeriesSignals(false);
516 516 }
517 517
518 518 #include "moc_qxymodelmapper.cpp"
519 519 #include "moc_qxymodelmapper_p.cpp"
520 520
521 521 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now