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

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