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

source code of qtdatavis3d/src/datavisualization/data/qbardataproxy.cpp