diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-09-10 16:26:11 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-09-11 10:42:53 +0300 |
commit | d93f5f3b64fdb52cc150232f6b6d80ffdb57db78 (patch) | |
tree | 4a99ecc02c2e885b56abb1082527e482967b84f8 /src/datavisualization/data/qbardataproxy.cpp | |
parent | d315336b202ec1c1260f96945a23fde6d2c41b69 (diff) |
QBarDataProxy now has list of row and column labels
Category axes use those labels if no explicit labels are set to them.
+ Other misc fixes
Task-number: QTRD-2252
Change-Id: Idc15e0cc1cdeb08195b2e2baeead9cfef2533e04
Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Diffstat (limited to 'src/datavisualization/data/qbardataproxy.cpp')
-rw-r--r-- | src/datavisualization/data/qbardataproxy.cpp | 291 |
1 files changed, 266 insertions, 25 deletions
diff --git a/src/datavisualization/data/qbardataproxy.cpp b/src/datavisualization/data/qbardataproxy.cpp index 85400831..418bb747 100644 --- a/src/datavisualization/data/qbardataproxy.cpp +++ b/src/datavisualization/data/qbardataproxy.cpp @@ -37,6 +37,12 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * QBarDataRow pointers should not be used to modify data further after they have been passed to * the proxy, as such modifications will not trigger proper signals. * + * QBarDataProxy optionally keeps track of row and column labels, which Q3DCategoryAxis can utilize + * to show axis labels. The row and column labels are stored in separate array from the data and + * row manipulation methods provide an alternate versions that don't affect the row labels. + * This enables the option of having row labels that relate to the position of the data in the + * array rather than the data itself. + * * QBarDataProxy supports the following format tags for QAbstractDataProxy::setItemLabelFormat(): * \table * \row @@ -88,37 +94,82 @@ QBarDataProxy::~QBarDataProxy() } /*! + * Clears the existing array and row and column labels. + */ +void QBarDataProxy::resetArray() +{ + resetArray(0, QStringList(), QStringList()); +} + +/*! * Clears the existing array and takes ownership of the \a newArray. Do not use \a newArray pointer * to further modify data after QBarDataProxy assumes ownership of it, as such modifications will * not trigger proper signals. * Passing null array clears all data. + * Row and column labels are not affected. */ void QBarDataProxy::resetArray(QBarDataArray *newArray) { - if (dptr()->resetArray(newArray)) + if (dptr()->resetArray(newArray, 0, 0)) + emit arrayReset(); +} + +/*! + * Clears the existing array and takes ownership of the \a newArray. Do not use \a newArray pointer + * to further modify data after QBarDataProxy assumes ownership of it, as such modifications will + * not trigger proper signals. + * Passing null array clears all data. + * The \a rowLabels and \a columnLabels lists specify the new labels for rows and columns. + */ +void QBarDataProxy::resetArray(QBarDataArray *newArray, const QStringList &rowLabels, + const QStringList &columnLabels) +{ + if (dptr()->resetArray(newArray, &rowLabels, &columnLabels)) emit arrayReset(); } /*! * Changes existing rows by replacing a row at \a rowIndex with \a row. + * Existing row labels are not affected. */ void QBarDataProxy::setRow(int rowIndex, QBarDataRow *row) { - dptr()->setRow(rowIndex, row); + dptr()->setRow(rowIndex, row, 0); + emit rowsChanged(rowIndex, 1); +} + +/*! + * Changes existing rows by replacing a row at \a rowIndex with \a row. + * Changes the row label to the \a label. + */ +void QBarDataProxy::setRow(int rowIndex, QBarDataRow *row, const QString &label) +{ + dptr()->setRow(rowIndex, row, &label); emit rowsChanged(rowIndex, 1); } /*! * Changes existing rows by replacing a rows starting at \a rowIndex with \a rows. + * Existing row labels are not affected. */ void QBarDataProxy::setRows(int rowIndex, const QBarDataArray &rows) { - dptr()->setRows(rowIndex, rows); + dptr()->setRows(rowIndex, rows, 0); emit rowsChanged(rowIndex, rows.size()); } /*! - * Changes a single item at \a rowIndex, \a columnIndex with \a item. + * Changes existing rows by replacing a rows starting at \a rowIndex with \a rows. + * The row labels are changed to \a labels. + */ +void QBarDataProxy::setRows(int rowIndex, const QBarDataArray &rows, const QStringList &labels) +{ + dptr()->setRows(rowIndex, rows, &labels); + emit rowsChanged(rowIndex, rows.size()); +} + +/*! + * Changes a single item at \a rowIndex, \a columnIndex to the \a item. */ void QBarDataProxy::setItem(int rowIndex, int columnIndex, const QBarDataItem &item) { @@ -128,56 +179,111 @@ void QBarDataProxy::setItem(int rowIndex, int columnIndex, const QBarDataItem &i /*! * Adds a new \a row to the end of array. + * Existing row labels are not affected. * * \return index of the added row. */ int QBarDataProxy::addRow(QBarDataRow *row) { - int addIndex = dptr()->addRow(row); + int addIndex = dptr()->addRow(row, 0); + emit rowsAdded(addIndex, 1); + return addIndex; +} + +/*! + * Adds a new \a row with the \a label to the end of array. + * + * \return index of the added row. + */ +int QBarDataProxy::addRow(QBarDataRow *row, const QString &label) +{ + int addIndex = dptr()->addRow(row, &label); emit rowsAdded(addIndex, 1); return addIndex; } /*! * Adds new \a rows to the end of array. + * Existing row labels are not affected. * * \return index of the first added row. */ int QBarDataProxy::addRows(const QBarDataArray &rows) { - int addIndex = dptr()->addRows(rows); + int addIndex = dptr()->addRows(rows, 0); + emit rowsAdded(addIndex, rows.size()); + return addIndex; +} + +/*! + * Adds new \a rows with \a labels to the end of array. + * + * \return index of the first added row. + */ +int QBarDataProxy::addRows(const QBarDataArray &rows, const QStringList &labels) +{ + int addIndex = dptr()->addRows(rows, &labels); emit rowsAdded(addIndex, rows.size()); return addIndex; } /*! - * Inserts a new \a row to \a rowIndex. If rowIndex is equal to array size, rows are added to end - * of the array. + * Inserts a new \a row into \a rowIndex. + * If rowIndex is equal to array size, rows are added to end of the array. + * Any existing row labels are not affected. + * \note Row labels array will be out of sync with row array after this call, + * if there were labeled rows beyond the inserted row. */ void QBarDataProxy::insertRow(int rowIndex, QBarDataRow *row) { - dptr()->insertRow(rowIndex, row); + dptr()->insertRow(rowIndex, row, 0); emit rowsInserted(rowIndex, 1); } /*! - * Inserts new \a rows to \a rowIndex. If rowIndex is equal to array size, rows are added to end - * of the array. + * Inserts a new \a row with the \a label into \a rowIndex. + * If rowIndex is equal to array size, rows are added to end of the array. + */ +void QBarDataProxy::insertRow(int rowIndex, QBarDataRow *row, const QString &label) +{ + dptr()->insertRow(rowIndex, row, &label); + emit rowsInserted(rowIndex, 1); +} + +/*! + * Inserts new \a rows into \a rowIndex. + * If rowIndex is equal to array size, rows are added to end of the array. + * Any existing row labels are not affected. + * \note Row labels array will be out of sync with row array after this call, + * if there were labeled rows beyond the inserted rows. */ void QBarDataProxy::insertRows(int rowIndex, const QBarDataArray &rows) { - dptr()->insertRows(rowIndex, rows); + dptr()->insertRows(rowIndex, rows, 0); + emit rowsInserted(rowIndex, rows.size()); +} + +/*! + * Inserts new \a rows with \a labels into \a rowIndex. + * If rowIndex is equal to array size, rows are added to end of the array. + */ +void QBarDataProxy::insertRows(int rowIndex, const QBarDataArray &rows, const QStringList &labels) +{ + dptr()->insertRows(rowIndex, rows, &labels); emit rowsInserted(rowIndex, rows.size()); } /*! * Removes \a removeCount rows staring at \a rowIndex. Attempting to remove rows past the end of the - * array does nothing. + * array does nothing. If \a removeLabels is true, corresponding row labels are also removed. Otherwise + * the row labels are not affected. + * \note If \a removeLabels is false, the row labels array will be out of sync with the row array + * if there are labeled rows beyond the removed rows. */ -void QBarDataProxy::removeRows(int rowIndex, int removeCount) +void QBarDataProxy::removeRows(int rowIndex, int removeCount, bool removeLabels) { - if (rowIndex < rowCount()) { - dptr()->removeRows(rowIndex, removeCount); + if (rowIndex < rowCount() && removeCount >= 1) { + dptr()->removeRows(rowIndex, removeCount, removeLabels); emit rowsRemoved(rowIndex, removeCount); } } @@ -185,7 +291,7 @@ void QBarDataProxy::removeRows(int rowIndex, int removeCount) /*! * \property QBarDataProxy::rowCount * - * \return row count in the array. + * Row count in the array. */ int QBarDataProxy::rowCount() const { @@ -193,6 +299,45 @@ int QBarDataProxy::rowCount() const } /*! + * \property QBarDataProxy::rowLabels + * + * Optional row labels for the array. Indexes in this array match row indexes in data array. + * If the list is shorter than row count, all rows will not get labels. + */ + +QStringList QBarDataProxy::rowLabels() const +{ + return dptrc()->m_rowLabels; +} + +void QBarDataProxy::setRowLabels(const QStringList &labels) +{ + if (dptr()->m_rowLabels != labels) { + dptr()->m_rowLabels = labels; + emit rowLabelsChanged(); + } +} + +/*! + * \property QBarDataProxy::columnLabels + * + * Optional column labels for the array. Indexes in this array match column indexes in rows. + * If the list is shorter than the longest row, all columns will not get labels. + */ +QStringList QBarDataProxy::columnLabels() const +{ + return dptrc()->m_columnLabels; +} + +void QBarDataProxy::setColumnLabels(const QStringList &labels) +{ + if (dptr()->m_columnLabels != labels) { + dptr()->m_columnLabels = labels; + emit columnLabelsChanged(); + } +} + +/*! * \return pointer to the data array. */ const QBarDataArray *QBarDataProxy::array() const @@ -291,8 +436,14 @@ QBarDataProxyPrivate::~QBarDataProxyPrivate() clearArray(); } -bool QBarDataProxyPrivate::resetArray(QBarDataArray *newArray) +bool QBarDataProxyPrivate::resetArray(QBarDataArray *newArray, const QStringList *rowLabels, + const QStringList *columnLabels) { + if (rowLabels) + qptr()->setRowLabels(*rowLabels); + if (columnLabels) + qptr()->setColumnLabels(*columnLabels); + if (!m_dataArray->size() && (!newArray || !newArray->size())) return false; @@ -306,17 +457,22 @@ bool QBarDataProxyPrivate::resetArray(QBarDataArray *newArray) return true; } -void QBarDataProxyPrivate::setRow(int rowIndex, QBarDataRow *row) +void QBarDataProxyPrivate::setRow(int rowIndex, QBarDataRow *row, const QString *label) { Q_ASSERT(rowIndex >= 0 && rowIndex < m_dataArray->size()); + + if (label) + fixRowLabels(rowIndex, 1, QStringList(*label), false); clearRow(rowIndex); (*m_dataArray)[rowIndex] = row; } -void QBarDataProxyPrivate::setRows(int rowIndex, const QBarDataArray &rows) +void QBarDataProxyPrivate::setRows(int rowIndex, const QBarDataArray &rows, const QStringList *labels) { QBarDataArray &dataArray = *m_dataArray; Q_ASSERT(rowIndex >= 0 && (rowIndex + rows.size()) <= dataArray.size()); + if (labels) + fixRowLabels(rowIndex, rows.size(), *labels, false); for (int i = 0; i < rows.size(); i++) { clearRow(rowIndex); dataArray[rowIndex] = rows.at(i); @@ -332,43 +488,63 @@ void QBarDataProxyPrivate::setItem(int rowIndex, int columnIndex, const QBarData row[columnIndex] = item; } -int QBarDataProxyPrivate::addRow(QBarDataRow *row) +int QBarDataProxyPrivate::addRow(QBarDataRow *row, const QString *label) { int currentSize = m_dataArray->size(); + if (label) + fixRowLabels(currentSize, 1, QStringList(*label), false); m_dataArray->append(row); return currentSize; } -int QBarDataProxyPrivate::addRows(const QBarDataArray &rows) +int QBarDataProxyPrivate::addRows(const QBarDataArray &rows, const QStringList *labels) { int currentSize = m_dataArray->size(); + if (labels) + fixRowLabels(currentSize, rows.size(), *labels, false); for (int i = 0; i < rows.size(); i++) m_dataArray->append(rows.at(i)); return currentSize; } -void QBarDataProxyPrivate::insertRow(int rowIndex, QBarDataRow *row) +void QBarDataProxyPrivate::insertRow(int rowIndex, QBarDataRow *row, const QString *label) { Q_ASSERT(rowIndex >= 0 && rowIndex <= m_dataArray->size()); + if (label) + fixRowLabels(rowIndex, 1, QStringList(*label), true); m_dataArray->insert(rowIndex, row); } -void QBarDataProxyPrivate::insertRows(int rowIndex, const QBarDataArray &rows) +void QBarDataProxyPrivate::insertRows(int rowIndex, const QBarDataArray &rows, const QStringList *labels) { Q_ASSERT(rowIndex >= 0 && rowIndex <= m_dataArray->size()); + if (labels) + fixRowLabels(rowIndex, rows.size(), *labels, true); for (int i = 0; i < rows.size(); i++) m_dataArray->insert(rowIndex++, rows.at(i)); } -void QBarDataProxyPrivate::removeRows(int rowIndex, int removeCount) +void QBarDataProxyPrivate::removeRows(int rowIndex, int removeCount, bool removeLabels) { Q_ASSERT(rowIndex >= 0); int maxRemoveCount = m_dataArray->size() - rowIndex; removeCount = qMin(removeCount, maxRemoveCount); + bool labelsChanged = false; for (int i = 0; i < removeCount; i++) { clearRow(rowIndex); m_dataArray->removeAt(rowIndex); + if (removeLabels && m_rowLabels.size() > rowIndex) { + m_rowLabels.removeAt(rowIndex); + labelsChanged = true; + } } + if (labelsChanged) + emit qptr()->rowLabelsChanged(); +} + +QBarDataProxy *QBarDataProxyPrivate::qptr() +{ + return static_cast<QBarDataProxy *>(q_ptr); } void QBarDataProxyPrivate::clearRow(int rowIndex) @@ -387,6 +563,71 @@ void QBarDataProxyPrivate::clearArray() delete m_dataArray; } +/*! + * \internal + * Fixes the row label array to include specified labels. + */ +void QBarDataProxyPrivate::fixRowLabels(int startIndex, int count, const QStringList &newLabels, bool isInsert) +{ + bool changed = false; + int currentSize = m_rowLabels.size(); + + int newSize = newLabels.size(); + if (startIndex >= currentSize) { + // Adding labels past old label array, create empty strings to fill intervening space + if (newSize) { + for (int i = currentSize; i < startIndex; i++) + m_rowLabels << QString(); + // Doesn't matter if insert, append, or just change when there were no existing + // strings, just append new strings. + m_rowLabels << newLabels; + changed = true; + } + } else { + if (isInsert) { + int insertIndex = startIndex; + if (count) + changed = true; + for (int i = 0; i < count; i++) { + if (i < newSize) + m_rowLabels.insert(insertIndex++, newLabels.at(i)); + else + m_rowLabels.insert(insertIndex++, QString()); + } + } else { + // Either append or change, replace labels up to array end and then add new ones + int lastChangeIndex = count + startIndex; + int newIndex = 0; + for (int i = startIndex; i < lastChangeIndex; i++) { + if (i >= currentSize) { + // Label past the current size, so just append the new label + if (newSize < newIndex) { + changed = true; + m_rowLabels << newLabels.at(newIndex); + } else { + break; // No point appending empty strings, so just exit + } + } else if (newSize > newIndex) { + // Replace existing label + if (m_rowLabels.at(i) != newLabels.at(newIndex)) { + changed = true; + m_rowLabels[i] = newLabels.at(newIndex); + } + } else { + // No more new labels, so clear existing label + if (!m_rowLabels.at(i).isEmpty()) { + changed = true; + m_rowLabels[i] = QString(); + } + } + newIndex++; + } + } + } + if (changed) + emit qptr()->rowLabelsChanged(); +} + QPair<GLfloat, GLfloat> QBarDataProxyPrivate::limitValues(int startRow, int endRow, int startColumn, int endColumn) { QPair<GLfloat, GLfloat> limits = qMakePair(0.0f, 0.0f); |