From d93f5f3b64fdb52cc150232f6b6d80ffdb57db78 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Tue, 10 Sep 2013 16:26:11 +0300 Subject: QBarDataProxy now has list of row and column labels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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ää --- examples/barchart/main.cpp | 54 +++- examples/widget/chart.cpp | 4 +- src/datavisualization/axis/q3dcategoryaxis.cpp | 49 +++- src/datavisualization/axis/q3dcategoryaxis.h | 4 +- src/datavisualization/axis/q3dcategoryaxis_p.h | 8 + src/datavisualization/data/baritemmodelhandler.cpp | 12 +- src/datavisualization/data/qbardataproxy.cpp | 291 +++++++++++++++++++-- src/datavisualization/data/qbardataproxy.h | 24 +- src/datavisualization/data/qbardataproxy_p.h | 24 +- .../engine/abstract3dcontroller_p.h | 2 +- .../engine/abstract3drenderer_p.h | 2 +- src/datavisualization/engine/bars3dcontroller.cpp | 45 +++- src/datavisualization/engine/bars3dcontroller_p.h | 5 + src/datavisualization/engine/q3dscene.cpp | 1 + src/datavisualization/engine/q3dwindow.h | 2 +- src/datavisualization/engine/surface3drenderer.cpp | 1 - tests/barstest/chart.cpp | 65 +++-- tests/barstest/chart.h | 2 + tests/barstest/main.cpp | 40 ++- 19 files changed, 538 insertions(+), 97 deletions(-) diff --git a/examples/barchart/main.cpp b/examples/barchart/main.cpp index 5fa798fd..0386bd74 100644 --- a/examples/barchart/main.cpp +++ b/examples/barchart/main.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #define USE_STATIC_DATA @@ -46,7 +47,8 @@ public: void changeTheme(); void start(); void selectFromTable(const QPoint &selection); - void selectedFromTable(int row, int column); + void selectedFromTable(int currentRow, int currentColumn, int previousRow, int previousColumn); + void fixTableSize(); private: Q3DBars *m_chart; @@ -73,18 +75,22 @@ ChartDataGenerator::ChartDataGenerator(Q3DBars *barchart, QTableWidget *tableWid // and add a small space between the bars m_chart->setBarSpecs(1.0, QSizeF(0.2, 0.2)); + // Set bar type to flat pyramids + m_chart->setBarType(QDataVis::Pyramids, false); + #ifndef USE_STATIC_DATA // Set up sample space; make it as deep as it's wide m_chart->setDataWindow(m_rowCount, m_columnCount); m_tableWidget->setColumnCount(m_columnCount); -#endif - - // Set bar type to flat pyramids - m_chart->setBarType(QDataVis::Pyramids, false); -#ifndef USE_STATIC_DATA // Set selection mode to full m_chart->setSelectionMode(QDataVis::ModeItemRowAndColumn); + + // Hide axis labels by explicitly setting one empty string as label list + m_chart->rowAxis()->setCategoryLabels(QStringList(QString())); + m_chart->columnAxis()->setCategoryLabels(QStringList(QString())); + + m_chart->activeDataProxy()->setItemLabelFormat(QStringLiteral("@valueLabel")); #else // Set selection mode to zoom row m_chart->setSelectionMode(QDataVis::ModeSliceRow); @@ -112,12 +118,17 @@ void ChartDataGenerator::start() #ifndef USE_STATIC_DATA m_dataTimer = new QTimer(); m_dataTimer->setTimerType(Qt::CoarseTimer); - m_dataTimer->setInterval(500); QObject::connect(m_dataTimer, &QTimer::timeout, this, &ChartDataGenerator::addRow); - m_dataTimer->start(500); + m_dataTimer->start(0); m_tableWidget->setFixedWidth(m_chart->width()); #else setupModel(); + // Table needs to be shown before the size of its headers can be accurately obtained, + // so we postpone it a bit + m_dataTimer = new QTimer(); + m_dataTimer->setSingleShot(true); + QObject::connect(m_dataTimer, &QTimer::timeout, this, &ChartDataGenerator::fixTableSize); + m_dataTimer->start(0); #endif } @@ -142,13 +153,14 @@ void ChartDataGenerator::setupModel() m_chart->valueAxis()->setTitle("Hours playing banjo"); m_chart->valueAxis()->setSegmentCount(5); m_chart->valueAxis()->setLabelFormat("%.1f h"); - m_chart->rowAxis()->setCategoryLabels(weeks); - m_chart->columnAxis()->setCategoryLabels(days); m_tableWidget->setRowCount(5); m_tableWidget->setColumnCount(7); m_tableWidget->setHorizontalHeaderLabels(days); m_tableWidget->setVerticalHeaderLabels(weeks); + m_tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_tableWidget->setCurrentCell(-1, -1); for (int week = 0; week < weeks.size(); week++) { for (int day = 0; day < days.size(); day++) { @@ -156,7 +168,6 @@ void ChartDataGenerator::setupModel() m_tableWidget->model()->setData(index, hours[week][day]); } } - m_tableWidget->setFixedWidth(600); // Set up sample space based on prepared data m_chart->setDataWindow(weeks.size(), days.size()); @@ -165,6 +176,8 @@ void ChartDataGenerator::setupModel() void ChartDataGenerator::addRow() { m_tableWidget->model()->insertRow(0); + if (m_tableWidget->model()->rowCount() > m_rowCount) + m_tableWidget->model()->removeRow(m_rowCount); for (int i = 0; i < m_columnCount; i++) { QModelIndex index = m_tableWidget->model()->index(0, i); m_tableWidget->model()->setData(index, @@ -179,9 +192,22 @@ void ChartDataGenerator::selectFromTable(const QPoint &selection) m_tableWidget->setCurrentCell(selection.x(), selection.y()); } -void ChartDataGenerator::selectedFromTable(int row, int column) +void ChartDataGenerator::selectedFromTable(int currentRow, int currentColumn, + int previousRow, int previousColumn) +{ + Q_UNUSED(previousRow) + Q_UNUSED(previousColumn) + m_chart->setSelectedBarPos(QPoint(currentRow, currentColumn)); +} + +void ChartDataGenerator::fixTableSize() { - m_chart->setSelectedBarPos(QPoint(row, column)); + int width = m_tableWidget->horizontalHeader()->length(); + width += m_tableWidget->verticalHeader()->width(); + m_tableWidget->setFixedWidth(width + 2); + int height = m_tableWidget->verticalHeader()->length(); + height += m_tableWidget->horizontalHeader()->height(); + m_tableWidget->setFixedHeight(height + 2); } int main(int argc, char **argv) @@ -219,7 +245,7 @@ int main(int argc, char **argv) QObject::connect(chart, &Q3DBars::selectedBarPosChanged, generator, &ChartDataGenerator::selectFromTable); - QObject::connect(tableWidget, &QTableWidget::cellClicked, generator, + QObject::connect(tableWidget, &QTableWidget::currentCellChanged, generator, &ChartDataGenerator::selectedFromTable); widget->show(); diff --git a/examples/widget/chart.cpp b/examples/widget/chart.cpp index d124a10b..534b135c 100644 --- a/examples/widget/chart.cpp +++ b/examples/widget/chart.cpp @@ -54,10 +54,8 @@ ChartModifier::ChartModifier(Q3DBars *barchart) m_temperatureAxis->setLabelFormat(QString(QStringLiteral("%d ") + celsiusString)); m_yearAxis->setTitle("Year"); - m_yearAxis->setCategoryLabels(m_years); m_monthAxis->setTitle("Month"); - m_monthAxis->setCategoryLabels(m_months); m_chart->addAxis(m_temperatureAxis); m_chart->addAxis(m_yearAxis); @@ -124,7 +122,7 @@ void ChartModifier::resetTemperatureData() } // Add data to chart (chart assumes ownership) - m_temperatureData->resetArray(dataSet); + m_temperatureData->resetArray(dataSet, m_years, m_months); } void ChartModifier::changeStyle(int style) diff --git a/src/datavisualization/axis/q3dcategoryaxis.cpp b/src/datavisualization/axis/q3dcategoryaxis.cpp index 55a27f52..90a7ff45 100644 --- a/src/datavisualization/axis/q3dcategoryaxis.cpp +++ b/src/datavisualization/axis/q3dcategoryaxis.cpp @@ -18,6 +18,8 @@ #include "q3dcategoryaxis.h" #include "q3dcategoryaxis_p.h" +#include "bars3dcontroller_p.h" +#include "qbardataproxy.h" QT_DATAVISUALIZATION_BEGIN_NAMESPACE @@ -53,7 +55,12 @@ Q3DCategoryAxis::~Q3DCategoryAxis() * \property Q3DCategoryAxis::categoryLabels * * Defines labels for axis applied to categories. If there are fewer labels than categories, the - * remaining ones do not have a label. + * remaining ones do not have a label. If category labels are not explicitly defined, labels are + * generated from the data row and column labels. + * + * \note CategoryLabels actually reads/writes the Q3DAbstractAxis::labels property, + * which is read only there. Since subclass cannot have property with same name, + * this partially duplicate property is necessary. */ QStringList Q3DCategoryAxis::categoryLabels() const { @@ -62,7 +69,24 @@ QStringList Q3DCategoryAxis::categoryLabels() const void Q3DCategoryAxis::setCategoryLabels(const QStringList &labels) { - if (d_ptr->m_labels != labels) { + dptr()->m_labelsExplicitlySet = !labels.isEmpty(); + bool labelsFromData = false; + + // Get labels from data proxy if axis is attached to a bar controller and an active axis there + if (labels.isEmpty()) { + Bars3DController *controller = qobject_cast(parent()); + if (controller) { + if (controller->axisX() == this) { + controller->handleDataRowLabelsChanged(); + labelsFromData = true; + } else if (controller->axisZ() == this) { + controller->handleDataColumnLabelsChanged(); + labelsFromData = true; + } + } + } + + if (!labelsFromData && d_ptr->m_labels != labels) { d_ptr->m_labels = labels; emit labelsChanged(); } @@ -77,7 +101,8 @@ Q3DCategoryAxisPrivate *Q3DCategoryAxis::dptr() } Q3DCategoryAxisPrivate::Q3DCategoryAxisPrivate(Q3DCategoryAxis *q) - : Q3DAbstractAxisPrivate(q, Q3DAbstractAxis::AxisTypeCategory) + : Q3DAbstractAxisPrivate(q, Q3DAbstractAxis::AxisTypeCategory), + m_labelsExplicitlySet(false) { } @@ -85,4 +110,22 @@ Q3DCategoryAxisPrivate::~Q3DCategoryAxisPrivate() { } +/*! + * \internal + * Controller uses this function to set labels from data proxy as category labels. + * If the labels have been explicitly set by user, data proxy labels are not used. + */ +void Q3DCategoryAxisPrivate::setDataLabels(const QStringList &labels) +{ + if (!m_labelsExplicitlySet && m_labels != labels) { + m_labels = labels; + emit qptr()->labelsChanged(); + } +} + +Q3DCategoryAxis *Q3DCategoryAxisPrivate::qptr() +{ + return static_cast(q_ptr); +} + QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/axis/q3dcategoryaxis.h b/src/datavisualization/axis/q3dcategoryaxis.h index 8b7f966c..bf5e66fd 100644 --- a/src/datavisualization/axis/q3dcategoryaxis.h +++ b/src/datavisualization/axis/q3dcategoryaxis.h @@ -28,9 +28,6 @@ class Q3DCategoryAxisPrivate; class QT_DATAVISUALIZATION_EXPORT Q3DCategoryAxis : public Q3DAbstractAxis { Q_OBJECT - // Note: categoryLabels actually reads/writes the labels property in abstract axis, - // which is read only there. Since subclass cannot have property with same name, - // this partially duplicate property is necessary. Q_PROPERTY(QStringList categoryLabels READ categoryLabels WRITE setCategoryLabels) public: @@ -47,6 +44,7 @@ protected: private: Q_DISABLE_COPY(Q3DCategoryAxis) + friend class Bars3DController; }; QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/axis/q3dcategoryaxis_p.h b/src/datavisualization/axis/q3dcategoryaxis_p.h index f7fa7b35..9b66e48a 100644 --- a/src/datavisualization/axis/q3dcategoryaxis_p.h +++ b/src/datavisualization/axis/q3dcategoryaxis_p.h @@ -42,6 +42,14 @@ class Q3DCategoryAxisPrivate : public Q3DAbstractAxisPrivate public: Q3DCategoryAxisPrivate(Q3DCategoryAxis *q); virtual ~Q3DCategoryAxisPrivate(); + + void setDataLabels(const QStringList &labels); + +private: + Q3DCategoryAxis *qptr(); + + bool m_labelsExplicitlySet; + friend class Q3DCategoryAxis; }; QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/baritemmodelhandler.cpp b/src/datavisualization/data/baritemmodelhandler.cpp index ec922f2b..07a802cd 100644 --- a/src/datavisualization/data/baritemmodelhandler.cpp +++ b/src/datavisualization/data/baritemmodelhandler.cpp @@ -88,7 +88,17 @@ void BarItemModelHandler::resolveModel() } } - m_proxy->resetArray(newProxyArray); + // Generate labels from headers if using model rows/columns + QStringList rowLabels; + QStringList columnLabels; + if (useModelRows) { + for (int i = 0; i < rowCount; i++) + rowLabels << m_itemModel->headerData(i, Qt::Vertical).toString(); + for (int i = 0; i < columnCount; i++) + columnLabels << m_itemModel->headerData(i, Qt::Horizontal).toString(); + } + + m_proxy->resetArray(newProxyArray, rowLabels, columnLabels); } QT_DATAVISUALIZATION_END_NAMESPACE 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 @@ -87,38 +93,83 @@ 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,13 +291,52 @@ 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 { return dptrc()->m_dataArray->size(); } +/*! + * \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. */ @@ -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(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 QBarDataProxyPrivate::limitValues(int startRow, int endRow, int startColumn, int endColumn) { QPair limits = qMakePair(0.0f, 0.0f); diff --git a/src/datavisualization/data/qbardataproxy.h b/src/datavisualization/data/qbardataproxy.h index 78f3d789..758700df 100644 --- a/src/datavisualization/data/qbardataproxy.h +++ b/src/datavisualization/data/qbardataproxy.h @@ -22,6 +22,7 @@ #include #include #include +#include QT_DATAVISUALIZATION_BEGIN_NAMESPACE @@ -35,7 +36,8 @@ class QT_DATAVISUALIZATION_EXPORT QBarDataProxy : public QAbstractDataProxy Q_OBJECT Q_PROPERTY(int rowCount READ rowCount) - + Q_PROPERTY(QStringList rowLabels READ rowLabels WRITE setRowLabels NOTIFY rowLabelsChanged) + Q_PROPERTY(QStringList columnLabels READ columnLabels WRITE setColumnLabels NOTIFY columnLabelsChanged) public: explicit QBarDataProxy(QObject *parent = 0); virtual ~QBarDataProxy(); @@ -50,14 +52,25 @@ public: */ int rowCount() const; + + QStringList rowLabels() const; + void setRowLabels(const QStringList &labels); + QStringList columnLabels() const; + void setColumnLabels(const QStringList &labels); + const QBarDataArray *array() const; const QBarDataRow *rowAt(int rowIndex) const; const QBarDataItem *itemAt(int rowIndex, int columnIndex) const; + void resetArray(); void resetArray(QBarDataArray *newArray); + void resetArray(QBarDataArray *newArray, const QStringList &rowLabels, + const QStringList &columnLabels); void setRow(int rowIndex, QBarDataRow *row); + void setRow(int rowIndex, QBarDataRow *row, const QString &label); void setRows(int rowIndex, const QBarDataArray &rows); + void setRows(int rowIndex, const QBarDataArray &rows, const QStringList &labels); // Setting a column is comparatively inefficient as it changes all rows. // Can resize rows that are shorter than columnIndex. @@ -69,16 +82,20 @@ public: // TODO setItems(int rowIndex, int columnIndex, QBarDataArray *items); int addRow(QBarDataRow *row); + int addRow(QBarDataRow *row, const QString &label); int addRows(const QBarDataArray &rows); + int addRows(const QBarDataArray &rows, const QStringList &labels); // TODO int addColumn(const QBarDataRow &column); // returns the index of the added column // TODO int addColumns(const QBarDataArray &columns); // returns the index of the first added column void insertRow(int rowIndex, QBarDataRow *row); + void insertRow(int rowIndex, QBarDataRow *row, const QString &label); void insertRows(int rowIndex, const QBarDataArray &rows); + void insertRows(int rowIndex, const QBarDataArray &rows, const QStringList &labels); // TODO void insertColumn(int columnIndex, const QBarDataRow &column); // TODO void insertColumns(int columnIndex, const QBarDataArray &columns); - void removeRows(int rowIndex, int removeCount); + void removeRows(int rowIndex, int removeCount, bool removeLabels = true); // TODO void removeColumns(int columnIndex, int removeCount); signals: @@ -94,6 +111,9 @@ signals: void itemChanged(int rowIndex, int columnIndex); // TODO remove once itemsChanged is added? // TODO void itemsChanged(int rowIndex, int columnIndex, int rowCount, int columnCount); + void rowLabelsChanged(); + void columnLabelsChanged(); + protected: explicit QBarDataProxy(QBarDataProxyPrivate *d, QObject *parent = 0); QBarDataProxyPrivate *dptr(); diff --git a/src/datavisualization/data/qbardataproxy_p.h b/src/datavisualization/data/qbardataproxy_p.h index ab64c4a1..6aa9d2cb 100644 --- a/src/datavisualization/data/qbardataproxy_p.h +++ b/src/datavisualization/data/qbardataproxy_p.h @@ -42,23 +42,29 @@ public: QBarDataProxyPrivate(QBarDataProxy *q); virtual ~QBarDataProxyPrivate(); - bool resetArray(QBarDataArray *newArray); - void setRow(int rowIndex, QBarDataRow *row); - void setRows(int rowIndex, const QBarDataArray &rows); + bool resetArray(QBarDataArray *newArray, const QStringList *rowLabels, + const QStringList *columnLabels); + void setRow(int rowIndex, QBarDataRow *row, const QString *label); + void setRows(int rowIndex, const QBarDataArray &rows, const QStringList *labels); void setItem(int rowIndex, int columnIndex, const QBarDataItem &item); - int addRow(QBarDataRow *row); - int addRows(const QBarDataArray &rows); - void insertRow(int rowIndex, QBarDataRow *row); - void insertRows(int rowIndex, const QBarDataArray &rows); - void removeRows(int rowIndex, int removeCount); + int addRow(QBarDataRow *row, const QString *label); + int addRows(const QBarDataArray &rows, const QStringList *labels); + void insertRow(int rowIndex, QBarDataRow *row, const QString *label); + void insertRows(int rowIndex, const QBarDataArray &rows, const QStringList *labels); + void removeRows(int rowIndex, int removeCount, bool removeLabels); - QPair limitValues(int startRow, int startColumn, int rowCount, int columnCount); + QPair limitValues(int startRow, int startColumn, int rowCount, + int columnCount); private: + QBarDataProxy *qptr(); void clearRow(int rowIndex); void clearArray(); + void fixRowLabels(int startIndex, int count, const QStringList &newLabels, bool isInsert); QBarDataArray *m_dataArray; + QStringList m_rowLabels; + QStringList m_columnLabels; private: friend class QBarDataProxy; diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h index 1419c0f4..c406f087 100644 --- a/src/datavisualization/engine/abstract3dcontroller_p.h +++ b/src/datavisualization/engine/abstract3dcontroller_p.h @@ -176,7 +176,7 @@ protected: bool m_renderPending; explicit Abstract3DController(QRect boundRect, QObject *parent = 0); - ~Abstract3DController(); + virtual ~Abstract3DController(); public: diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h index 1edca798..49a40209 100644 --- a/src/datavisualization/engine/abstract3drenderer_p.h +++ b/src/datavisualization/engine/abstract3drenderer_p.h @@ -86,7 +86,7 @@ protected: QString generateValueLabel(const QString &format, qreal value); public: - ~Abstract3DRenderer(); + virtual ~Abstract3DRenderer(); void updateDataModel(QAbstractDataProxy *dataProxy); diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp index 90987fc5..1f4d44c0 100644 --- a/src/datavisualization/engine/bars3dcontroller.cpp +++ b/src/datavisualization/engine/bars3dcontroller.cpp @@ -21,7 +21,7 @@ #include "camerahelper_p.h" #include "q3dabstractaxis_p.h" #include "q3dvalueaxis_p.h" -#include "q3dcategoryaxis.h" +#include "q3dcategoryaxis_p.h" #include "qbardataproxy_p.h" #include @@ -128,11 +128,18 @@ void Bars3DController::setActiveDataProxy(QAbstractDataProxy *proxy) &Bars3DController::handleRowsInserted); QObject::connect(barDataProxy, &QBarDataProxy::itemChanged, this, &Bars3DController::handleItemChanged); + QObject::connect(barDataProxy, &QBarDataProxy::rowLabelsChanged, this, + &Bars3DController::handleDataRowLabelsChanged); + QObject::connect(barDataProxy, &QBarDataProxy::columnLabelsChanged, this, + &Bars3DController::handleDataColumnLabelsChanged); adjustValueAxisRange(); // Always clear selection on proxy change setSelectedBarPos(noSelectionPoint()); + + handleDataRowLabelsChanged(); + handleDataColumnLabelsChanged(); } void Bars3DController::handleArrayReset() @@ -209,6 +216,26 @@ void Bars3DController::handleItemChanged(int rowIndex, int columnIndex) emitNeedRender(); } +void Bars3DController::handleDataRowLabelsChanged() +{ + if (m_axisX && m_data) { + // Grab a sublist equal to data window (no need to have more labels in axis) + // TODO once axis controls data window, this needs to change + QStringList subList = static_cast(m_data)->rowLabels().mid(0, m_rowCount); + static_cast(m_axisX)->dptr()->setDataLabels(subList); + } +} + +void Bars3DController::handleDataColumnLabelsChanged() +{ + if (m_axisZ && m_data) { + // Grab a sublist equal to data window (no need to have more labels in axis) + // TODO once axis controls data window, this needs to change + QStringList subList = static_cast(m_data)->columnLabels().mid(0, m_columnCount); + static_cast(m_axisZ)->dptr()->setDataLabels(subList); + } +} + void Bars3DController::handleSelectedBarPosChanged(const QPoint &position) { QPoint pos = position; @@ -235,6 +262,18 @@ QPoint Bars3DController::noSelectionPoint() return noSelectionPos; } +void Bars3DController::setAxisX(Q3DAbstractAxis *axis) +{ + Abstract3DController::setAxisX(axis); + handleDataRowLabelsChanged(); +} + +void Bars3DController::setAxisZ(Q3DAbstractAxis *axis) +{ + Abstract3DController::setAxisZ(axis); + handleDataColumnLabelsChanged(); +} + void Bars3DController::setBarSpecs(GLfloat thicknessRatio, const QSizeF &spacing, bool relative) { m_barThicknessRatio = thicknessRatio; @@ -296,6 +335,10 @@ void Bars3DController::setDataWindow(int rowCount, int columnCount) m_changeTracker.sampleSpaceChanged = true; m_isDataDirty = true; // Render item array is recreated in renderer + + handleDataRowLabelsChanged(); + handleDataColumnLabelsChanged(); + emitNeedRender(); } diff --git a/src/datavisualization/engine/bars3dcontroller_p.h b/src/datavisualization/engine/bars3dcontroller_p.h index 69ead98a..6dbaf742 100644 --- a/src/datavisualization/engine/bars3dcontroller_p.h +++ b/src/datavisualization/engine/bars3dcontroller_p.h @@ -114,6 +114,9 @@ public: static QPoint noSelectionPoint(); + virtual void setAxisX(Q3DAbstractAxis *axis); + virtual void setAxisZ(Q3DAbstractAxis *axis); + public slots: void handleArrayReset(); void handleRowsAdded(int startIndex, int count); @@ -121,6 +124,8 @@ public slots: void handleRowsRemoved(int startIndex, int count); void handleRowsInserted(int startIndex, int count); void handleItemChanged(int rowIndex, int columnIndex); + void handleDataRowLabelsChanged(); + void handleDataColumnLabelsChanged(); void handleSelectedBarPosChanged(const QPoint &position); diff --git a/src/datavisualization/engine/q3dscene.cpp b/src/datavisualization/engine/q3dscene.cpp index 49c08bbc..b39daab6 100644 --- a/src/datavisualization/engine/q3dscene.cpp +++ b/src/datavisualization/engine/q3dscene.cpp @@ -28,6 +28,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE Q3DScene::Q3DScene(QObject *parent) : + QObject(parent), d_ptr(new Q3DScenePrivate(this)) { } diff --git a/src/datavisualization/engine/q3dwindow.h b/src/datavisualization/engine/q3dwindow.h index 4a76c677..c46e293a 100644 --- a/src/datavisualization/engine/q3dwindow.h +++ b/src/datavisualization/engine/q3dwindow.h @@ -36,7 +36,7 @@ class QT_DATAVISUALIZATION_EXPORT Q3DWindow : public QWindow, protected QOpenGLF public: explicit Q3DWindow(QWindow *parent = 0); - ~Q3DWindow(); + virtual ~Q3DWindow(); protected slots: void renderLater(); diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index f39a0228..55fb9d6f 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -232,7 +232,6 @@ void Surface3DRenderer::updateScene(Q3DScene *scene) void Surface3DRenderer::render(GLuint defaultFboHandle) { m_cachedScene->setUnderSideCameraEnabled(m_hasNegativeValues); - Q3DCamera *camera = m_cachedScene->camera(); if (defaultFboHandle) { glDepthMask(true); glEnable(GL_DEPTH_TEST); diff --git a/tests/barstest/chart.cpp b/tests/barstest/chart.cpp index 08ce4d94..e2d4bda4 100644 --- a/tests/barstest/chart.cpp +++ b/tests/barstest/chart.cpp @@ -53,16 +53,8 @@ ChartModifier::ChartModifier(Q3DBars *barchart) m_genericData(new QBarDataProxy), m_currentAxis(m_fixedRangeAxis) { - // Don't set any styles or specifications, start from defaults // Generate generic labels - QStringList genericRowLabels; QStringList genericColumnLabels; - for (int i = 0; i < 200; i++) { - if (i % 5) - genericRowLabels << QString(); - else - genericRowLabels << QStringLiteral("Row %1").arg(i); - } for (int i = 0; i < 200; i++) { if (i % 5) genericColumnLabels << QString(); @@ -89,7 +81,6 @@ ChartModifier::ChartModifier(Q3DBars *barchart) m_fixedRangeAxis->setRange(0.0, 100.0); m_genericRowAxis->setTitle("Generic Row"); - m_genericRowAxis->setCategoryLabels(genericRowLabels); m_genericColumnAxis->setTitle("Generic Column"); m_genericColumnAxis->setCategoryLabels(genericColumnLabels); @@ -101,10 +92,8 @@ ChartModifier::ChartModifier(Q3DBars *barchart) m_temperatureAxis->setLabelFormat(QString(QStringLiteral("%d ") + celsiusString)); m_yearAxis->setTitle("Year"); - m_yearAxis->setCategoryLabels(m_years); m_monthAxis->setTitle("Month"); - m_monthAxis->setCategoryLabels(m_months); m_chart->addAxis(m_autoAdjustingAxis); m_chart->addAxis(m_fixedRangeAxis); @@ -249,38 +238,71 @@ void ChartModifier::resetTemperatureData() // Add data to chart (chart assumes ownership) - m_temperatureData->resetArray(dataSet); + m_temperatureData->resetArray(dataSet, m_years, m_months); } + +static int addCounter = 0; +static int insertCounter = 0; +static int changeCounter = 0; + void ChartModifier::addRow() { QBarDataRow *dataRow = new QBarDataRow(m_columnCount); - for (float i = 0; i < m_columnCount; i++) { + for (float i = 0; i < m_columnCount; i++) (*dataRow)[i].setValue(((i + 1) / (float)m_columnCount) * (float)(rand() % 100)); - //(*dataRow)[i].setValue(i + m_chart->dataProxy()->rowCount()); + + // TODO Needs to be changed to account for data window offset once it is implemented. + QString label = QStringLiteral("Add %1").arg(addCounter++); + m_chart->activeDataProxy()->addRow(dataRow, label); +} + +void ChartModifier::addRows() +{ + QBarDataArray dataArray; + QStringList labels; + for (int i = 0; i < m_rowCount; i++) { + QBarDataRow *dataRow = new QBarDataRow(m_columnCount); + for (int j = 0; j < m_columnCount; j++) + (*dataRow)[j].setValue(qreal(j + i + m_chart->activeDataProxy()->rowCount())); + dataArray.append(dataRow); + labels.append(QStringLiteral("Add %1").arg(addCounter++)); } + // TODO Needs to be changed to account for data window offset once it is implemented. + m_chart->activeDataProxy()->addRows(dataArray, labels); +} + +void ChartModifier::insertRow() +{ + QBarDataRow *dataRow = new QBarDataRow(m_columnCount); + for (float i = 0; i < m_columnCount; i++) + (*dataRow)[i].setValue(((i + 1) / (float)m_columnCount) * (float)(rand() % 100)); + // TODO Needs to be changed to account for data window offset once it is implemented. int row = qMax(m_selectedBarPos.x(), 0); - m_chart->activeDataProxy()->insertRow(row, dataRow); + QString label = QStringLiteral("Insert %1").arg(insertCounter++); + m_chart->activeDataProxy()->insertRow(row, dataRow, label); } -void ChartModifier::addRows() +void ChartModifier::insertRows() { QTime timer; timer.start(); QBarDataArray dataArray; + QStringList labels; for (int i = 0; i < m_rowCount; i++) { QBarDataRow *dataRow = new QBarDataRow(m_columnCount); for (int j = 0; j < m_columnCount; j++) (*dataRow)[j].setValue(qreal(j + i + m_chart->activeDataProxy()->rowCount())); dataArray.append(dataRow); + labels.append(QStringLiteral("Insert %1").arg(insertCounter++)); } // TODO Needs to be changed to account for data window offset once it is implemented. int row = qMax(m_selectedBarPos.x(), 0); - m_chart->activeDataProxy()->insertRows(row, dataArray); - qDebug() << "Added" << m_rowCount << "rows, time:" << timer.elapsed(); + m_chart->activeDataProxy()->insertRows(row, dataArray, labels); + qDebug() << "Inserted" << m_rowCount << "rows, time:" << timer.elapsed(); } void ChartModifier::changeItem() @@ -302,7 +324,8 @@ void ChartModifier::changeRow() QBarDataRow *newRow = new QBarDataRow(m_chart->activeDataProxy()->rowAt(row)->size()); for (int i = 0; i < newRow->size(); i++) (*newRow)[i].setValue(qreal(rand() % 100)); - m_chart->activeDataProxy()->setRow(row, newRow); + QString label = QStringLiteral("Change %1").arg(changeCounter++); + m_chart->activeDataProxy()->setRow(row, newRow, label); } } @@ -313,13 +336,15 @@ void ChartModifier::changeRows() if (row >= 0) { int startRow = qMax(row - 2, 0); QBarDataArray newArray; + QStringList labels; for (int i = startRow; i <= row; i++ ) { QBarDataRow *newRow = new QBarDataRow(m_chart->activeDataProxy()->rowAt(i)->size()); for (int j = 0; j < newRow->size(); j++) (*newRow)[j].setValue(qreal(rand() % 100)); newArray.append(newRow); + labels.append(QStringLiteral("Change %1").arg(changeCounter++)); } - m_chart->activeDataProxy()->setRows(startRow, newArray); + m_chart->activeDataProxy()->setRows(startRow, newArray, labels); } } diff --git a/tests/barstest/chart.h b/tests/barstest/chart.h index bd601021..fcd861b7 100644 --- a/tests/barstest/chart.h +++ b/tests/barstest/chart.h @@ -38,6 +38,8 @@ public: void resetTemperatureData(); void addRow(); void addRows(); + void insertRow(); + void insertRows(); void changeItem(); void changeRow(); void changeRows(); diff --git a/tests/barstest/main.cpp b/tests/barstest/main.cpp index b5225d4c..39341471 100644 --- a/tests/barstest/main.cpp +++ b/tests/barstest/main.cpp @@ -54,13 +54,21 @@ int main(int argc, char **argv) hLayout->addLayout(vLayout); hLayout->addLayout(vLayout2); - QPushButton *dataButton = new QPushButton(widget); - dataButton->setText(QStringLiteral("Insert a row of data")); - dataButton->setEnabled(false); + QPushButton *addDataButton = new QPushButton(widget); + addDataButton->setText(QStringLiteral("Add a row of data")); + addDataButton->setEnabled(false); - QPushButton *multiDataButton = new QPushButton(widget); - multiDataButton->setText(QStringLiteral("Insert many rows of data")); - multiDataButton->setEnabled(false); + QPushButton *addMultiDataButton = new QPushButton(widget); + addMultiDataButton->setText(QStringLiteral("Add many rows of data")); + addMultiDataButton->setEnabled(false); + + QPushButton *insertDataButton = new QPushButton(widget); + insertDataButton->setText(QStringLiteral("Insert a row of data")); + insertDataButton->setEnabled(false); + + QPushButton *insertMultiDataButton = new QPushButton(widget); + insertMultiDataButton->setText(QStringLiteral("Insert many rows of data")); + insertMultiDataButton->setEnabled(false); QPushButton *changeSingleDataButton = new QPushButton(widget); changeSingleDataButton->setText(QStringLiteral("Change selected bar value")); @@ -188,8 +196,10 @@ int main(int argc, char **argv) shadowQuality->addItem(QStringLiteral("High Soft")); shadowQuality->setCurrentIndex(5); - vLayout->addWidget(dataButton, 0, Qt::AlignTop); - vLayout->addWidget(multiDataButton, 0, Qt::AlignTop); + vLayout->addWidget(addDataButton, 0, Qt::AlignTop); + vLayout->addWidget(addMultiDataButton, 0, Qt::AlignTop); + vLayout->addWidget(insertDataButton, 0, Qt::AlignTop); + vLayout->addWidget(insertMultiDataButton, 0, Qt::AlignTop); vLayout->addWidget(changeSingleDataButton, 0, Qt::AlignTop); vLayout->addWidget(changeRowButton, 0, Qt::AlignTop); vLayout->addWidget(changeRowsButton, 0, Qt::AlignTop); @@ -264,8 +274,10 @@ int main(int argc, char **argv) QObject::connect(themeButton, &QPushButton::clicked, modifier, &ChartModifier::changeTheme); QObject::connect(labelButton, &QPushButton::clicked, modifier, &ChartModifier::changeTransparency); - QObject::connect(dataButton, &QPushButton::clicked, modifier, &ChartModifier::addRow); - QObject::connect(multiDataButton, &QPushButton::clicked, modifier, &ChartModifier::addRows); + QObject::connect(addDataButton, &QPushButton::clicked, modifier, &ChartModifier::addRow); + QObject::connect(addMultiDataButton, &QPushButton::clicked, modifier, &ChartModifier::addRows); + QObject::connect(insertDataButton, &QPushButton::clicked, modifier, &ChartModifier::insertRow); + QObject::connect(insertMultiDataButton, &QPushButton::clicked, modifier, &ChartModifier::insertRows); QObject::connect(changeSingleDataButton, &QPushButton::clicked, modifier, &ChartModifier::changeItem); QObject::connect(changeRowButton, &QPushButton::clicked, modifier, &ChartModifier::changeRow); QObject::connect(changeRowsButton, &QPushButton::clicked, modifier, &ChartModifier::changeRows); @@ -299,9 +311,13 @@ int main(int argc, char **argv) QObject::connect(rotationCheckBox, &QCheckBox::stateChanged, rotationSliderY, &QSlider::setValue); - QObject::connect(staticCheckBox, &QCheckBox::stateChanged, dataButton, + QObject::connect(staticCheckBox, &QCheckBox::stateChanged, addDataButton, + &QPushButton::setEnabled); + QObject::connect(staticCheckBox, &QCheckBox::stateChanged, addMultiDataButton, + &QPushButton::setEnabled); + QObject::connect(staticCheckBox, &QCheckBox::stateChanged, insertDataButton, &QPushButton::setEnabled); - QObject::connect(staticCheckBox, &QCheckBox::stateChanged, multiDataButton, + QObject::connect(staticCheckBox, &QCheckBox::stateChanged, insertMultiDataButton, &QPushButton::setEnabled); QObject::connect(staticCheckBox, &QCheckBox::stateChanged, changeSingleDataButton, &QPushButton::setEnabled); -- cgit v1.2.3