1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qbardataproxy_p.h"
5#include "qbar3dseries_p.h"
6
7QT_BEGIN_NAMESPACE
8
9/*!
10 * \class QBarDataProxy
11 * \inmodule QtGraphs
12 * \brief The QBarDataProxy class is the data proxy for a 3D bars graph.
13 *
14 * A bar data proxy handles adding, inserting, changing, and removing rows of
15 * data.
16 *
17 * The data array is a list of vectors (rows) of QBarDataItem instances.
18 * Each row can contain a different number of items or even be null.
19 *
20 * QBarDataProxy takes ownership of all QtGraphs::QBarDataRow objects
21 * passed to it, whether directly or in a QtGraphs::QBarDataArray container.
22 * If bar data row pointers are used to directly modify data after adding the
23 * array to the proxy, the appropriate signal must be emitted to update the
24 * graph.
25 *
26 * QBarDataProxy optionally keeps track of row and column labels, which QCategory3DAxis can utilize
27 * to show axis labels. The row and column labels are stored in a separate array from the data and
28 * row manipulation methods provide alternate versions that do not affect the row labels.
29 * This enables the option of having row labels that relate to the position of the data in the
30 * array rather than the data itself.
31 *
32 * \sa {Qt Graphs Data Handling}
33 */
34
35/*!
36 * \typealias QBarDataRow
37 * \relates QBarDataProxy
38 *
39 * A list of \l {QBarDataItem} objects.
40 */
41
42/*!
43 * \typealias QBarDataArray
44 * \relates QBarDataProxy
45 *
46 * A list of pointers to \l {QBarDataRow} objects.
47 */
48
49/*!
50 * \qmltype BarDataProxy
51 * \inqmlmodule QtGraphs
52 * \ingroup graphs_qml
53 * \instantiates QBarDataProxy
54 * \inherits AbstractDataProxy
55 * \brief The data proxy for a 3D bars graph.
56 *
57 * This type handles adding, inserting, changing, and removing rows of data with Qt Quick 2.
58 *
59 * This type is uncreatable, but contains properties that are exposed via subtypes.
60 *
61 * For a more complete description, see QBarDataProxy.
62 *
63 * \sa ItemModelBarDataProxy, {Qt Graphs Data Handling}
64 */
65
66/*!
67 * \qmlproperty int BarDataProxy::rowCount
68 * The number of rows in the array.
69 */
70
71/*!
72 * \qmlproperty list BarDataProxy::rowLabels
73 *
74 * The optional row labels for the array. Indexes in this array match the row
75 * indexes in the data array.
76 * If the list is shorter than the number of rows, all rows will not get labels.
77 */
78
79/*!
80 * \qmlproperty list BarDataProxy::columnLabels
81 *
82 * The optional column labels for the array. Indexes in this array match column indexes in rows.
83 * If the list is shorter than the longest row, all columns will not get labels.
84 */
85
86/*!
87 * \qmlproperty Bar3DSeries BarDataProxy::series
88 *
89 * The series this proxy is attached to.
90 */
91
92/*!
93 * Constructs a bar data proxy with the given \a parent.
94 */
95QBarDataProxy::QBarDataProxy(QObject *parent) :
96 QAbstractDataProxy(new QBarDataProxyPrivate(this), parent)
97{
98}
99
100/*!
101 * \internal
102 */
103QBarDataProxy::QBarDataProxy(QBarDataProxyPrivate *d, QObject *parent) :
104 QAbstractDataProxy(d, parent)
105{
106}
107
108/*!
109 * Deletes the bar data proxy.
110 */
111QBarDataProxy::~QBarDataProxy()
112{
113}
114
115/*!
116 * \property QBarDataProxy::series
117 *
118 * \brief The series this proxy is attached to.
119 */
120QBar3DSeries *QBarDataProxy::series() const
121{
122 const Q_D(QBarDataProxy);
123 return static_cast<QBar3DSeries *>(d->series());
124}
125
126/*!
127 * Clears the existing array and row and column labels.
128 */
129void QBarDataProxy::resetArray()
130{
131 resetArray(newArray: 0, rowLabels: QStringList(), columnLabels: QStringList());
132 emit rowCountChanged(count: rowCount());
133 emit colCountChanged(count: colCount());
134}
135
136/*!
137 * Takes ownership of the array \a newArray. Clears the existing array if the
138 * new array differs from it. If the arrays are the same, this function
139 * just triggers the arrayReset() signal.
140 *
141 * Passing a null array deletes the old array and creates a new empty array.
142 * Row and column labels are not affected.
143 */
144void QBarDataProxy::resetArray(QBarDataArray *newArray)
145{
146 Q_D(QBarDataProxy);
147 d->resetArray(newArray, rowLabels: 0, columnLabels: 0);
148 emit arrayReset();
149 if (rowCount() && colCount()) {
150 emit rowCountChanged(count: rowCount());
151 emit colCountChanged(count: colCount());
152 }
153}
154
155/*!
156 * Takes ownership of the array \a newArray. Clears the existing array if the
157 * new array differs from it. If the arrays are the same, this function
158 * just triggers the arrayReset() signal.
159 *
160 * Passing a null array deletes the old array and creates a new empty array.
161 *
162 * The \a rowLabels and \a columnLabels lists specify the new labels for rows and columns.
163 */
164void QBarDataProxy::resetArray(QBarDataArray *newArray, const QStringList &rowLabels,
165 const QStringList &columnLabels)
166{
167 Q_D(QBarDataProxy);
168 d->resetArray(newArray, rowLabels: &rowLabels, columnLabels: &columnLabels);
169 emit arrayReset();
170 emit rowCountChanged(count: rowCount());
171 emit colCountChanged(count: colCount());
172}
173
174/*!
175 * Changes an existing row by replacing the row at the position \a rowIndex
176 * with the new row specified by \a row. The new row can be
177 * the same as the existing row already stored at \a rowIndex.
178 * Existing row labels are not affected.
179 */
180void QBarDataProxy::setRow(int rowIndex, QBarDataRow *row)
181{
182 Q_D(QBarDataProxy);
183 d->setRow(rowIndex, row, label: 0);
184 emit rowsChanged(startIndex: rowIndex, count: 1);
185}
186
187/*!
188 * Changes an existing row by replacing the row at the position \a rowIndex
189 * with the new row specified by \a row. The new row can be
190 * the same as the existing row already stored at \a rowIndex.
191 * Changes the row label to \a label.
192 */
193void QBarDataProxy::setRow(int rowIndex, QBarDataRow *row, const QString &label)
194{
195 Q_D(QBarDataProxy);
196 d->setRow(rowIndex, row, label: &label);
197 emit rowsChanged(startIndex: rowIndex, count: 1);
198}
199
200/*!
201 * Changes existing rows by replacing the rows starting at the position
202 * \a rowIndex with the new rows specifies by \a rows.
203 * Existing row labels are not affected. The rows in the \a rows array can be
204 * the same as the existing rows already stored at \a rowIndex.
205 */
206void QBarDataProxy::setRows(int rowIndex, const QBarDataArray &rows)
207{
208 Q_D(QBarDataProxy);
209 d->setRows(rowIndex, rows, labels: 0);
210 emit rowsChanged(startIndex: rowIndex, count: rows.size());
211}
212
213/*!
214 * Changes existing rows by replacing the rows starting at the position
215 * \a rowIndex with the new rows specifies by \a rows.
216 * The row labels are changed to \a labels. The rows in the \a rows array can be
217 * the same as the existing rows already stored at \a rowIndex.
218 */
219void QBarDataProxy::setRows(int rowIndex, const QBarDataArray &rows, const QStringList &labels)
220{
221 Q_D(QBarDataProxy);
222 d->setRows(rowIndex, rows, labels: &labels);
223 emit rowsChanged(startIndex: rowIndex, count: rows.size());
224}
225
226/*!
227 * Changes a single item at the position specified by \a rowIndex and
228 * \a columnIndex to the item \a item.
229 */
230void QBarDataProxy::setItem(int rowIndex, int columnIndex, const QBarDataItem &item)
231{
232 Q_D(QBarDataProxy);
233 d->setItem(rowIndex, columnIndex, item);
234 emit itemChanged(rowIndex, columnIndex);
235}
236
237/*!
238 * Changes a single item at the position \a position to the item \a item.
239 * The x-value of \a position indicates the row and the y-value indicates the
240 * column.
241 */
242void QBarDataProxy::setItem(const QPoint &position, const QBarDataItem &item)
243{
244 setItem(rowIndex: position.x(), columnIndex: position.y(), item);
245}
246
247/*!
248 * Adds the new row \a row to the end of an array.
249 * Existing row labels are not affected.
250 *
251 * Returns the index of the added row.
252 */
253int QBarDataProxy::addRow(QBarDataRow *row)
254{
255 Q_D(QBarDataProxy);
256 int addIndex = d->addRow(row, label: 0);
257 emit rowsAdded(startIndex: addIndex, count: 1);
258 emit rowCountChanged(count: rowCount());
259 emit colCountChanged(count: colCount());
260 return addIndex;
261}
262
263/*!
264 * Adds a the new row \a row with the label \a label to the end of an array.
265 *
266 * Returns the index of the added row.
267 */
268int QBarDataProxy::addRow(QBarDataRow *row, const QString &label)
269{
270 Q_D(QBarDataProxy);
271 int addIndex = d->addRow(row, label: &label);
272 emit rowsAdded(startIndex: addIndex, count: 1);
273 emit rowCountChanged(count: rowCount());
274 emit colCountChanged(count: colCount());
275 return addIndex;
276}
277
278/*!
279 * Adds the new \a rows to the end of an array.
280 * Existing row labels are not affected.
281 *
282 * Returns the index of the first added row.
283 */
284int QBarDataProxy::addRows(const QBarDataArray &rows)
285{
286 Q_D(QBarDataProxy);
287 int addIndex = d->addRows(rows, labels: 0);
288 emit rowsAdded(startIndex: addIndex, count: rows.size());
289 emit rowCountChanged(count: rowCount());
290 emit colCountChanged(count: colCount());
291 return addIndex;
292}
293
294/*!
295 * Adds the new \a rows with \a labels to the end of the array.
296 *
297 * Returns the index of the first added row.
298 */
299int QBarDataProxy::addRows(const QBarDataArray &rows, const QStringList &labels)
300{
301 Q_D(QBarDataProxy);
302 int addIndex = d->addRows(rows, labels: &labels);
303 emit rowsAdded(startIndex: addIndex, count: rows.size());
304 emit rowCountChanged(count: rowCount());
305 emit colCountChanged(count: colCount());
306 return addIndex;
307}
308
309/*!
310 * Inserts the new row \a row into \a rowIndex.
311 * If \a rowIndex is equal to the array size, the rows are added to the end of
312 * the array.
313 * The existing row labels are not affected.
314 * \note The row labels array will be out of sync with the row array after this call
315 * if there were labeled rows beyond the inserted row.
316 */
317void QBarDataProxy::insertRow(int rowIndex, QBarDataRow *row)
318{
319 Q_D(QBarDataProxy);
320 d->insertRow(rowIndex, row, label: 0);
321 emit rowsInserted(startIndex: rowIndex, count: 1);
322 emit rowCountChanged(count: rowCount());
323 emit colCountChanged(count: colCount());
324}
325
326/*!
327 * Inserts the new row \a row with the label \a label into \a rowIndex.
328 * If \a rowIndex is equal to array size, rows are added to the end of the
329 * array.
330 */
331void QBarDataProxy::insertRow(int rowIndex, QBarDataRow *row, const QString &label)
332{
333 Q_D(QBarDataProxy);
334 d->insertRow(rowIndex, row, label: &label);
335 emit rowsInserted(startIndex: rowIndex, count: 1);
336 emit rowCountChanged(count: rowCount());
337 emit colCountChanged(count: colCount());
338}
339
340/*!
341 * Inserts new \a rows into \a rowIndex.
342 * If \a rowIndex is equal to the array size, the rows are added to the end of
343 * the array. The existing row labels are not affected.
344 * \note The row labels array will be out of sync with the row array after this call
345 * if there were labeled rows beyond the inserted rows.
346 */
347void QBarDataProxy::insertRows(int rowIndex, const QBarDataArray &rows)
348{
349 Q_D(QBarDataProxy);
350 d->insertRows(rowIndex, rows, labels: 0);
351 emit rowsInserted(startIndex: rowIndex, count: rows.size());
352 emit rowCountChanged(count: rowCount());
353 emit colCountChanged(count: colCount());
354}
355
356/*!
357 * Inserts new \a rows with \a labels into \a rowIndex.
358 * If \a rowIndex is equal to the array size, the rows are added to the end of
359 * the array.
360 */
361void QBarDataProxy::insertRows(int rowIndex, const QBarDataArray &rows, const QStringList &labels)
362{
363 Q_D(QBarDataProxy);
364 d->insertRows(rowIndex, rows, labels: &labels);
365 emit rowsInserted(startIndex: rowIndex, count: rows.size());
366 emit rowCountChanged(count: rowCount());
367 emit colCountChanged(count: colCount());
368}
369
370/*!
371 * Removes the number of rows specified by \a removeCount starting at the
372 * position \a rowIndex. Attempting to remove rows past the end of the
373 * array does nothing. If \a removeLabels is \c true, the corresponding row
374 * labels are also removed. Otherwise, the row labels are not affected.
375 * \note If \a removeLabels is \c false, the row labels array will be out of
376 * sync with the row array if there are labeled rows beyond the removed rows.
377 */
378void QBarDataProxy::removeRows(int rowIndex, int removeCount, bool removeLabels)
379{
380 Q_D(QBarDataProxy);
381 if (rowIndex < rowCount() && removeCount >= 1) {
382 d->removeRows(rowIndex, removeCount, removeLabels);
383 emit rowsRemoved(startIndex: rowIndex, count: removeCount);
384 emit rowCountChanged(count: rowCount());
385 emit colCountChanged(count: colCount());
386 }
387}
388
389/*!
390 * \property QBarDataProxy::colCount
391 *
392 * \brief The number of columns in the array.
393 */
394int QBarDataProxy::colCount() const
395{
396 const Q_D(QBarDataProxy);
397 if (d->m_dataArray->size() <= 0)
398 return 0;
399 return d->m_dataArray->at(i: 0)->size();
400}
401
402/*!
403 * \property QBarDataProxy::rowCount
404 *
405 * \brief The number of rows in the array.
406 */
407int QBarDataProxy::rowCount() const
408{
409 const Q_D(QBarDataProxy);
410 return d->m_dataArray->size();
411}
412
413/*!
414 * \property QBarDataProxy::rowLabels
415 *
416 * \brief The optional row labels for the array.
417 *
418 * Indexes in this array match the row indexes in the data array.
419 * If the list is shorter than the number of rows, all rows will not get labels.
420 */
421QStringList QBarDataProxy::rowLabels() const
422{
423 const Q_D(QBarDataProxy);
424 return d->m_rowLabels;
425}
426
427void QBarDataProxy::setRowLabels(const QStringList &labels)
428{
429 Q_D(QBarDataProxy);
430 if (d->m_rowLabels != labels) {
431 d->m_rowLabels = labels;
432 emit rowLabelsChanged();
433 }
434}
435
436/*!
437 * \property QBarDataProxy::columnLabels
438 *
439 * \brief The optional column labels for the array.
440 *
441 * Indexes in this array match column indexes in rows.
442 * If the list is shorter than the longest row, all columns will not get labels.
443 */
444QStringList QBarDataProxy::columnLabels() const
445{
446 const Q_D(QBarDataProxy);
447 return d->m_columnLabels;
448}
449
450void QBarDataProxy::setColumnLabels(const QStringList &labels)
451{
452 Q_D(QBarDataProxy);
453 if (d->m_columnLabels != labels) {
454 d->m_columnLabels = labels;
455 emit columnLabelsChanged();
456 }
457}
458
459/*!
460 * Returns the pointer to the data array.
461 */
462const QBarDataArray *QBarDataProxy::array() const
463{
464 const Q_D(QBarDataProxy);
465 return d->m_dataArray;
466}
467
468/*!
469 * Returns the pointer to the row at the position \a rowIndex. It is guaranteed
470 * to be valid only until the next call that modifies data.
471 */
472const QBarDataRow *QBarDataProxy::rowAt(int rowIndex) const
473{
474 const Q_D(QBarDataProxy);
475 const QBarDataArray &dataArray = *d->m_dataArray;
476 Q_ASSERT(rowIndex >= 0 && rowIndex < dataArray.size());
477 return dataArray[rowIndex];
478}
479
480/*!
481 * Returns the pointer to the item at the position specified by \a rowIndex and
482 * \a columnIndex. It is guaranteed to be valid only
483 * until the next call that modifies data.
484 */
485const QBarDataItem *QBarDataProxy::itemAt(int rowIndex, int columnIndex) const
486{
487 const Q_D(QBarDataProxy);
488 const QBarDataArray &dataArray = *d->m_dataArray;
489 Q_ASSERT(rowIndex >= 0 && rowIndex < dataArray.size());
490 const QBarDataRow &dataRow = *dataArray[rowIndex];
491 Q_ASSERT(columnIndex >= 0 && columnIndex < dataRow.size());
492 return &dataRow.at(i: columnIndex);
493}
494
495/*!
496 * Returns the pointer to the item at the position \a position. The x-value of
497 * \a position indicates the row and the y-value indicates the column. The item
498 * is guaranteed to be valid only until the next call that modifies data.
499 */
500const QBarDataItem *QBarDataProxy::itemAt(const QPoint &position) const
501{
502 return itemAt(rowIndex: position.x(), columnIndex: position.y());
503}
504
505/*!
506 * \fn void QBarDataProxy::arrayReset()
507 *
508 * This signal is emitted when the data array is reset.
509 * If the contents of the whole array are changed without calling resetArray(),
510 * this signal needs to be emitted to update the graph.
511 */
512
513/*!
514 * \fn void QBarDataProxy::rowsAdded(int startIndex, int count)
515 *
516 * This signal is emitted when the number of rows specified by \a count is
517 * added starting at the position \a startIndex.
518 * If rows are added to the array without calling addRow() or addRows(),
519 * this signal needs to be emitted to update the graph.
520 */
521
522/*!
523 * \fn void QBarDataProxy::rowsChanged(int startIndex, int count)
524 *
525 * This signal is emitted when the number of rows specified by \a count is
526 * changed starting at the position \a startIndex.
527 * If rows are changed in the array without calling setRow() or setRows(),
528 * this signal needs to be emitted to update the graph.
529 */
530
531/*!
532 * \fn void QBarDataProxy::rowsRemoved(int startIndex, int count)
533 *
534 * This signal is emitted when the number of rows specified by \a count is
535 * removed starting at the position \a startIndex.
536 *
537 * The index is the current array size if the rows were removed from the end of
538 * the array. If rows are removed from the array without calling removeRows(),
539 * this signal needs to be emitted to update the graph.
540 */
541
542/*!
543 * \fn void QBarDataProxy::rowsInserted(int startIndex, int count)
544 *
545 * This signal is emitted when the number of rows specified by \a count is
546 * inserted at the position \a startIndex.
547 *
548 * If rows are inserted into the array without calling insertRow() or
549 * insertRows(), this signal needs to be emitted to update the graph.
550 */
551
552/*!
553 * \fn void QBarDataProxy::itemChanged(int rowIndex, int columnIndex)
554 *
555 * This signal is emitted when the item at the position specified by \a rowIndex
556 * and \a columnIndex changes.
557 * If the item is changed in the array without calling setItem(),
558 * this signal needs to be emitted to update the graph.
559 */
560
561// QBarDataProxyPrivate
562
563QBarDataProxyPrivate::QBarDataProxyPrivate(QBarDataProxy *q)
564 : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeBar),
565 m_dataArray(new QBarDataArray)
566{
567}
568
569QBarDataProxyPrivate::~QBarDataProxyPrivate()
570{
571 clearArray();
572}
573
574void QBarDataProxyPrivate::resetArray(QBarDataArray *newArray, const QStringList *rowLabels,
575 const QStringList *columnLabels)
576{
577 Q_Q(QBarDataProxy);
578 if (rowLabels)
579 q->setRowLabels(*rowLabels);
580 if (columnLabels)
581 q->setColumnLabels(*columnLabels);
582
583 if (!newArray)
584 newArray = new QBarDataArray;
585
586 if (newArray != m_dataArray) {
587 clearArray();
588 m_dataArray = newArray;
589 }
590}
591
592void QBarDataProxyPrivate::setRow(int rowIndex, QBarDataRow *row, const QString *label)
593{
594 Q_ASSERT(rowIndex >= 0 && rowIndex < m_dataArray->size());
595
596 if (label)
597 fixRowLabels(startIndex: rowIndex, count: 1, newLabels: QStringList(*label), isInsert: false);
598 if (row != m_dataArray->at(i: rowIndex)) {
599 clearRow(rowIndex);
600 (*m_dataArray)[rowIndex] = row;
601 }
602}
603
604void QBarDataProxyPrivate::setRows(int rowIndex, const QBarDataArray &rows,
605 const QStringList *labels)
606{
607 QBarDataArray &dataArray = *m_dataArray;
608 Q_ASSERT(rowIndex >= 0 && (rowIndex + rows.size()) <= dataArray.size());
609 if (labels)
610 fixRowLabels(startIndex: rowIndex, count: rows.size(), newLabels: *labels, isInsert: false);
611 for (int i = 0; i < rows.size(); i++) {
612 if (rows.at(i) != dataArray.at(i: rowIndex)) {
613 clearRow(rowIndex);
614 dataArray[rowIndex] = rows.at(i);
615 }
616 rowIndex++;
617 }
618}
619
620void QBarDataProxyPrivate::setItem(int rowIndex, int columnIndex, const QBarDataItem &item)
621{
622 Q_ASSERT(rowIndex >= 0 && rowIndex < m_dataArray->size());
623 QBarDataRow &row = *(*m_dataArray)[rowIndex];
624 Q_ASSERT(columnIndex < row.size());
625 row[columnIndex] = item;
626}
627
628int QBarDataProxyPrivate::addRow(QBarDataRow *row, const QString *label)
629{
630 int currentSize = m_dataArray->size();
631 if (label)
632 fixRowLabels(startIndex: currentSize, count: 1, newLabels: QStringList(*label), isInsert: false);
633 m_dataArray->append(t: row);
634 return currentSize;
635}
636
637int QBarDataProxyPrivate::addRows(const QBarDataArray &rows, const QStringList *labels)
638{
639 int currentSize = m_dataArray->size();
640 if (labels)
641 fixRowLabels(startIndex: currentSize, count: rows.size(), newLabels: *labels, isInsert: false);
642 for (int i = 0; i < rows.size(); i++)
643 m_dataArray->append(t: rows.at(i));
644 return currentSize;
645}
646
647void QBarDataProxyPrivate::insertRow(int rowIndex, QBarDataRow *row, const QString *label)
648{
649 Q_ASSERT(rowIndex >= 0 && rowIndex <= m_dataArray->size());
650 if (label)
651 fixRowLabels(startIndex: rowIndex, count: 1, newLabels: QStringList(*label), isInsert: true);
652 m_dataArray->insert(i: rowIndex, t: row);
653}
654
655void QBarDataProxyPrivate::insertRows(int rowIndex, const QBarDataArray &rows,
656 const QStringList *labels)
657{
658 Q_ASSERT(rowIndex >= 0 && rowIndex <= m_dataArray->size());
659 if (labels)
660 fixRowLabels(startIndex: rowIndex, count: rows.size(), newLabels: *labels, isInsert: true);
661 for (int i = 0; i < rows.size(); i++)
662 m_dataArray->insert(i: rowIndex++, t: rows.at(i));
663}
664
665void QBarDataProxyPrivate::removeRows(int rowIndex, int removeCount, bool removeLabels)
666{
667 Q_ASSERT(rowIndex >= 0);
668 Q_Q(QBarDataProxy);
669 int maxRemoveCount = m_dataArray->size() - rowIndex;
670 removeCount = qMin(a: removeCount, b: maxRemoveCount);
671 bool labelsChanged = false;
672 for (int i = 0; i < removeCount; i++) {
673 clearRow(rowIndex);
674 m_dataArray->removeAt(i: rowIndex);
675 if (removeLabels && m_rowLabels.size() > rowIndex) {
676 m_rowLabels.removeAt(i: rowIndex);
677 labelsChanged = true;
678 }
679 }
680 if (labelsChanged)
681 emit q->rowLabelsChanged();
682}
683
684void QBarDataProxyPrivate::clearRow(int rowIndex)
685{
686 if (m_dataArray->at(i: rowIndex)) {
687 delete m_dataArray->at(i: rowIndex);
688 (*m_dataArray)[rowIndex] = 0;
689 }
690}
691
692void QBarDataProxyPrivate::clearArray()
693{
694 for (int i = 0; i < m_dataArray->size(); i++)
695 clearRow(rowIndex: i);
696 m_dataArray->clear();
697 delete m_dataArray;
698}
699
700/*!
701 * \internal
702 * Fixes the row label array to include specified labels.
703 */
704void QBarDataProxyPrivate::fixRowLabels(int startIndex, int count, const QStringList &newLabels,
705 bool isInsert)
706{
707 Q_Q(QBarDataProxy);
708 bool changed = false;
709 int currentSize = m_rowLabels.size();
710
711 int newSize = newLabels.size();
712 if (startIndex >= currentSize) {
713 // Adding labels past old label array, create empty strings to fill intervening space
714 if (newSize) {
715 for (int i = currentSize; i < startIndex; i++)
716 m_rowLabels << QString();
717 // Doesn't matter if insert, append, or just change when there were no existing
718 // strings, just append new strings.
719 m_rowLabels << newLabels;
720 changed = true;
721 }
722 } else {
723 if (isInsert) {
724 int insertIndex = startIndex;
725 if (count)
726 changed = true;
727 for (int i = 0; i < count; i++) {
728 if (i < newSize)
729 m_rowLabels.insert(i: insertIndex++, t: newLabels.at(i));
730 else
731 m_rowLabels.insert(i: insertIndex++, t: QString());
732 }
733 } else {
734 // Either append or change, replace labels up to array end and then add new ones
735 int lastChangeIndex = count + startIndex;
736 int newIndex = 0;
737 for (int i = startIndex; i < lastChangeIndex; i++) {
738 if (i >= currentSize) {
739 // Label past the current size, so just append the new label
740 if (newSize < newIndex) {
741 changed = true;
742 m_rowLabels << newLabels.at(i: newIndex);
743 } else {
744 break; // No point appending empty strings, so just exit
745 }
746 } else if (newSize > newIndex) {
747 // Replace existing label
748 if (m_rowLabels.at(i) != newLabels.at(i: newIndex)) {
749 changed = true;
750 m_rowLabels[i] = newLabels.at(i: newIndex);
751 }
752 } else {
753 // No more new labels, so clear existing label
754 if (!m_rowLabels.at(i).isEmpty()) {
755 changed = true;
756 m_rowLabels[i] = QString();
757 }
758 }
759 newIndex++;
760 }
761 }
762 }
763 if (changed)
764 emit q->rowLabelsChanged();
765}
766
767QPair<float, float> QBarDataProxyPrivate::limitValues(int startRow, int endRow,
768 int startColumn, int endColumn) const
769{
770 QPair<float, float> limits = qMakePair(value1: 0.0f, value2: 0.0f);
771 endRow = qMin(a: endRow, b: m_dataArray->size() - 1);
772 for (int i = startRow; i <= endRow; i++) {
773 QBarDataRow *row = m_dataArray->at(i);
774 if (row) {
775 int lastColumn = qMin(a: endColumn, b: row->size() - 1);
776 for (int j = startColumn; j <= lastColumn; j++) {
777 const QBarDataItem &item = row->at(i: j);
778 float itemValue = item.value();
779 if (limits.second < itemValue)
780 limits.second = itemValue;
781 if (limits.first > itemValue)
782 limits.first = itemValue;
783 }
784 }
785 }
786 return limits;
787}
788
789void QBarDataProxyPrivate::setSeries(QAbstract3DSeries *series)
790{
791 Q_Q(QBarDataProxy);
792 QAbstractDataProxyPrivate::setSeries(series);
793 QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(series);
794 emit q->seriesChanged(series: barSeries);
795}
796
797QT_END_NAMESPACE
798

source code of qtgraphs/src/graphs/data/qbardataproxy.cpp