1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3#include <QtCore/QAbstractItemModel>
4#include <QtGraphs/QBarModelMapper>
5#include <QtGraphs/QBarSeries>
6#include <private/qabstractitemmodel_p.h>
7#include <private/qbarmodelmapper_p.h>
8
9QT_BEGIN_NAMESPACE
10
11/*!
12 \class QBarModelMapper
13 \inmodule QtGraphs
14 \ingroup graphs_2D
15 \brief The QBarModelMapper class is a model mapper for bar series.
16
17 Model mappers enable using a data model derived from the QAbstractItemModel class
18 as a data source for a graph. A model mapper is used to create a connection
19 between a data model and QBarSeries.
20
21 Both model and bar series properties can be used to manipulate the data. The model mapper
22 keeps the bar series and the data model in sync.
23
24 The model mapper ensures that all the bar sets in the bar series have equal sizes.
25 Therefore, adding or removing a value from a bar set causes the same change to be
26 made in all the bar sets in the bar series.
27
28*/
29/*!
30 \qmltype BarModelMapper
31 \nativetype QBarModelMapper
32 \inqmlmodule QtGraphs
33 \ingroup graphs_qml_2D
34
35 \brief Model mapper for bar series.
36
37 The BarModelMapper type enables using a data model derived from the QAbstractItemModel
38 class as a data source for a graph. A model mapper is used to create a connection
39 between a data model and QBarSeries. You need to implement
40 the data model and expose it to QML.
41
42 Both model and bar series properties can be used to manipulate the data. The model mapper
43 keeps the bar series and the data model in sync.
44
45 The model mapper ensures that all the bar sets in the bar series have equal sizes.
46 Therefore, adding or removing a value from a bar set causes the same change to be
47 made in all the bar sets in the bar series.
48
49 The following QML code snippet creates a bar series with three bar sets (assuming the model
50 has at least four columns). Each bar set contains data starting from row 1. The name
51 of a bar set is defined by the column header.
52 \code
53 BarSeries {
54 BarModelMapper {
55 model: myCustomModel // QAbstractItemModel derived implementation
56 firstBarSetColumn: 1
57 lastBarSetColumn: 3
58 firstRow: 1
59 orientation: Qt.Vertical
60 }
61 }
62 \endcode
63
64*/
65
66/*!
67 \property QBarModelMapper::series
68 \brief The bar series that is used by the mapper.
69
70 All the data in the series is discarded when it is set to the mapper.
71 When a new series is specified, the old series is disconnected, but it preserves its data.
72*/
73/*!
74 \qmlproperty BarSeries BarModelMapper::series
75 The bar series that is used by the mapper. All the data in the series is discarded when it is
76 set to the mapper. When the new series is specified, the old series is disconnected, but it
77 preserves its data.
78*/
79
80/*!
81 \property QBarModelMapper::model
82 \brief The data model that is used by the mapper.
83*/
84/*!
85 \qmlproperty model BarModelMapper::model
86 The data model that is used by the mapper. You need to implement the model and expose it to QML.
87
88 \note The model has to support adding and removing rows or columns and modifying
89 the data in the cells.
90*/
91
92/*!
93 \property QBarModelMapper::firstBarSetSection
94 \brief The section of the model that is used as the data source for the first bar set.
95
96 The default value is -1 (invalid mapping).
97
98 \sa QBarModelMapper::orientation
99*/
100/*!
101 \qmlproperty qsizetype BarModelMapper::firstBarSetSection
102 The section of the model that is used as the data source for the first bar set. The default value
103 is -1 (invalid mapping).
104
105 \sa orientation
106*/
107
108/*!
109 \property QBarModelMapper::lastBarSetSection
110 \brief The section of the model that is used as the data source for the last bar set.
111
112 The default value is -1 (invalid mapping).
113
114 \sa QBarModelMapper::orientation
115*/
116/*!
117 \qmlproperty qsizetype BarModelMapper::lastBarSetSection
118 The section of the model that is used as the data source for the last bar set. The default
119 value is -1 (invalid mapping).
120
121 \sa orientation
122*/
123
124/*!
125 \property QBarModelMapper::first
126 \brief The row or column of the model that contains the first values of the bar sets in the bar series.
127
128 The minimum and default value is 0.
129
130 \sa QBarModelMapper::orientation
131*/
132/*!
133 \qmlproperty qsizetype BarModelMapper::first
134 The row or column of the model that contains the first values of the bar sets in the bar series.
135 The default value is 0.
136
137 \sa orientation
138*/
139
140/*!
141 \property QBarModelMapper::count
142 \brief The number of rows or columns of the model that are mapped as the data for the bar series.
143
144 The default value is \c{-1} which is also the minimum. The count is
145 limited by the number of model's rows/columns.
146
147 \sa QBarModelMapper::orientation
148*/
149/*!
150 \qmlproperty qsizetype BarModelMapper::count
151 The number of rows or columns of the model that are mapped as the data for the bar
152 series. The default value is \c{-1} which is also the minimum. The count is
153 limited by the number of model's rows/columns.
154
155 \sa orientation
156*/
157
158/*!
159 \property QBarModelMapper::orientation
160 \brief Tells the modelmapper how to map data from a model. If
161 \c{Qt::Vertical} is used, each of the model's columns defines a bar set, and the
162 model's rows define the categories. When the orientation is set to
163 \c{Qt::Horizontal}, each of the model's rows defines a bar set, and the model's
164 columns define categories.
165
166 The default value is \c{Qt::Vertical}
167*/
168/*!
169 \qmlproperty orientation BarModelMapper::orientation
170 Tells the modelmapper how to map data from a model. If
171 \c{Qt.Vertical} is used, each of the model's columns defines a bar set, and the
172 model's rows define the categories. When the orientation is set to
173 \c{Qt.Horizontal}, each of the model's rows defines a bar set, and the model's
174 columns define categories.
175*/
176
177/*!
178 \qmlsignal BarModelMapper::seriesChanged()
179
180 This signal is emitted when the bar series that the mapper is connected to changes.
181*/
182
183/*!
184 \qmlsignal BarModelMapper::modelChanged()
185
186 This signal is emitted when the model that the mapper is connected to changes.
187*/
188
189/*!
190 \qmlsignal BarModelMapper::firstBarSetSectionChanged()
191 This signal is emitted when the first bar set section changes.
192*/
193
194/*!
195 \qmlsignal BarModelMapper::lastBarSetSectionChanged()
196 This signal is emitted when the last bar set section changes.
197*/
198
199/*!
200 \qmlsignal BarModelMapper::firstChanged()
201 This signal is emitted when the first row or column changes.
202*/
203
204/*!
205 \qmlsignal BarModelMapper::countChanged()
206 This signal is emitted when the number of rows or columns changes.
207*/
208
209/*!
210 \qmlsignal BarModelMapper::orientationChanged()
211 This signal is emitted when the orientation changes.
212*/
213
214QBarModelMapper::QBarModelMapper(QObject *parent)
215 : QObject(*(new QBarModelMapperPrivate), parent)
216{}
217
218QBarModelMapper::QBarModelMapper(QBarModelMapperPrivate &dd, QObject *parent)
219 : QObject(dd, parent)
220{}
221
222QBarModelMapper::~QBarModelMapper() {}
223
224QAbstractItemModel *QBarModelMapper::model() const
225{
226 Q_D(const QBarModelMapper);
227 return d->m_model;
228}
229
230void QBarModelMapper::setModel(QAbstractItemModel *model)
231{
232 Q_D(QBarModelMapper);
233 if (d->m_model) {
234 QObjectPrivate::disconnect(sender: d->m_model,
235 signal: &QAbstractItemModel::modelReset,
236 receiverPrivate: d,
237 slot: &QBarModelMapperPrivate::initializeBarsFromModel);
238 QObjectPrivate::disconnect(sender: d->m_model,
239 signal: &QAbstractItemModel::dataChanged,
240 receiverPrivate: d,
241 slot: &QBarModelMapperPrivate::modelUpdated);
242 QObjectPrivate::disconnect(sender: d->m_model,
243 signal: &QAbstractItemModel::headerDataChanged,
244 receiverPrivate: d,
245 slot: &QBarModelMapperPrivate::modelHeaderDataUpdated);
246 QObjectPrivate::disconnect(sender: d->m_model,
247 signal: &QAbstractItemModel::rowsInserted,
248 receiverPrivate: d,
249 slot: &QBarModelMapperPrivate::modelRowsAdded);
250 QObjectPrivate::disconnect(sender: d->m_model,
251 signal: &QAbstractItemModel::rowsRemoved,
252 receiverPrivate: d,
253 slot: &QBarModelMapperPrivate::modelRowsRemoved);
254 QObjectPrivate::disconnect(sender: d->m_model,
255 signal: &QAbstractItemModel::columnsInserted,
256 receiverPrivate: d,
257 slot: &QBarModelMapperPrivate::modelColumnsAdded);
258 QObjectPrivate::disconnect(sender: d->m_model,
259 signal: &QAbstractItemModel::columnsRemoved,
260 receiverPrivate: d,
261 slot: &QBarModelMapperPrivate::modelColumnsRemoved);
262 QObjectPrivate::disconnect(sender: d->m_model,
263 signal: &QAbstractItemModel::destroyed,
264 receiverPrivate: d,
265 slot: &QBarModelMapperPrivate::handleModelDestroyed);
266 }
267
268 d->m_model = model;
269
270 d->initializeBarsFromModel();
271
272 if (d->m_model) {
273 QObjectPrivate::connect(sender: d->m_model,
274 signal: &QAbstractItemModel::modelReset,
275 receiverPrivate: d,
276 slot: &QBarModelMapperPrivate::initializeBarsFromModel);
277 QObjectPrivate::connect(sender: d->m_model,
278 signal: &QAbstractItemModel::dataChanged,
279 receiverPrivate: d,
280 slot: &QBarModelMapperPrivate::modelUpdated);
281 QObjectPrivate::connect(sender: d->m_model,
282 signal: &QAbstractItemModel::headerDataChanged,
283 receiverPrivate: d,
284 slot: &QBarModelMapperPrivate::modelHeaderDataUpdated);
285 QObjectPrivate::connect(sender: d->m_model,
286 signal: &QAbstractItemModel::rowsInserted,
287 receiverPrivate: d,
288 slot: &QBarModelMapperPrivate::modelRowsAdded);
289 QObjectPrivate::connect(sender: d->m_model,
290 signal: &QAbstractItemModel::rowsRemoved,
291 receiverPrivate: d,
292 slot: &QBarModelMapperPrivate::modelRowsRemoved);
293 QObjectPrivate::connect(sender: d->m_model,
294 signal: &QAbstractItemModel::columnsInserted,
295 receiverPrivate: d,
296 slot: &QBarModelMapperPrivate::modelColumnsAdded);
297 QObjectPrivate::connect(sender: d->m_model,
298 signal: &QAbstractItemModel::columnsRemoved,
299 receiverPrivate: d,
300 slot: &QBarModelMapperPrivate::modelColumnsRemoved);
301 QObjectPrivate::connect(sender: d->m_model,
302 signal: &QAbstractItemModel::destroyed,
303 receiverPrivate: d,
304 slot: &QBarModelMapperPrivate::handleModelDestroyed);
305 }
306 Q_EMIT modelChanged();
307}
308
309QBarSeries *QBarModelMapper::series() const
310{
311 Q_D(const QBarModelMapper);
312 return d->m_series;
313}
314
315void QBarModelMapper::setSeries(QBarSeries *series)
316{
317 Q_D(QBarModelMapper);
318 if (d->m_series) {
319 QObjectPrivate::disconnect(sender: d->m_series,
320 signal: &QBarSeries::barsetsAdded,
321 receiverPrivate: d,
322 slot: &QBarModelMapperPrivate::barSetsAdded);
323 QObjectPrivate::disconnect(sender: d->m_series,
324 signal: &QBarSeries::barsetsRemoved,
325 receiverPrivate: d,
326 slot: &QBarModelMapperPrivate::barSetsRemoved);
327 QObjectPrivate::disconnect(sender: d->m_series,
328 signal: &QBarSeries::destroyed,
329 receiverPrivate: d,
330 slot: &QBarModelMapperPrivate::handleSeriesDestroyed);
331 }
332
333 d->m_series = series;
334
335 d->initializeBarsFromModel();
336 if (d->m_series) {
337 QObjectPrivate::connect(sender: d->m_series,
338 signal: &QBarSeries::barsetsAdded,
339 receiverPrivate: d,
340 slot: &QBarModelMapperPrivate::barSetsAdded);
341 QObjectPrivate::connect(sender: d->m_series,
342 signal: &QBarSeries::barsetsRemoved,
343 receiverPrivate: d,
344 slot: &QBarModelMapperPrivate::barSetsRemoved);
345 QObjectPrivate::connect(sender: d->m_series,
346 signal: &QBarSeries::destroyed,
347 receiverPrivate: d,
348 slot: &QBarModelMapperPrivate::handleSeriesDestroyed);
349 }
350 Q_EMIT seriesChanged();
351}
352
353qsizetype QBarModelMapper::first() const
354{
355 Q_D(const QBarModelMapper);
356 return d->m_first;
357}
358
359void QBarModelMapper::setFirst(qsizetype newFirst)
360{
361 Q_D(QBarModelMapper);
362 d->m_first = qMax(a: newFirst, b: 0);
363 d->initializeBarsFromModel();
364 Q_EMIT firstChanged();
365}
366
367Qt::Orientation QBarModelMapper::orientation() const
368{
369 Q_D(const QBarModelMapper);
370 return d->m_orientation;
371}
372
373void QBarModelMapper::setOrientation(Qt::Orientation orientation)
374{
375 Q_D(QBarModelMapper);
376 d->m_orientation = orientation;
377 d->initializeBarsFromModel();
378 Q_EMIT orientationChanged();
379}
380
381qsizetype QBarModelMapper::count() const
382{
383 Q_D(const QBarModelMapper);
384 return d->m_count;
385}
386
387void QBarModelMapper::setCount(qsizetype newCount)
388{
389 Q_D(QBarModelMapper);
390 d->m_count = qMax(a: newCount, b: -1);
391 d->initializeBarsFromModel();
392 Q_EMIT countChanged();
393}
394
395qsizetype QBarModelMapper::lastBarSetSection() const
396{
397 Q_D(const QBarModelMapper);
398 return d->m_lastBarSetSection;
399}
400
401void QBarModelMapper::setLastBarSetSection(qsizetype newLastBarSetSection)
402{
403 Q_D(QBarModelMapper);
404 d->m_lastBarSetSection = qMax(a: -1, b: newLastBarSetSection);
405 d->initializeBarsFromModel();
406 Q_EMIT lastBarSetSectionChanged();
407}
408
409qsizetype QBarModelMapper::firstBarSetSection() const
410{
411 Q_D(const QBarModelMapper);
412 return d->m_firstBarSetSection;
413}
414
415void QBarModelMapper::setFirstBarSetSection(qsizetype newFirstBarSetSection)
416{
417 Q_D(QBarModelMapper);
418 d->m_firstBarSetSection = qMax(a: -1, b: newFirstBarSetSection);
419 d->initializeBarsFromModel();
420 Q_EMIT firstBarSetSectionChanged();
421}
422
423void QBarModelMapper::onValuesAdded(qsizetype index, qsizetype count)
424{
425 Q_D(QBarModelMapper);
426
427 if (d->m_seriesSignalsBlock)
428 return;
429 d->handleValuesAdded(set: qobject_cast<QBarSet *>(object: sender()), index, count);
430}
431
432void QBarModelMapper::onBarLabelChanged()
433{
434 Q_D(QBarModelMapper);
435
436 if (d->m_seriesSignalsBlock)
437 return;
438 d->handleBarLabelChanged(set: qobject_cast<QBarSet *>(object: sender()));
439}
440
441void QBarModelMapper::onBarValueChanged(qsizetype index)
442{
443 Q_D(QBarModelMapper);
444
445 if (d->m_seriesSignalsBlock)
446 return;
447 d->handleBarValueChanged(set: qobject_cast<QBarSet *>(object: sender()), index);
448}
449
450/////////////////////////////////////////////////////////////////////////////////////
451QBarModelMapperPrivate::QBarModelMapperPrivate() {}
452
453QBarModelMapperPrivate::~QBarModelMapperPrivate() {}
454
455QModelIndex QBarModelMapperPrivate::barModelIndex(qsizetype barSection, qsizetype posInBar)
456{
457 if (m_count != -1 && posInBar >= m_count)
458 return QModelIndex(); // invalid
459
460 if (barSection < m_firstBarSetSection || barSection > m_lastBarSetSection)
461 return QModelIndex(); // invalid
462
463 if (m_orientation == Qt::Vertical)
464 return m_model->index(row: int(posInBar) + m_first, column: int(barSection));
465 else
466 return m_model->index(row: int(barSection), column: int(posInBar) + m_first);
467}
468
469void QBarModelMapperPrivate::blockSeriesSignals(const bool block)
470{
471 m_seriesSignalsBlock = block;
472}
473
474void QBarModelMapperPrivate::blockModelSignals(const bool block)
475{
476 m_modelSignalsBlock = block;
477}
478
479QBarSet *QBarModelMapperPrivate::barSet(QModelIndex index)
480{
481 if (!index.isValid())
482 return 0;
483
484 if (m_orientation == Qt::Vertical && index.column() >= m_firstBarSetSection
485 && index.column() <= m_lastBarSetSection) {
486 if (index.row() >= m_first && (m_count == -1 || index.row() < m_first + m_count))
487 return m_series->barSets().at(i: index.column() - m_firstBarSetSection);
488
489 } else if (m_orientation == Qt::Horizontal && index.row() >= m_firstBarSetSection
490 && index.row() <= m_lastBarSetSection) {
491 if (index.column() >= m_first && (m_count == -1 || index.column() < m_first + m_count))
492 return m_series->barSets().at(i: index.row() - m_firstBarSetSection);
493 }
494 return 0; // This part of model has not been mapped to any slice
495}
496
497void QBarModelMapperPrivate::insertData(qsizetype start, qsizetype end)
498{
499 Q_UNUSED(start);
500 Q_UNUSED(end);
501 // Currently bar graph needs to be fully recalculated when change is made.
502 // Re-initialize
503 initializeBarsFromModel();
504}
505
506void QBarModelMapperPrivate::removeData(qsizetype start, qsizetype end)
507{
508 Q_UNUSED(start);
509 Q_UNUSED(end);
510 // Currently bar graph needs to be fully recalculated when change is made.
511 // Re-initialize
512 initializeBarsFromModel();
513}
514
515void QBarModelMapperPrivate::initializeBarsFromModel()
516{
517 if (m_model == nullptr || m_series == nullptr)
518 return;
519 Q_Q(QBarModelMapper);
520 blockSeriesSignals();
521 m_series->clear();
522 m_barSets.clear();
523
524 // create the initial bar sets
525 for (int i = m_firstBarSetSection; i <= m_lastBarSetSection; i++) {
526 int posInBar = 0;
527 QModelIndex barIndex = barModelIndex(barSection: i, posInBar);
528 // check if there is such model index
529 if (barIndex.isValid()) {
530 QBarSet *barSet = new QBarSet(
531 m_model->headerData(section: i, orientation: m_orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical)
532 .toString());
533 while (barIndex.isValid()) {
534 barSet->append(value: m_model->data(index: barIndex, role: Qt::DisplayRole).toDouble());
535 posInBar++;
536 barIndex = barModelIndex(barSection: i, posInBar);
537 }
538 QObjectPrivate::connect(sender: barSet,
539 signal: &QBarSet::valuesRemoved,
540 receiverPrivate: this,
541 slot: &QBarModelMapperPrivate::valuesRemoved);
542
543 QObject::connect(sender: barSet, signal: &QBarSet::valuesAdded, context: q, slot: &QBarModelMapper::onValuesAdded);
544 QObject::connect(sender: barSet, signal: &QBarSet::valueChanged, context: q, slot: &QBarModelMapper::onBarValueChanged);
545 QObject::connect(sender: barSet, signal: &QBarSet::labelChanged, context: q, slot: &QBarModelMapper::onBarLabelChanged);
546 m_series->append(set: barSet);
547 m_barSets.append(t: barSet);
548 } else {
549 break;
550 }
551 }
552 blockSeriesSignals(block: false);
553}
554
555void QBarModelMapperPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
556{
557 if (m_model == nullptr || m_series == nullptr)
558 return;
559
560 if (m_modelSignalsBlock)
561 return;
562
563 blockSeriesSignals();
564 QModelIndex index;
565 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
566 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
567 index = topLeft.sibling(arow: row, acolumn: column);
568 QBarSet *bar = barSet(index);
569 if (bar) {
570 if (m_orientation == Qt::Vertical)
571 bar->replace(index: row - m_first, value: m_model->data(index).toReal());
572 else
573 bar->replace(index: column - m_first, value: m_model->data(index).toReal());
574 }
575 }
576 }
577 blockSeriesSignals(block: false);
578}
579
580void QBarModelMapperPrivate::modelHeaderDataUpdated(Qt::Orientation orientation, qsizetype first, qsizetype last)
581{
582 if (m_model == nullptr || m_series == nullptr)
583 return;
584
585 if (m_modelSignalsBlock)
586 return;
587
588 blockSeriesSignals();
589 if (orientation != m_orientation) {
590 for (int section = first; section <= last; section++) {
591 if (section >= m_firstBarSetSection && section <= m_lastBarSetSection) {
592 QBarSet *bar = m_series->barSets().at(i: section - m_firstBarSetSection);
593 if (bar)
594 bar->setLabel(m_model->headerData(section, orientation).toString());
595 }
596 }
597 }
598 blockSeriesSignals(block: false);
599}
600
601void QBarModelMapperPrivate::modelRowsAdded(QModelIndex parent, qsizetype start, qsizetype end)
602{
603 Q_UNUSED(parent);
604 if (m_modelSignalsBlock)
605 return;
606
607 blockSeriesSignals();
608 if (m_orientation == Qt::Vertical) {
609 insertData(start, end);
610 } else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) {
611 // if the changes affect the map - reinitialize
612 initializeBarsFromModel();
613 }
614 blockSeriesSignals(block: false);
615}
616
617void QBarModelMapperPrivate::modelRowsRemoved(QModelIndex parent, qsizetype start, qsizetype end)
618{
619 Q_UNUSED(parent);
620 if (m_modelSignalsBlock)
621 return;
622
623 blockSeriesSignals();
624 if (m_orientation == Qt::Vertical) {
625 removeData(start, end);
626 } else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) {
627 // if the changes affect the map - reinitialize
628 initializeBarsFromModel();
629 }
630 blockSeriesSignals(block: false);
631}
632
633void QBarModelMapperPrivate::modelColumnsAdded(QModelIndex parent, qsizetype start, qsizetype end)
634{
635 Q_UNUSED(parent);
636 if (m_modelSignalsBlock)
637 return;
638
639 blockSeriesSignals();
640 if (m_orientation == Qt::Horizontal) {
641 insertData(start, end);
642 } else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) {
643 // if the changes affect the map - reinitialize
644 initializeBarsFromModel();
645 }
646 blockSeriesSignals(block: false);
647}
648
649void QBarModelMapperPrivate::modelColumnsRemoved(QModelIndex parent, qsizetype start, qsizetype end)
650{
651 Q_UNUSED(parent);
652 if (m_modelSignalsBlock)
653 return;
654
655 blockSeriesSignals();
656 if (m_orientation == Qt::Horizontal) {
657 removeData(start, end);
658 } else if (start <= m_firstBarSetSection || start <= m_lastBarSetSection) {
659 // if the changes affect the map - reinitialize
660 initializeBarsFromModel();
661 }
662 blockSeriesSignals(block: false);
663}
664
665void QBarModelMapperPrivate::handleModelDestroyed()
666{
667 m_model = nullptr;
668}
669
670void QBarModelMapperPrivate::barSetsAdded(const QList<QBarSet *> &sets)
671{
672 if (m_seriesSignalsBlock)
673 return;
674
675 if (sets.size() == 0)
676 return;
677
678 int firstIndex = int(m_series->barSets().indexOf(t: sets.at(i: 0)));
679 if (firstIndex == -1)
680 return;
681
682 qsizetype maxCount = 0;
683 for (int i = 0; i < sets.size(); i++) {
684 if (sets.at(i)->count() > m_count)
685 maxCount = sets.at(i)->count();
686 }
687
688 if (m_count != -1 && m_count < maxCount)
689 m_count = maxCount;
690
691 m_lastBarSetSection += sets.size();
692
693 blockModelSignals();
694 int modelCapacity = m_orientation == Qt::Vertical ? m_model->rowCount() - m_first
695 : m_model->columnCount() - m_first;
696 if (maxCount > modelCapacity) {
697 if (m_orientation == Qt::Vertical)
698 m_model->insertRows(row: m_model->rowCount(), count: int(maxCount) - modelCapacity);
699 else
700 m_model->insertColumns(column: m_model->columnCount(), count: int(maxCount) - modelCapacity);
701 }
702
703 if (m_orientation == Qt::Vertical)
704 m_model->insertColumns(column: firstIndex + m_firstBarSetSection, count: int(sets.size()));
705 else
706 m_model->insertRows(row: firstIndex + m_firstBarSetSection, count: int(sets.size()));
707
708 for (int i = firstIndex + m_firstBarSetSection;
709 i < firstIndex + m_firstBarSetSection + sets.size();
710 i++) {
711 m_model->setHeaderData(section: i,
712 orientation: m_orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical,
713 value: sets.at(i: i - firstIndex - m_firstBarSetSection)->label());
714 for (int j = 0; j < sets.at(i: i - firstIndex - m_firstBarSetSection)->count(); j++) {
715 m_model->setData(index: barModelIndex(barSection: i, posInBar: j),
716 value: sets.at(i: i - firstIndex - m_firstBarSetSection)->at(index: j));
717 }
718 }
719 blockModelSignals(block: false);
720 initializeBarsFromModel();
721}
722
723void QBarModelMapperPrivate::barSetsRemoved(const QList<QBarSet *> &sets)
724{
725 if (m_seriesSignalsBlock)
726 return;
727
728 if (sets.size() == 0)
729 return;
730
731 int firstIndex = int(m_barSets.indexOf(t: sets.at(i: 0)));
732 if (firstIndex == -1)
733 return;
734
735 m_lastBarSetSection -= sets.size();
736
737 for (qsizetype i = firstIndex + sets.size() - 1; i >= firstIndex; i--)
738 m_barSets.removeAt(i);
739
740 blockModelSignals();
741 if (m_orientation == Qt::Vertical)
742 m_model->removeColumns(column: firstIndex + m_firstBarSetSection, count: int(sets.size()));
743 else
744 m_model->removeRows(row: firstIndex + m_firstBarSetSection, count: int(sets.size()));
745 blockModelSignals(block: false);
746 initializeBarsFromModel();
747}
748
749void QBarModelMapperPrivate::handleValuesAdded(QBarSet *set, qsizetype index, qsizetype count)
750{
751 if (m_seriesSignalsBlock)
752 return;
753
754 if (m_count != -1)
755 m_count += count;
756 Q_ASSERT(set);
757 qsizetype barSetIndex = m_barSets.indexOf(t: set);
758
759 blockModelSignals();
760 if (m_orientation == Qt::Vertical)
761 m_model->insertRows(row: int(index) + m_first, count: int(count));
762 else
763 m_model->insertColumns(column: int(index) + m_first, count: int(count));
764
765 for (qsizetype j = index; j < index + count; j++) {
766 m_model->setData(index: barModelIndex(barSection: barSetIndex + m_firstBarSetSection, posInBar: int(j)),
767 value: m_barSets.at(i: barSetIndex)->at(index: j));
768 }
769
770 blockModelSignals(block: false);
771 initializeBarsFromModel();
772}
773
774void QBarModelMapperPrivate::valuesRemoved(qsizetype index, qsizetype count)
775{
776 if (m_seriesSignalsBlock)
777 return;
778
779 if (m_count != -1)
780 m_count -= count;
781
782 blockModelSignals();
783 if (m_orientation == Qt::Vertical)
784 m_model->removeRows(row: int(index) + m_first, count: int(count));
785 else
786 m_model->removeColumns(column: int(index) + m_first, count: int(count));
787
788 blockModelSignals(block: false);
789 initializeBarsFromModel();
790}
791
792void QBarModelMapperPrivate::handleBarLabelChanged(QBarSet *set)
793{
794 if (m_seriesSignalsBlock)
795 return;
796
797 Q_ASSERT(set);
798 int barSetIndex = int(m_barSets.indexOf(t: set));
799
800 blockModelSignals();
801 m_model->setHeaderData(section: barSetIndex + m_firstBarSetSection,
802 orientation: m_orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical,
803 value: m_barSets.at(i: barSetIndex)->label());
804 blockModelSignals(block: false);
805 initializeBarsFromModel();
806}
807
808void QBarModelMapperPrivate::handleBarValueChanged(QBarSet *set, qsizetype index)
809{
810 if (m_seriesSignalsBlock)
811 return;
812
813 Q_ASSERT(set);
814 int barSetIndex = int(m_barSets.indexOf(t: set));
815
816 blockModelSignals();
817 m_model->setData(index: barModelIndex(barSection: barSetIndex + m_firstBarSetSection, posInBar: index),
818 value: m_barSets.at(i: barSetIndex)->at(index));
819 blockModelSignals(block: false);
820 initializeBarsFromModel();
821}
822
823void QBarModelMapperPrivate::handleSeriesDestroyed()
824{
825 m_series = nullptr;
826}
827QT_END_NAMESPACE
828

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtgraphs/src/graphs2d/barchart/qbarmodelmapper.cpp