diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-07-05 11:34:47 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-07-05 12:52:57 +0300 |
commit | 03276f3187bc58162e335b9a5739c1631344fa84 (patch) | |
tree | d491698251a0320fd2f8eadf8cd262211baebb59 | |
parent | 0963cf7feda67225700f4291264e68c9060046f6 (diff) |
Miscellaneous fixes
- Widget example now uses default QBarDataProxy directly
- Axes store labels in QStringLists instead of vectors
- Axes LabelItems as QList<LabelItem *> instead of QVector<LabelItem>
This allows better control of when label items are constructed
and destructed -> easier to keep track of textures.
- Removed label setting from QAbstractDataItem api, it should be
replaced with label format setter if we want individual items
to have custom labels.
- Added functionality to QBarDataItem
- Misc bug fixes
Change-Id: I01b3a5f3fc4acb8c1a826f19fa2762864430a088
Reviewed-by: Mika Salmela <mika.salmela@digia.com>
27 files changed, 323 insertions, 213 deletions
diff --git a/examples/barchart/main.cpp b/examples/barchart/main.cpp index caa5b9dc..040be325 100644 --- a/examples/barchart/main.cpp +++ b/examples/barchart/main.cpp @@ -94,7 +94,7 @@ ChartDataGenerator::ChartDataGenerator(Q3DBars *barchart) #ifndef USE_STATIC_DATA // Set up sample space; make it as deep as it's wide - m_chart->setupSampleSpace(m_columnCount, m_rowCount); + m_chart->setupSampleSpace(m_rowCount, m_columnCount); #endif // Set bar type to smooth bar @@ -201,7 +201,7 @@ void ChartDataGenerator::addDataSet() row.clear(); } // Set up sample space based on inserted data - m_chart->setupSampleSpace(m_columnCount, m_rowCount); + m_chart->setupSampleSpace(m_rowCount, m_columnCount); // Add data to chart m_chart->addDataSet(data); #else @@ -212,9 +212,9 @@ void ChartDataGenerator::addDataSet() m_chart->setWindowTitle(QStringLiteral("Hours playing banjo")); // Set up row and column names - QVector<QString> days; + QStringList days; days << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday" << "Saturday" << "Sunday"; - QVector<QString> weeks; + QStringList weeks; weeks << "week 1" << "week 2" << "week 3" << "week 4" << "week 5"; // Set up data Mon Tue Wed Thu Fri Sat Sun @@ -253,7 +253,7 @@ void ChartDataGenerator::addDataSet() } // Set up sample space based on prepared data - m_chart->setupSampleSpace(days.size(), weeks.size()); + m_chart->setupSampleSpace(weeks.size(), days.size()); // Add data to chart static_cast<QOldDataProxy *>(m_chart->dataProxy())->addDataSet(dataSet); diff --git a/examples/qmlbarchart/qml/qmlbarchart/main.qml b/examples/qmlbarchart/qml/qmlbarchart/main.qml index 28b3326d..748a5241 100644 --- a/examples/qmlbarchart/qml/qmlbarchart/main.qml +++ b/examples/qmlbarchart/qml/qmlbarchart/main.qml @@ -125,7 +125,7 @@ Item { testset1.addRow(testrow1); testset1.addRow(testrow2); - testchart.setupSampleSpace(4, 2); + testchart.setupSampleSpace(2, 4); testchart.addDataSet(testset1); } diff --git a/examples/rainfall/main.cpp b/examples/rainfall/main.cpp index 46757e46..be1b120f 100644 --- a/examples/rainfall/main.cpp +++ b/examples/rainfall/main.cpp @@ -74,12 +74,12 @@ RainfallChart::RainfallChart(Q3DBars *rainfall) m_chart->setBarSpecs(QSizeF(1.0f, 1.0f), QSizeF(0.2f, 0.2f), true); // Set up sample space; make it match actual data size - m_chart->setupSampleSpace(m_columnCount, m_rowCount); + m_chart->setupSampleSpace(m_rowCount, m_columnCount); // Set axis labels and titles - QVector<QString> months; + QStringList months; months << "January" << "February" << "March" << "April" << "May" << "June" << "July" << "August" << "September" << "October" << "November" << "December"; - QVector<QString> years; + QStringList years; years << "2000" << "2001" << "2002" << "2003" << "2004" << "2005" << "2006" << "2007" << "2008" << "2009" << "2010" << "2011" << "2012"; m_chart->rowAxis()->setTitle("Year"); diff --git a/examples/spectrum/spectrumapp/main.cpp b/examples/spectrum/spectrumapp/main.cpp index 19f195fa..2fa0be8f 100644 --- a/examples/spectrum/spectrumapp/main.cpp +++ b/examples/spectrum/spectrumapp/main.cpp @@ -86,7 +86,7 @@ MainApp::MainApp(Q3DBars *window) m_lowFreq(SpectrumLowFreq), m_highFreq(SpectrumHighFreq) { - m_chart->setupSampleSpace(SpectrumNumBands, SpectrumNumBands * 2); + m_chart->setupSampleSpace(SpectrumNumBands * 2, SpectrumNumBands); // Disable grid m_chart->setGridVisible(false); // Disable auto-scaling of height by defining tick count and step, even though we don't draw grid diff --git a/examples/widget/chart.cpp b/examples/widget/chart.cpp index 00cdd3c3..f2928f7b 100644 --- a/examples/widget/chart.cpp +++ b/examples/widget/chart.cpp @@ -41,9 +41,9 @@ #include "chart.h" #include "qcategoryaxis.h" #include "qvalueaxis.h" -#include "qolddataproxy.h" +#include "qbardataproxy.h" -using namespace QtDataVis3D; +QT_DATAVIS3D_USE_NAMESPACE const QString celsiusString = QString(QChar(0xB0)) + "C"; @@ -64,6 +64,12 @@ ChartModifier::ChartModifier(Q3DBars *barchart) m_minval(-15.2f) { // Don't set any styles or specifications, start from defaults + // Generate generic labels + for (int i = 0; i < m_rowCount; i++) + m_genericRowLabels << QStringLiteral("Row %1").arg(i); + for (int i = 0; i < m_columnCount; i++) + m_genericColumnLabels << QStringLiteral("Column %1").arg(i); + } ChartModifier::~ChartModifier() @@ -88,12 +94,20 @@ void ChartModifier::restart(bool dynamicData) m_chart->setFont(QFont("Times Roman", 20)); m_chart->setTickCount(m_ticks, m_tickStep, m_minval); } else { + m_chart->dataProxy()->resetArray(0, 0); // Set up sample space - m_chart->setupSampleSpace(m_columnCount, m_rowCount); + m_chart->setupSampleSpace(m_rowCount, m_columnCount); // Set selection mode to full m_chart->setSelectionMode(ModeBarRowAndColumn); // Reset tick count to default m_chart->setTickCount(0, 0); + + m_chart->rowAxis()->setTitle("Generic Row"); + m_chart->columnAxis()->setTitle("Generic Column"); + m_chart->valueAxis()->setTitle("Generic Value"); + + m_chart->rowAxis()->setLabels(QStringList()); + m_chart->columnAxis()->setLabels(m_genericColumnLabels); } } @@ -106,9 +120,9 @@ void ChartModifier::addDataSet() m_chart->setWindowTitle(QStringLiteral("Average temperatures in Oulu, Finland (2006-2012)")); // Set up row and column names - QVector<QString> months; + QStringList months; months << "January" << "February" << "March" << "April" << "May" << "June" << "July" << "August" << "September" << "October" << "November" << "December"; - QVector<QString> years; + QStringList years; years << "2006" << "2007" << "2008" << "2009" << "2010" << "2011" << "2012"; // Set up data @@ -120,8 +134,9 @@ void ChartModifier::addDataSet() {-9.0f, -15.2f, -3.8f, 2.6f, 8.3f, 15.9f, 18.6f, 14.9f, 11.1f, 5.3f, 1.8f, -0.2f}, // 2011 {-8.7f, -11.3f, -2.3f, 0.4f, 7.5f, 12.2f, 16.4f, 14.1f, 9.2f, 3.1f, 0.3f, -12.1f}}; // 2012 - // Create data set - QDataSet *dataSet = new QDataSet(); + // Use default data proxy to feed data directly in expected format + QBarDataProxy *proxy = m_chart->dataProxy(); + proxy->setItemLabelFormat(celsiusString); // Add labels m_chart->rowAxis()->setTitle("Year"); @@ -131,18 +146,19 @@ void ChartModifier::addDataSet() m_chart->columnAxis()->setLabels(months); // Create data rows - QDataRow *dataRow; + QBarDataArray *dataSet = new QBarDataArray; + QBarDataRow *dataRow; + + dataSet->reserve(years.size()); for (int year = 0; year < years.size(); year++) { - dataRow = new QDataRow(); + dataRow = new QBarDataRow; // Create data items for (int month = 0; month < months.size(); month++) { // Add data to rows - dataRow->addItem(new QDataItem(temp[year][month], celsiusString)); + dataRow->append(new QBarDataItem(temp[year][month])); } // Add row to set - dataSet->addRow(dataRow); - // Get next pointer - dataRow++; + dataSet->append(dataRow); } // Set tick count (4 steps of 5 degrees, with absolute minimum of -16C, even though we don't have quite that low temperatures in the data) @@ -151,20 +167,21 @@ void ChartModifier::addDataSet() m_chart->setTickCount(m_ticks, m_tickStep, m_minval); // Set up sample space based on prepared data - m_chart->setupSampleSpace(months.size(), years.size()); + m_chart->setupSampleSpace(years.size(), months.size()); - QOldDataProxy *proxy = new QOldDataProxy; - m_chart->setDataProxy(proxy); - // Add data to chart - static_cast<QOldDataProxy *>(m_chart->dataProxy())->addDataSet(dataSet); + // Add data to chart (chart assumes ownership) + proxy->resetArray(dataSet); } void ChartModifier::addBars() { - QVector<float> data; + QBarDataRow *dataRow = new QBarDataRow; for (float i = 0; i < m_columnCount; i++) - data.append(((i + 1) / (float)m_columnCount) * (float)(rand() % 100)); - static_cast<QOldDataProxy *>(m_chart->dataProxy())->addDataRow(data); + dataRow->append(new QBarDataItem(i + m_chart->dataProxy()->rowCount())); + //dataRow->append(new QBarDataItem(((i + 1) / (float)m_columnCount) * (float)(rand() % 100))); + m_chart->dataProxy()->insertRow(0, dataRow); + if (m_chart->dataProxy()->rowCount() <= m_rowCount) + m_chart->rowAxis()->setLabels(m_genericRowLabels.mid(0, m_chart->dataProxy()->rowCount())); } void ChartModifier::changeStyle() @@ -347,11 +364,11 @@ void ChartModifier::setSpacingSpecsZ(int spacing) void ChartModifier::setSampleCountX(int samples) { m_columnCount = samples; - m_chart->setupSampleSpace(m_columnCount, m_rowCount); + m_chart->setupSampleSpace(m_rowCount, m_columnCount); } void ChartModifier::setSampleCountZ(int samples) { m_rowCount = samples; - m_chart->setupSampleSpace(m_columnCount, m_rowCount); + m_chart->setupSampleSpace(m_rowCount, m_columnCount); } diff --git a/examples/widget/chart.h b/examples/widget/chart.h index 20748564..3c943588 100644 --- a/examples/widget/chart.h +++ b/examples/widget/chart.h @@ -42,10 +42,10 @@ #define CHARTMODIFIER_H #include "q3dbars.h" -#include "qdataset.h" #include <QFont> #include <QDebug> +#include <QStringList> using namespace QtDataVis3D; @@ -100,6 +100,8 @@ private: int m_ticks; float m_tickStep; float m_minval; + QStringList m_genericRowLabels; + QStringList m_genericColumnLabels; }; #endif diff --git a/src/datavis3d/axis/qabstractaxis.cpp b/src/datavis3d/axis/qabstractaxis.cpp index eb47542e..4b3de4ff 100644 --- a/src/datavis3d/axis/qabstractaxis.cpp +++ b/src/datavis3d/axis/qabstractaxis.cpp @@ -59,7 +59,7 @@ QString QAbstractAxis::title() const return d_ptr->m_title; } -QVector<QString> &QAbstractAxis::labels() const +QStringList &QAbstractAxis::labels() const { return d_ptr->m_labels; } @@ -100,7 +100,7 @@ QAbstractAxisPrivate::~QAbstractAxisPrivate() { m_titleItem.clear(); for (int i = 0; i < m_labelItems.size(); i++) - m_labelItems[i].clear(); + delete m_labelItems[i]; } void QAbstractAxisPrivate::setDrawer(Drawer *drawer) diff --git a/src/datavis3d/axis/qabstractaxis.h b/src/datavis3d/axis/qabstractaxis.h index 398643b1..a5dd6951 100644 --- a/src/datavis3d/axis/qabstractaxis.h +++ b/src/datavis3d/axis/qabstractaxis.h @@ -46,6 +46,7 @@ #include <QObject> #include <QScopedPointer> #include <QVector> +#include <QStringList> QT_DATAVIS3D_BEGIN_NAMESPACE @@ -81,7 +82,7 @@ public: virtual ~QAbstractAxis(); QString title() const; - QVector<QString> &labels() const; + QStringList &labels() const; AxisOrientation orientation() const; AxisType type() const; diff --git a/src/datavis3d/axis/qabstractaxis_p.h b/src/datavis3d/axis/qabstractaxis_p.h index 7d64c957..5319fc6e 100644 --- a/src/datavis3d/axis/qabstractaxis_p.h +++ b/src/datavis3d/axis/qabstractaxis_p.h @@ -66,7 +66,7 @@ public: virtual ~QAbstractAxisPrivate(); void setDrawer(Drawer *drawer); - QVector<LabelItem> &labelItems() { return m_labelItems; } + QList<LabelItem *> &labelItems() { return m_labelItems; } LabelItem &titleItem() { return m_titleItem; } void setOrientation(QAbstractAxis::AxisOrientation orientation); @@ -83,8 +83,8 @@ protected: // TODO: Replace Drawer with AbstractRenderer? LabelItem m_titleItem; Drawer *m_drawer; // not owned - QVector<QString> m_labels; - QVector<LabelItem> m_labelItems; + QStringList m_labels; + QList<LabelItem *> m_labelItems; QAbstractAxis::AxisOrientation m_orientation; QAbstractAxis::AxisType m_type; diff --git a/src/datavis3d/axis/qcategoryaxis.cpp b/src/datavis3d/axis/qcategoryaxis.cpp index 346e0685..d268c98b 100644 --- a/src/datavis3d/axis/qcategoryaxis.cpp +++ b/src/datavis3d/axis/qcategoryaxis.cpp @@ -53,20 +53,22 @@ QCategoryAxis::~QCategoryAxis() { } -void QCategoryAxis::setLabels(const QVector<QString> &labels) +void QCategoryAxis::setLabels(const QStringList &labels) { int newSize(labels.size()); int oldSize(d_ptr->m_labels.size()); - for (int i = oldSize - 1; i >= newSize; i--) - d_ptr->m_labelItems[i].clear(); + for (int i = newSize; i < oldSize; i++) + delete d_ptr->m_labelItems.takeLast(); - d_ptr->m_labelItems.resize(newSize); + d_ptr->m_labelItems.reserve(newSize); if (d_ptr->m_drawer) { for (int i = 0; i < newSize; i++) { + if (i >= oldSize) + d_ptr->m_labelItems.append(new LabelItem); if (i >= oldSize || labels.at(i) != d_ptr->m_labels.at(i)) - d_ptr->m_drawer->generateLabelItem(d_ptr->m_labelItems[i], labels.at(i)); + d_ptr->m_drawer->generateLabelItem(*d_ptr->m_labelItems[i], labels.at(i)); } } @@ -90,7 +92,7 @@ QCategoryAxisPrivate::~QCategoryAxisPrivate() void QCategoryAxisPrivate::updateLabels() { for (int i = 0; i < m_labels.size(); i++) - m_drawer->generateLabelItem(m_labelItems[i], m_labels.at(i)); + m_drawer->generateLabelItem(*m_labelItems[i], m_labels.at(i)); } QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qcategoryaxis.h b/src/datavis3d/axis/qcategoryaxis.h index 6d7c8ce3..ae0d2ee8 100644 --- a/src/datavis3d/axis/qcategoryaxis.h +++ b/src/datavis3d/axis/qcategoryaxis.h @@ -55,7 +55,7 @@ public: explicit QCategoryAxis(); ~QCategoryAxis(); - void setLabels(const QVector<QString> &labels); + void setLabels(const QStringList &labels); protected: QCategoryAxisPrivate *dptr(); diff --git a/src/datavis3d/data/labelitem_p.h b/src/datavis3d/data/labelitem_p.h index 4d80642a..32ae305b 100644 --- a/src/datavis3d/data/labelitem_p.h +++ b/src/datavis3d/data/labelitem_p.h @@ -71,10 +71,8 @@ public: void clear(); private: - // LabelItem owns a global texture id resource, and deletes it at destructor, - // so we disable assignment operator as a safety measure. We don't use Q_DISABLE_COPY - // macro, because that also disables the default constructor, which we need. - LabelItem &operator=(const LabelItem &); + Q_DISABLE_COPY(LabelItem); + QSize m_size; GLuint m_textureId; }; diff --git a/src/datavis3d/data/qabstractdataitem.cpp b/src/datavis3d/data/qabstractdataitem.cpp index fa86fd91..b955f7a7 100644 --- a/src/datavis3d/data/qabstractdataitem.cpp +++ b/src/datavis3d/data/qabstractdataitem.cpp @@ -70,16 +70,6 @@ QAbstractDataItem::~QAbstractDataItem() { } -/*! - * \a label A formatted label for the data item. - * - * Sets the formatted label for the data item. - */ -void QAbstractDataItem::setLabel(const QString &label) -{ - d_ptr->m_label = label; -} - QString &QAbstractDataItem::label() const { if (d_ptr->m_label.isNull()) @@ -96,4 +86,10 @@ QAbstractDataItemPrivate::~QAbstractDataItemPrivate() { } +void QAbstractDataItemPrivate::setLabel(const QString &label) +{ + m_labelItem.clear(); + m_label = label; +} + QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qabstractdataitem.h b/src/datavis3d/data/qabstractdataitem.h index 999f3c3d..be69bf49 100644 --- a/src/datavis3d/data/qabstractdataitem.h +++ b/src/datavis3d/data/qabstractdataitem.h @@ -57,8 +57,10 @@ protected: public: virtual ~QAbstractDataItem(); + // Set custom label format for this item - otherwise uses label format specified by the proxy + //TODO void setLabelFormat(const QString &labelFormat); + // formatted label for value - void setLabel(const QString &label); QString &label() const; protected: diff --git a/src/datavis3d/data/qabstractdataitem_p.h b/src/datavis3d/data/qabstractdataitem_p.h index 9630a914..ff86b8fc 100644 --- a/src/datavis3d/data/qabstractdataitem_p.h +++ b/src/datavis3d/data/qabstractdataitem_p.h @@ -82,12 +82,16 @@ public: // Selection label item (containing special selection texture, if mode is activated) // Ownership of the label texture (if any) transfers to QAbstractDataItemPrivate - void setSelectionLabel(const LabelItem &labelItem); const LabelItem &selectionLabel() const { return m_selectionLabel; } LabelItem &selectionLabel() { return m_selectionLabel; } void setDataProxy(QAbstractDataProxy *proxy) { m_dataProxy = proxy; } + // setLabel is not public because changing value automatically reformats it. + // If we want to enable custom labels for items, we should have item specific + // labelFormat instead. + void setLabel(const QString &label); + protected: virtual void formatLabel() = 0; diff --git a/src/datavis3d/data/qabstractdataproxy.h b/src/datavis3d/data/qabstractdataproxy.h index b861e8ed..e06e52d3 100644 --- a/src/datavis3d/data/qabstractdataproxy.h +++ b/src/datavis3d/data/qabstractdataproxy.h @@ -72,8 +72,6 @@ public: DataType type() const; - // TODO: Maybe proxy should be just - // Items use this string to format single item labels, unless custom proxy initializes // item labels with something else. void setItemLabelFormat(const QString &format); @@ -82,7 +80,6 @@ public: QMutex *mutex(); signals: -// void dataHintChanged(); void itemLabelFormatChanged(); protected: diff --git a/src/datavis3d/data/qbardataitem.cpp b/src/datavis3d/data/qbardataitem.cpp index d093e69f..ad70d6e2 100644 --- a/src/datavis3d/data/qbardataitem.cpp +++ b/src/datavis3d/data/qbardataitem.cpp @@ -50,7 +50,7 @@ QT_DATAVIS3D_BEGIN_NAMESPACE * \brief The QBarDataItem class provides a container for resolved data to be added to bar graphs. * \since 1.0.0 * - * A QAbstractDataItem holds data for a single rendered bar in a graph. + * A QBarDataItem holds data for a single rendered bar in a graph. * Bar data proxies parse data into QBarDataItem instances for visualizing. * * \sa QAbstractDataItem, QBarDataProxy, {Qt Data Visualization 3D C++ Classes} @@ -64,6 +64,12 @@ QBarDataItem::QBarDataItem() { } +QBarDataItem::QBarDataItem(float value) + : QAbstractDataItem(new QBarDataItemPrivate()) +{ + setValue(value); +} + /*! * Destroys QBarDataItem. @@ -75,7 +81,7 @@ QBarDataItem::~QBarDataItem() void QBarDataItem::setValue(float value) { dptr()->m_value = value; - setLabel(QString()); // Forces reformatting on next access + d_ptr->setLabel(QString()); // Forces reformatting on next access } float QBarDataItem::value() @@ -98,10 +104,10 @@ void QBarDataItemPrivate::formatLabel() // Format the string on first access QString numStr; numStr.setNum(m_value); - // TODO actually format instead of just appending the value + // TODO actually format instead of just prepending the value m_label.clear(); - m_label.append(m_dataProxy->itemLabelFormat()); m_label.append(numStr); + m_label.append(m_dataProxy->itemLabelFormat()); } QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qbardataitem.h b/src/datavis3d/data/qbardataitem.h index d68e283b..19f77617 100644 --- a/src/datavis3d/data/qbardataitem.h +++ b/src/datavis3d/data/qbardataitem.h @@ -52,6 +52,7 @@ class QT_DATAVIS3D_EXPORT QBarDataItem : public QAbstractDataItem { public: QBarDataItem(); + QBarDataItem(float value); ~QBarDataItem(); void setValue(float value); diff --git a/src/datavis3d/data/qbardataproxy.cpp b/src/datavis3d/data/qbardataproxy.cpp index 6495886c..ea77b870 100644 --- a/src/datavis3d/data/qbardataproxy.cpp +++ b/src/datavis3d/data/qbardataproxy.cpp @@ -57,49 +57,91 @@ QBarDataProxy::~QBarDataProxy() void QBarDataProxy::resetArray(int rowCount, int columnCount) { - dptr()->resetArray(rowCount, columnCount); + resetArray(0, rowCount, columnCount); +} + +void QBarDataProxy::resetArray(QBarDataArray *newArray, int rowCount, int columnCount) +{ + dptr()->resetArray(newArray, rowCount, columnCount); emit arrayReset(); } +void QBarDataProxy::resetArray(QBarDataArray *newArray) +{ + int rowCount(newArray->size()); + int columnCount(0); + + if (rowCount) + columnCount = newArray->at(0)->size(); + + resetArray(newArray, rowCount, columnCount); +} + void QBarDataProxy::setRow(int rowIndex, QBarDataRow *row) { dptr()->setRow(rowIndex, row); emit rowsChanged(rowIndex, 1); } +int QBarDataProxy::addRow(QBarDataRow *row) +{ + int addIndex = dptr()->addRow(row); + emit rowsAdded(addIndex, 1); + return addIndex; +} + int QBarDataProxy::addRows(QBarDataArray *rows) { int addCount = rows->size(); - int addIndex = dptr()->addRows(rows); // deletes rows + int addIndex = dptr()->addRows(rows); // deletes original rows array emit rowsAdded(addIndex, addCount); return addIndex; } +void QBarDataProxy::insertRow(int rowIndex, QBarDataRow *row) +{ + dptr()->insertRow(rowIndex, row); + emit rowsInserted(rowIndex, 1); +} + void QBarDataProxy::insertRows(int rowIndex, QBarDataArray *rows) { int insertCount = rows->size(); - dptr()->insertRows(rowIndex, rows); // deletes rows + dptr()->insertRows(rowIndex, rows); // deletes original rows array emit rowsInserted(rowIndex, insertCount); } -int QBarDataProxy::rowCount() +void QBarDataProxy::setRowCount(int count) { - return dptr()->m_rowCount; + QMutexLocker locker(mutex()); + int oldCount = dptr()->m_rowCount; + + dptr()->setRowCount(count); + + locker.unlock(); + + if (oldCount < count) + emit rowsAdded(oldCount, count - oldCount); + else if (oldCount > count) + emit rowsRemoved(count, oldCount - count); } -void QBarDataProxy::setRowCount(int count) +void QBarDataProxy::setColumnCount(int count) { - dptr()->setRowCount(count); + QMutexLocker locker(mutex()); + dptr()->setColumnCount(count); + // TODO emit columnsAdded/columnsRemoved } -int QBarDataProxy::columnCount() +// Mutexing data accessors should be done by user +int QBarDataProxy::rowCount() { - return dptr()->m_columnCount; + return dptr()->m_rowCount; } -void QBarDataProxy::setColumnCount(int count) +int QBarDataProxy::columnCount() { - dptr()->setColumnCount(count); + return dptr()->m_columnCount; } const QBarDataArray &QBarDataProxy::array() const @@ -138,37 +180,59 @@ QBarDataProxyPrivate::QBarDataProxyPrivate(QBarDataProxy *q) QBarDataProxyPrivate::~QBarDataProxyPrivate() { - resetArray(0, 0); + clearArray(); } -void QBarDataProxyPrivate::resetArray(int rowCount, int columnCount) +void QBarDataProxyPrivate::resetArray(QBarDataArray *newArray, int rowCount, int columnCount) { QMutexLocker locker(&m_mutex); - for (int i = 0; i < m_rowCount; i++) - clearRow(i); - m_dataArray.clear(); + clearArray(); m_rowCount = rowCount; m_columnCount = columnCount; + if (newArray) { + m_dataArray = *newArray; + delete newArray; + } - m_dataArray.reserve(m_rowCount); - for (int i = 0; i < m_rowCount; i++) - addEmptyRow(); -} + int oldSize = m_dataArray.size(); -//void QBarDataProxyPrivate::resetRow(int rowIndex) -//{ -// QMutexLocker locker(&m_mutex); -//} + if (oldSize < m_rowCount) { + m_dataArray.reserve(m_rowCount); + for (int i = oldSize; i < m_rowCount; i++) + m_dataArray.append(0); + } else if (oldSize > m_rowCount) { + for (int i = oldSize - 1; i >= m_rowCount; i--) { + clearRow(i); + m_dataArray.removeLast(); + } + } + + for (int i = 0; i < m_dataArray.size(); i++) + fixRow(m_dataArray.at(i)); +} void QBarDataProxyPrivate::setRow(int rowIndex, QBarDataRow *row) { QMutexLocker locker(&m_mutex); clearRow(rowIndex); - fixRow(*row); + fixRow(row); m_dataArray[rowIndex] = row; } +int QBarDataProxyPrivate::addRow(QBarDataRow *row) +{ + QMutexLocker locker(&m_mutex); + int currentSize = m_rowCount; + // Init column count to row size if not yet explicitly set + if (!m_columnCount) + m_columnCount = row->size(); + fixRow(row); + m_dataArray.append(row); + m_rowCount++; + return currentSize; +} + int QBarDataProxyPrivate::addRows(QBarDataArray *rows) { QMutexLocker locker(&m_mutex); @@ -177,7 +241,7 @@ int QBarDataProxyPrivate::addRows(QBarDataArray *rows) if (!m_columnCount && rows->size()) m_columnCount = rows->at(0)->size(); for (int i = 0; i < rows->size(); i++) { - fixRow(*rows->at(i)); + fixRow(rows->at(i)); m_dataArray.append(rows->at(i)); } m_rowCount += rows->size(); @@ -185,6 +249,17 @@ int QBarDataProxyPrivate::addRows(QBarDataArray *rows) return currentSize; } +void QBarDataProxyPrivate::insertRow(int rowIndex, QBarDataRow *row) +{ + QMutexLocker locker(&m_mutex); + // Init column count to row size if not yet explicitly set + if (!m_columnCount) + m_columnCount = row->size(); + fixRow(row); + m_dataArray.insert(rowIndex, row); + m_rowCount++; +} + void QBarDataProxyPrivate::insertRows(int rowIndex, QBarDataArray *rows) { QMutexLocker locker(&m_mutex); @@ -192,55 +267,87 @@ void QBarDataProxyPrivate::insertRows(int rowIndex, QBarDataArray *rows) if (!m_columnCount && rows->size()) m_columnCount = rows->at(0)->size(); for (int i = 0; i < rows->size(); i++) { - fixRow(*rows->at(i)); + fixRow(rows->at(i)); m_dataArray.insert(rowIndex, rows->at(i)); } m_rowCount += rows->size(); delete rows; } +void QBarDataProxyPrivate::setRowCount(int count) +{ + // Locked already in public implementatation to avoid multiple lockings per call + if (m_rowCount != count) { + if (count < m_columnCount) { + for (int i = m_columnCount - 1; i >= count; i--) { + clearRow(i); + m_dataArray.removeLast(); + } + } else if (count > m_columnCount) { + for (int i = m_columnCount; i < count; i++) + m_dataArray.append(0); + } + m_rowCount = count; + } +} + +void QBarDataProxyPrivate::setColumnCount(int count) +{ + QMutexLocker locker(&m_mutex); + if (m_columnCount != count) { + m_columnCount = count; + for (int i = 0; i < m_rowCount; i++) + fixRow(m_dataArray.at(i)); + } +} + // Protected & private functions. Do not mutex as these are used from mutexed functions. void QBarDataProxyPrivate::clearRow(int rowIndex) { - for (int i = 0; i < m_columnCount; i++) - delete m_dataArray[rowIndex]->at(i); - delete m_dataArray[rowIndex]; - m_dataArray[rowIndex] = 0; + if (m_dataArray[rowIndex]) { + for (int i = 0; i < m_columnCount; i++) + delete m_dataArray[rowIndex]->at(i); + delete m_dataArray[rowIndex]; + m_dataArray[rowIndex] = 0; + } } -// Note that this function doesn't change rowCount -void QBarDataProxyPrivate::addEmptyRow() +void QBarDataProxyPrivate::clearArray() { - QBarDataRow *newRow = new QBarDataRow; - newRow->reserve(m_columnCount); - for (int i = 0; i < m_columnCount; i++) - newRow->append(0); - m_dataArray.append(newRow); + for (int i = 0; i < m_rowCount; i++) + clearRow(i); + m_dataArray.clear(); } -void QBarDataProxyPrivate::fixRow(QBarDataRow &row) +void QBarDataProxyPrivate::fixRow(QBarDataRow *row) { - int rowSize = row.size(); + if (!row) + return; + + int rowSize = row->size(); if (rowSize < m_columnCount) { for (int i = rowSize; i < m_columnCount; i++) - row.append(new QBarDataItem); + row->append(new QBarDataItem); } else if (rowSize > m_columnCount) { for (int i = m_columnCount; i < rowSize; i++) - delete row.takeLast(); + delete row->takeLast(); } for (int i = 0; i < m_columnCount; i++) { - if (row.at(i)) - row.at(i)->d_ptr->setDataProxy(q_ptr); + if (row->at(i)) + row->at(i)->d_ptr->setDataProxy(q_ptr); } } QPair<GLfloat, GLfloat> QBarDataProxyPrivate::limitValues(int startRow, int endRow, int startColumn, int endColumn) { + QMutexLocker locker(&m_mutex); QPair<GLfloat, GLfloat> limits = qMakePair(100.0f, -100.0f); endRow = qMin(endRow, m_rowCount - 1); endColumn = qMin(endColumn, m_columnCount - 1); for (int i = startRow; i <= endRow; i++) { + if (!m_dataArray.at(i)) + continue; for (int j = startColumn; j <= endColumn; j++) { QBarDataItem *item = m_dataArray.at(i)->at(j); if (item) { @@ -255,30 +362,4 @@ QPair<GLfloat, GLfloat> QBarDataProxyPrivate::limitValues(int startRow, int endR return limits; } -void QBarDataProxyPrivate::setRowCount(int count) -{ - if (m_rowCount != count) { - if (count < m_columnCount) { - for (int i = m_columnCount - 1; i >= count; i--) { - clearRow(i); - m_dataArray.removeLast(); - } - } else if (count > m_columnCount) { - for (int i = m_columnCount; i < count; i++) { - addEmptyRow(); - } - } - m_rowCount = count; - } -} - -void QBarDataProxyPrivate::setColumnCount(int count) -{ - if (m_columnCount != count) { - m_columnCount = count; - for (int i = 0; i < m_rowCount; i++) - fixRow(*m_dataArray.at(i)); - } -} - QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qbardataproxy.h b/src/datavis3d/data/qbardataproxy.h index a2631a23..3ac13f78 100644 --- a/src/datavis3d/data/qbardataproxy.h +++ b/src/datavis3d/data/qbardataproxy.h @@ -63,46 +63,53 @@ public: explicit QBarDataProxy(); virtual ~QBarDataProxy(); + // Anyone accessing the data needs to protect the access with QAbstractDataProxy::mutex(). + // However, unprotected use from same thread that handles data setting to proxy is generally + // not very risky, as QtDataVis3D does very little automatic changing of data that can be changed via + // public interface. E.g. Item labels is one such example that could conflict. + int rowCount(); + int columnCount(); + const QBarDataArray &array() const; + const QBarDataRow *rowAt(int rowIndex) const; + QBarDataItem *itemAt(int rowIndex, int columnIndex); + // The data array is a list of list (rows) of QBarDataItem instances. - // Each row can contains exactly the column count items, empty items are added if + // Each row can contains exactly zero or the column count items, empty items are added if // adding too short rows or removed if adding too long rows. // All array/item manipulation functions are internally protected by data mutex. // TODO: Should we remove internal mutexing and require user to mutex also on data manipulations? - // TODO: That would lead to signal emissions from inside the mutex, potential for deadlock? + // TODO: Upside would be enabling user to mix data setters and getters within same mutex scope. + // TODO: Downside would be signal emissions from inside the mutex scope, which has potential for deadlock. - // TODO Should data manipulation/access methods be protected to enforce subclassing use of proxy? + // TODO Should data manipulation/access methods be protected rather than public to enforce subclassing use of proxy? // TODO Leaving them public gives user more options. - // Anyone accessing the data needs to protect the access with QAbstractDataProxy::mutex(). - const QBarDataArray &array() const; - const QBarDataRow *rowAt(int rowIndex) const; - QBarDataItem *itemAt(int rowIndex, int columnIndex); + // QBarDataProxy takes ownership of all QBarDataArrays, QBarDataRows, and QBarDataItems passed to it. - int rowCount(); void setRowCount(int count); - int columnCount(); void setColumnCount(int count); - // QBarDataProxy takes ownership of all QBarDataArrays, QBarDataRows, and QBarDataItems passed to it. - // Clears the array and reserves specified amount of new empty rows. void resetArray(int rowCount, int columnCount); - // TODO void resetArray(QBarDataArray *newArray); - // TODO void resetRow(int rowIndex); // Clear a row - // TODO void resetColumn(int columnIndex); - // TODO void resetItem(int rowIndex, int columnIndex); // deletes the item + // Clears the existing array and sets it data to new array. Fixes the array according to + // specified row and column counts. + void resetArray(QBarDataArray *newArray, int rowCount, int columnCount); + // Clears the existing array and sets it data to new array. + // Row count is the row count of new array, and column count is the column count of + // the first row of the new array. Rest of the rows are fixed to this count. + void resetArray(QBarDataArray *newArray); void setRow(int rowIndex, QBarDataRow *row); // TODO void setColumn(int columnIndex, QBarDataRow *column); // TODO void setItem(int rowIndex, int columnIndex, QBarDataItem *item); - // TODO int addRow(QBarDataRow *row); // returns the index of added row + int addRow(QBarDataRow *row); // returns the index of added row int addRows(QBarDataArray *rows); // returns the index of first added row // TODO int addColumns(QBarDataArray *columns); // returns the index of first added column - // TODO void insertRow(int rowIndex, QBarDataRow *row); + void insertRow(int rowIndex, QBarDataRow *row); void insertRows(int rowIndex, QBarDataArray *rows); // TODO void insertColumns(int columnIndex, QBarDataArray *columns); @@ -120,7 +127,6 @@ signals: void rowsChanged(int startIndex, int count); void rowsRemoved(int startIndex, int count); // Index may be over current array size if removed from end void rowsInserted(int startIndex, int count); - // TODO void itemChanged(int rowIndex, int columnIndex); protected: QBarDataProxyPrivate *dptr(); diff --git a/src/datavis3d/data/qbardataproxy_p.h b/src/datavis3d/data/qbardataproxy_p.h index 276b1e56..83af659b 100644 --- a/src/datavis3d/data/qbardataproxy_p.h +++ b/src/datavis3d/data/qbardataproxy_p.h @@ -66,10 +66,11 @@ public: QBarDataProxyPrivate(QBarDataProxy *q); virtual ~QBarDataProxyPrivate(); - void resetArray(int rowCount, int columnCount); - // TODO void resetRow(int rowIndex); + void resetArray(QBarDataArray *newArray, int rowCount, int columnCount); void setRow(int rowIndex, QBarDataRow *row); + int addRow(QBarDataRow *row); int addRows(QBarDataArray *rows); + void insertRow(int rowIndex, QBarDataRow *row); void insertRows(int rowIndex, QBarDataArray *rows); QPair<GLfloat, GLfloat> limitValues(int startRow, int startColumn, int rowCount, int columnCount); @@ -79,8 +80,8 @@ public: protected: void clearRow(int rowIndex); - void addEmptyRow(); - void fixRow(QBarDataRow &row); + void clearArray(); + void fixRow(QBarDataRow *row); QBarDataArray m_dataArray; diff --git a/src/datavis3d/data/qolddataproxy.cpp b/src/datavis3d/data/qolddataproxy.cpp index 1bdfd2ee..d2fb2cb0 100644 --- a/src/datavis3d/data/qolddataproxy.cpp +++ b/src/datavis3d/data/qolddataproxy.cpp @@ -176,7 +176,7 @@ void QOldDataProxy::addProxySet(QDataSet *dataSet) newProxyArray->append(newProxyRow); } - resetArray(rowCount(), columnCount()); + resetArray(0, 0); addRows(newProxyArray); } diff --git a/src/datavis3d/engine/bars3dcontroller.cpp b/src/datavis3d/engine/bars3dcontroller.cpp index 90390149..c3f7aa5f 100644 --- a/src/datavis3d/engine/bars3dcontroller.cpp +++ b/src/datavis3d/engine/bars3dcontroller.cpp @@ -76,12 +76,14 @@ Bars3dController::Bars3dController(QRect boundRect) m_tickStep(0), m_tickMinimum(0.0f), m_renderer(0), - m_data(new QBarDataProxy) + m_data(0) { // Default axes. Only Y axis can actually be changed by user. setAxisX(new QCategoryAxis()); setAxisY(new QValueAxis()); setAxisZ(new QCategoryAxis()); + + setDataProxy(new QBarDataProxy); } Bars3dController::~Bars3dController() @@ -406,7 +408,7 @@ void Bars3dController::setMeshFileName(const QString &objFileName) } // TODO: This sets data window. Needs more parameters, now assumes window always starts at 0,0. -void Bars3dController::setupSampleSpace(int columnCount, int rowCount) +void Bars3dController::setupSampleSpace(int rowCount, int columnCount) { // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted) setSlicingActive(false); diff --git a/src/datavis3d/engine/bars3drenderer.cpp b/src/datavis3d/engine/bars3drenderer.cpp index d3cdfdaf..6e13b82f 100644 --- a/src/datavis3d/engine/bars3drenderer.cpp +++ b/src/datavis3d/engine/bars3drenderer.cpp @@ -310,7 +310,6 @@ void Bars3dRenderer::render(const QBarDataArray &dataArray, const LabelItem &zLabel, const GLuint defaultFboHandle) { - // TODO: Protect access to data with mutex! #ifdef DISPLAY_RENDER_SPEED // For speed computation if (m_isFirstFrame) { @@ -481,11 +480,13 @@ void Bars3dRenderer::drawSlicedScene(CameraHelper *camera, QBarDataItem *dummyItem = NULL; const LabelItem &sliceSelectionLabel = *m_sliceTitleItem; if (ModeZoomRow == m_cachedSelectionMode) { - m_drawer->drawLabel(*dummyItem, sliceSelectionLabel, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), 0, - m_cachedSelectionMode, m_labelShader, - m_labelObj, camera, false, false, LabelTop); + if (m_sliceTitleItem) { + m_drawer->drawLabel(*dummyItem, sliceSelectionLabel, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), 0, + m_cachedSelectionMode, m_labelShader, + m_labelObj, camera, false, false, LabelTop); + } m_drawer->drawLabel(*dummyItem, zLabel, viewMatrix, projectionMatrix, QVector3D(0.0f, m_yAdjustment, zComp), QVector3D(0.0f, 0.0f, 0.0f), 0, @@ -497,11 +498,13 @@ void Bars3dRenderer::drawSlicedScene(CameraHelper *camera, QVector3D(0.0f, 0.0f, 0.0f), 0, m_cachedSelectionMode, m_labelShader, m_labelObj, camera, false, false, LabelBottom); - m_drawer->drawLabel(*dummyItem, sliceSelectionLabel, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), 0, - m_cachedSelectionMode, m_labelShader, - m_labelObj, camera, false, false, LabelTop); + if (m_sliceTitleItem) { + m_drawer->drawLabel(*dummyItem, sliceSelectionLabel, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), 0, + m_cachedSelectionMode, m_labelShader, + m_labelObj, camera, false, false, LabelTop); + } } m_drawer->drawLabel(*dummyItem, yLabel, viewMatrix, projectionMatrix, QVector3D(0.0f, m_yAdjustment, zComp), @@ -520,22 +523,22 @@ void Bars3dRenderer::drawSlicedScene(CameraHelper *camera, m_labelObj, camera); // Draw labels - const LabelItem *labelItem; // TODO: Protect with mutex or redesign axis label handling? if (m_sliceAxisP->labelItems().size() > col) { + const LabelItem *labelItem(0); // If draw order of bars is flipped, label draw order should be too if (m_xFlipped) { - labelItem = &m_sliceAxisP->labelItems().at(col); + labelItem = m_sliceAxisP->labelItems().at(col); } else { - labelItem = &m_sliceAxisP->labelItems().at( + labelItem = m_sliceAxisP->labelItems().at( m_sliceAxisP->labelItems().size() - col - 1); } + m_drawer->drawLabel(*item, *labelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, -45.0f), (item->value() / m_heightNormalizer), + m_cachedSelectionMode, m_labelShader, + m_labelObj, camera, false, false, LabelBelow); } - m_drawer->drawLabel(*item, *labelItem, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, -45.0f), (item->value() / m_heightNormalizer), - m_cachedSelectionMode, m_labelShader, - m_labelObj, camera, false, false, LabelBelow); } glDisable(GL_TEXTURE_2D); @@ -668,6 +671,8 @@ void Bars3dRenderer::drawScene(const QBarDataArray &dataArray, if (dataArray.size() <= row || !dataArray.at(row)) continue; for (int bar = startBar; bar != stopBar; bar += stepBar) { + if (dataArray.at(row)->size() <= bar) + continue; QBarDataItem *item = dataArray.at(row)->at(bar); if (!item) continue; @@ -770,6 +775,8 @@ void Bars3dRenderer::drawScene(const QBarDataArray &dataArray, if (dataArray.size() <= row || !dataArray.at(row)) continue; for (int bar = startBar; bar != stopBar; bar += stepBar) { + if (dataArray.at(row)->size() <= bar) + continue; QBarDataItem *item = dataArray.at(row)->at(bar); if (!item) continue; @@ -877,12 +884,15 @@ void Bars3dRenderer::drawScene(const QBarDataArray &dataArray, if (!m_cachedIsSlicingActivated && m_sliceSelection) { m_sliceSelection->clear(); // Slice doesn't own its items m_sliceAxisP = 0; + m_sliceTitleItem = 0; } bool barSelectionFound = false; for (int row = startRow; row != stopRow; row += stepRow) { if (dataArray.size() <= row || !dataArray.at(row)) continue; for (int bar = startBar; bar != stopBar; bar += stepBar) { + if (dataArray.at(row)->size() <= bar) + continue; QBarDataItem *item = dataArray.at(row)->at(bar); if (!item) continue; @@ -959,8 +969,10 @@ void Bars3dRenderer::drawScene(const QBarDataArray &dataArray, if (!m_sliceAxisP) { // m_sliceAxisP is the axis for labels, while title comes from different axis. m_sliceAxisP = m_controller->axisZ()->d_ptr.data(); - m_sliceTitleItem = &m_controller->axisX()->d_ptr->labelItems().at( - m_controller->axisX()->d_ptr->labelItems().size() - row - 1); + if (m_controller->axisX()->d_ptr->labelItems().size() > row) { + m_sliceTitleItem = m_controller->axisX()->d_ptr->labelItems().at( + m_controller->axisX()->d_ptr->labelItems().size() - row - 1); + } } } break; @@ -975,8 +987,10 @@ void Bars3dRenderer::drawScene(const QBarDataArray &dataArray, if (!m_sliceAxisP) { // m_sliceAxisP is the axis for labels, while title comes from different axis. m_sliceAxisP = m_controller->axisX()->d_ptr.data(); - m_sliceTitleItem = &m_controller->axisZ()->d_ptr->labelItems().at( - m_controller->axisZ()->d_ptr->labelItems().size() - bar - 1); + if (m_controller->axisZ()->d_ptr->labelItems().size() > bar) { + m_sliceTitleItem = m_controller->axisZ()->d_ptr->labelItems().at( + m_controller->axisZ()->d_ptr->labelItems().size() - bar - 1); + } } } break; @@ -1384,10 +1398,9 @@ void Bars3dRenderer::drawScene(const QBarDataArray &dataArray, #else // TODO: using static is bad, cannot use two barcharts at the same time! // TODO: Besides, doesn't m_previouslySelectedBar mechanic already cover this? - static bool firstSelection = true; // Draw the value string followed by row label and column label LabelItem &labelItem = m_selectedBar->d_ptr->selectionLabel(); - if (firstSelection || m_previouslySelectedBar != m_selectedBar || m_updateLabels) { + if (m_previouslySelectedBar != m_selectedBar || m_updateLabels) { QString labelText = m_selectedBar->label(); if ((m_controller->axisZ()->labels().size() > m_selectedBar->dptr()->position().y()) && (m_controller->axisX()->labels().size() > m_selectedBar->dptr()->position().x())) { @@ -1400,7 +1413,6 @@ void Bars3dRenderer::drawScene(const QBarDataArray &dataArray, } m_drawer->generateLabelItem(labelItem, labelText); m_previouslySelectedBar = m_selectedBar; - firstSelection = false; } m_drawer->drawLabel(*m_selectedBar, labelItem, viewMatrix, projectionMatrix, @@ -1462,7 +1474,7 @@ void Bars3dRenderer::drawScene(const QBarDataArray &dataArray, // TODO: Try it; draw the label here m_dummyBarDataItem->d_ptr->setTranslation(labelPos); - const LabelItem &axisLabelItem = m_controller->axisX()->d_ptr->labelItems().at( + const LabelItem &axisLabelItem = *m_controller->axisX()->d_ptr->labelItems().at( m_controller->axisX()->d_ptr->labelItems().size() - row - 1); //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << dataSet->rowLabels().at(row); @@ -1505,7 +1517,7 @@ void Bars3dRenderer::drawScene(const QBarDataArray &dataArray, // TODO: Try it; draw the label here m_dummyBarDataItem->d_ptr->setTranslation(labelPos); - const LabelItem &axisLabelItem = m_controller->axisZ()->d_ptr->labelItems().at( + const LabelItem &axisLabelItem = *m_controller->axisZ()->d_ptr->labelItems().at( m_controller->axisZ()->d_ptr->labelItems().size() - bar - 1); //qDebug() << "labelPos, col" << bar + 1 << ":" << labelPos << dataSet->columnLabels().at(bar); diff --git a/src/datavis3d/engine/drawer.cpp b/src/datavis3d/engine/drawer.cpp index 79344c6f..b5a59607 100644 --- a/src/datavis3d/engine/drawer.cpp +++ b/src/datavis3d/engine/drawer.cpp @@ -305,6 +305,8 @@ void Drawer::generateLabelItem(LabelItem &item, const QString &text) { initializeOpenGL(); + item.clear(); + // Create labels // Print label into a QImage using QPainter QImage label = Utils::printTextToImage(m_font, diff --git a/src/datavis3d/engine/maps3dcontroller.cpp b/src/datavis3d/engine/maps3dcontroller.cpp index fc06f3a5..8df4b53e 100644 --- a/src/datavis3d/engine/maps3dcontroller.cpp +++ b/src/datavis3d/engine/maps3dcontroller.cpp @@ -840,7 +840,6 @@ void Maps3DController::drawScene(const GLuint defaultFboHandle) // Draw just the value string of the selected bar QBarDataItem dummyItem; // TODO temporary solution dummyItem.setValue(m_selectedBar->d_ptr->value()); - dummyItem.setLabel(m_selectedBar->d_ptr->valueStr()); if (prevItem != m_selectedBar || m_updateLabels) { m_drawer->generateLabelTexture(&dummyItem); prevItem = m_selectedBar; diff --git a/src/datavis3d/engine/q3dbars.h b/src/datavis3d/engine/q3dbars.h index b38db363..6a9922e2 100644 --- a/src/datavis3d/engine/q3dbars.h +++ b/src/datavis3d/engine/q3dbars.h @@ -73,25 +73,6 @@ public: explicit Q3DBars(); ~Q3DBars(); - // Add a row of data. Each new row is added to the front of the sample space, moving previous - // rows back (if sample space is more than one row deep) - //void addDataRow(const QVector<float> &dataRow); - - // ownership of dataItems is transferred - //void addDataRow(const QVector<QDataItem*> &dataRow); - - // ownership of dataRow is transferred - //void addDataRow(QDataRow *dataRow); - - // Add complete data set at a time, as a vector of data rows - //void addDataSet(const QVector< QVector<float> > &data); - - // ownership of dataItems is transferred - //void addDataSet(const QVector< QVector<QDataItem*> > &data); - - // ownership of dataSet is transferred - //void addDataSet(QDataSet* dataSet); - // bar thickness, spacing between bars, and is spacing relative to thickness or absolute // y -component sets the thickness/spacing of z -direction // With relative 0.0f means side-to-side, 1.0f = one thickness in between |