diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-08-16 12:08:48 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-08-16 12:31:06 +0300 |
commit | 4adf6812aa19781fc005bdb06958fdb3c051a3d5 (patch) | |
tree | 4862427281c91129c63c08e7d9a1ea88e5523c61 | |
parent | bfcbf5d59277635a9c958cf47b540d32ee7f78dc (diff) |
Implement value axis label formatting.
Change-Id: Ie657df264549e4277d3bd1eaf2ca48436c153717
Reviewed-by: Mika Salmela <mika.salmela@digia.com>
-rw-r--r-- | examples/barchart/main.cpp | 1 | ||||
-rw-r--r-- | examples/qmlbarchart/qml/qmlbarchart/main.qml | 2 | ||||
-rw-r--r-- | examples/rainfall/rainfallchart.cpp | 1 | ||||
-rw-r--r-- | examples/widget/chart.cpp | 4 | ||||
-rw-r--r-- | src/datavis3d/axis/qabstractaxis.cpp | 6 | ||||
-rw-r--r-- | src/datavis3d/axis/qabstractaxis_p.h | 2 | ||||
-rw-r--r-- | src/datavis3d/axis/qvalueaxis.cpp | 42 | ||||
-rw-r--r-- | src/datavis3d/axis/qvalueaxis_p.h | 4 | ||||
-rw-r--r-- | src/datavis3d/engine/abstract3dcontroller.cpp | 93 | ||||
-rw-r--r-- | src/datavis3d/engine/abstract3dcontroller_p.h | 14 | ||||
-rw-r--r-- | src/datavis3d/utils/utils.cpp | 57 | ||||
-rw-r--r-- | src/datavis3d/utils/utils_p.h | 15 |
12 files changed, 152 insertions, 89 deletions
diff --git a/examples/barchart/main.cpp b/examples/barchart/main.cpp index 77230b5d..d5d138e4 100644 --- a/examples/barchart/main.cpp +++ b/examples/barchart/main.cpp @@ -187,6 +187,7 @@ void ChartDataGenerator::setupModel() m_chart->columnAxis()->setTitle("Day of week"); 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); diff --git a/examples/qmlbarchart/qml/qmlbarchart/main.qml b/examples/qmlbarchart/qml/qmlbarchart/main.qml index f10f98b9..d23113db 100644 --- a/examples/qmlbarchart/qml/qmlbarchart/main.qml +++ b/examples/qmlbarchart/qml/qmlbarchart/main.qml @@ -104,7 +104,7 @@ Item { id: valueAxis min: 0 max: 35 - labelFormat: "M\u20AC" + labelFormat: "%.1f M\u20AC" } Bars3D { id: testchart diff --git a/examples/rainfall/rainfallchart.cpp b/examples/rainfall/rainfallchart.cpp index f7bcd82b..8d7e0157 100644 --- a/examples/rainfall/rainfallchart.cpp +++ b/examples/rainfall/rainfallchart.cpp @@ -55,6 +55,7 @@ RainfallChart::RainfallChart(Q3DBars *rainfall) m_chart->rowAxis()->setTitle("Year"); m_chart->columnAxis()->setTitle("Month"); m_chart->valueAxis()->setTitle(QString("rainfall (in mm) in city %1").arg(m_city - 1)); + m_chart->valueAxis()->setLabelFormat("%d mm"); m_chart->rowAxis()->setCategoryLabels(m_years); m_chart->columnAxis()->setCategoryLabels(months); diff --git a/examples/widget/chart.cpp b/examples/widget/chart.cpp index a8c6c14a..637c140e 100644 --- a/examples/widget/chart.cpp +++ b/examples/widget/chart.cpp @@ -86,8 +86,9 @@ void ChartModifier::restart(bool dynamicData) // Set selection mode to full m_chart->setSelectionMode(QDataVis::ModeItemRowAndColumn); m_chart->valueAxis()->setSegmentCount(m_segments * 2); - m_chart->valueAxis()->setSubSegmentCount(0); + m_chart->valueAxis()->setSubSegmentCount(1); m_chart->valueAxis()->setAutoAdjustRange(true); + m_chart->valueAxis()->setLabelFormat(QString(QStringLiteral("%.3f"))); m_chart->rowAxis()->setTitle("Generic Row"); m_chart->columnAxis()->setTitle("Generic Column"); @@ -137,6 +138,7 @@ void ChartModifier::addDataSet() m_chart->valueAxis()->setSegmentCount(m_segments); m_chart->valueAxis()->setSubSegmentCount(m_subSegments); m_chart->valueAxis()->setRange(m_minval, m_maxval); + m_chart->valueAxis()->setLabelFormat(QString(QStringLiteral("%d ") + celsiusString)); // Create data rows QBarDataArray *dataSet = new QBarDataArray; diff --git a/src/datavis3d/axis/qabstractaxis.cpp b/src/datavis3d/axis/qabstractaxis.cpp index 71b9effd..b35dffc7 100644 --- a/src/datavis3d/axis/qabstractaxis.cpp +++ b/src/datavis3d/axis/qabstractaxis.cpp @@ -38,6 +38,7 @@ QString QAbstractAxis::title() const QStringList QAbstractAxis::labels() const { + d_ptr->updateLabels(); return d_ptr->m_labels; } @@ -81,4 +82,9 @@ void QAbstractAxisPrivate::setOrientation(QAbstractAxis::AxisOrientation orienta Q_ASSERT("Attempted to reset axis orientation."); } +void QAbstractAxisPrivate::updateLabels() +{ + // Default implementation does nothing +} + QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qabstractaxis_p.h b/src/datavis3d/axis/qabstractaxis_p.h index 3866ee75..5b73ce17 100644 --- a/src/datavis3d/axis/qabstractaxis_p.h +++ b/src/datavis3d/axis/qabstractaxis_p.h @@ -44,6 +44,8 @@ public: void setOrientation(QAbstractAxis::AxisOrientation orientation); protected: + virtual void updateLabels(); + QAbstractAxis *q_ptr; QString m_title; diff --git a/src/datavis3d/axis/qvalueaxis.cpp b/src/datavis3d/axis/qvalueaxis.cpp index cee8a5c7..fdc40d75 100644 --- a/src/datavis3d/axis/qvalueaxis.cpp +++ b/src/datavis3d/axis/qvalueaxis.cpp @@ -18,6 +18,7 @@ #include "qvalueaxis.h" #include "qvalueaxis_p.h" +#include "utils_p.h" QT_DATAVIS3D_BEGIN_NAMESPACE @@ -67,7 +68,7 @@ void QValueAxis::setSegmentCount(int count) } if (dptr()->m_segmentCount != count){ dptr()->m_segmentCount = count; - dptr()->recreateLabels(); + dptr()->emitLabelsChanged(); emit segmentCountChanged(count); } } @@ -112,7 +113,7 @@ void QValueAxis::setLabelFormat(const QString &format) { if (dptr()->m_labelFormat != format) { dptr()->m_labelFormat = format; - dptr()->recreateLabels(); + dptr()->emitLabelsChanged(); emit labelFormatChanged(format); } } @@ -169,7 +170,7 @@ void QValueAxisPrivate::setRange(qreal min, qreal max) dirty = true; } if (dirty) { - recreateLabels(); + emitLabelsChanged(); emit qptr()->rangeChanged(min, max); } } @@ -185,7 +186,7 @@ void QValueAxisPrivate::setMin(qreal min) << oldMax << "-->" << m_max; } m_min = min; - recreateLabels(); + emitLabelsChanged(); emit qptr()->rangeChanged(m_min, m_max); } } @@ -201,30 +202,47 @@ void QValueAxisPrivate::setMax(qreal max) << oldMin << "-->" << m_min; } m_max = max; - recreateLabels(); + emitLabelsChanged(); emit qptr()->rangeChanged(m_min, m_max); } } -void QValueAxisPrivate::recreateLabels() +void QValueAxisPrivate::emitLabelsChanged() { + m_labelsDirty = true; + emit q_ptr->labelsChanged(); +} + +void QValueAxisPrivate::updateLabels() +{ + if (!m_labelsDirty) + return; + + m_labelsDirty = false; + QStringList newLabels; newLabels.reserve(m_segmentCount + 1); // First label is at axis min, which is an extra segment qreal segmentStep = (m_max - m_min) / m_segmentCount; + QString formatString(m_labelFormat); + if (formatString.isEmpty()) + formatString = QStringLiteral("%.2f"); + + Utils::ParamType paramType = Utils::findFormatParamType(formatString); + QByteArray formatArray = formatString.toUtf8(); + for (int i = 0; i < m_segmentCount; i++) { - // TODO Actually do proper formatting - newLabels.append(QString::number(m_min + (segmentStep * i))); + qreal value = m_min + (segmentStep * i); + newLabels.append(Utils::formatLabel(formatArray, paramType, value)); } + // Ensure max label doesn't suffer from any rounding errors - newLabels.append(QString::number(m_max)); + newLabels.append(Utils::formatLabel(formatArray, paramType, m_max)); - if (m_labels != newLabels) { + if (m_labels != newLabels) m_labels = newLabels; - emit q_ptr->labelsChanged(); - } } QValueAxis *QValueAxisPrivate::qptr() diff --git a/src/datavis3d/axis/qvalueaxis_p.h b/src/datavis3d/axis/qvalueaxis_p.h index f730d0c0..6d8cc362 100644 --- a/src/datavis3d/axis/qvalueaxis_p.h +++ b/src/datavis3d/axis/qvalueaxis_p.h @@ -47,7 +47,8 @@ public: void setMax (qreal max); protected: - void recreateLabels(); + void emitLabelsChanged(); + virtual void updateLabels(); qreal m_min; qreal m_max; @@ -55,6 +56,7 @@ protected: int m_subSegmentCount; bool m_autoAdjust; QString m_labelFormat; + bool m_labelsDirty; private: QValueAxis *qptr(); diff --git a/src/datavis3d/engine/abstract3dcontroller.cpp b/src/datavis3d/engine/abstract3dcontroller.cpp index 12f76fd1..9a99afaa 100644 --- a/src/datavis3d/engine/abstract3dcontroller.cpp +++ b/src/datavis3d/engine/abstract3dcontroller.cpp @@ -521,23 +521,20 @@ QString Abstract3DController::meshFileName() void Abstract3DController::handleAxisTitleChanged(const QString &title) { - handleAxisTitleChangedBySender(sender(), title); + Q_UNUSED(title) + handleAxisTitleChangedBySender(sender()); } -void Abstract3DController::handleAxisTitleChangedBySender(QObject *sender, const QString &title) +void Abstract3DController::handleAxisTitleChangedBySender(QObject *sender) { - if (sender == m_axisX) { + if (sender == m_axisX) m_changeTracker.axisXTitleChanged = true; - emit axisTitleChanged(QAbstractAxis::AxisOrientationX, title); - } else if (sender == m_axisY) { + else if (sender == m_axisY) m_changeTracker.axisYTitleChanged = true; - emit axisTitleChanged(QAbstractAxis::AxisOrientationY, title); - } else if (sender == m_axisZ) { + else if (sender == m_axisZ) m_changeTracker.axisZTitleChanged = true; - emit axisTitleChanged(QAbstractAxis::AxisOrientationZ, title); - } else { + else qWarning() << __FUNCTION__ << "invoked for invalid axis"; - } } void Abstract3DController::handleAxisLabelsChanged() @@ -547,40 +544,34 @@ void Abstract3DController::handleAxisLabelsChanged() void Abstract3DController::handleAxisLabelsChangedBySender(QObject *sender) { - if (sender == m_axisX) { + if (sender == m_axisX) m_changeTracker.axisXLabelsChanged = true; - emit axisLabelsChanged(QAbstractAxis::AxisOrientationX, m_axisX->labels()); - } else if (sender == m_axisY) { + else if (sender == m_axisY) m_changeTracker.axisYLabelsChanged = true; - emit axisLabelsChanged(QAbstractAxis::AxisOrientationY, m_axisY->labels()); - } else if (sender == m_axisZ) { + else if (sender == m_axisZ) m_changeTracker.axisZLabelsChanged = true; - emit axisLabelsChanged(QAbstractAxis::AxisOrientationZ, m_axisZ->labels()); - } else { + else qWarning() << __FUNCTION__ << "invoked for invalid axis"; - } } void Abstract3DController::handleAxisRangeChanged(qreal min, qreal max) { - handleAxisRangeChangedBySender(sender(), min, max); + Q_UNUSED(min) + Q_UNUSED(max) + handleAxisRangeChangedBySender(sender()); } -void Abstract3DController::handleAxisRangeChangedBySender(QObject *sender, qreal min, qreal max) +void Abstract3DController::handleAxisRangeChangedBySender(QObject *sender) { if (sender == m_axisX) { m_isDataDirty = true; m_changeTracker.axisXRangeChanged = true; - emit axisRangeChanged(QAbstractAxis::AxisOrientationX, min, max); } else if (sender == m_axisY) { m_isDataDirty = true; m_changeTracker.axisYRangeChanged = true; - emit axisRangeChanged(QAbstractAxis::AxisOrientationY, min, max); } else if (sender == m_axisZ) { m_isDataDirty = true; - m_changeTracker.axisZRangeChanged = true; - emit axisRangeChanged(QAbstractAxis::AxisOrientationZ, min, max); } else { qWarning() << __FUNCTION__ << "invoked for invalid axis"; } @@ -588,44 +579,38 @@ void Abstract3DController::handleAxisRangeChangedBySender(QObject *sender, qreal void Abstract3DController::handleAxisSegmentCountChanged(int count) { - handleAxisSegmentCountChangedBySender(sender(), count); + Q_UNUSED(count) + handleAxisSegmentCountChangedBySender(sender()); } -void Abstract3DController::handleAxisSegmentCountChangedBySender(QObject *sender, int count) +void Abstract3DController::handleAxisSegmentCountChangedBySender(QObject *sender) { - if (sender == m_axisX) { + if (sender == m_axisX) m_changeTracker.axisXSegmentCountChanged = true; - emit axisSegmentCountChanged(QAbstractAxis::AxisOrientationX, count); - } else if (sender == m_axisY) { + else if (sender == m_axisY) m_changeTracker.axisYSegmentCountChanged = true; - emit axisSegmentCountChanged(QAbstractAxis::AxisOrientationY, count); - } else if (sender == m_axisZ) { + else if (sender == m_axisZ) m_changeTracker.axisZSegmentCountChanged = true; - emit axisSegmentCountChanged(QAbstractAxis::AxisOrientationZ, count); - } else { + else qWarning() << __FUNCTION__ << "invoked for invalid axis"; - } } void Abstract3DController::handleAxisSubSegmentCountChanged(int count) { - handleAxisSubSegmentCountChangedBySender(sender(), count); + Q_UNUSED(count) + handleAxisSubSegmentCountChangedBySender(sender()); } -void Abstract3DController::handleAxisSubSegmentCountChangedBySender(QObject *sender, int count) +void Abstract3DController::handleAxisSubSegmentCountChangedBySender(QObject *sender) { - if (sender == m_axisX) { + if (sender == m_axisX) m_changeTracker.axisXSubSegmentCountChanged = true; - emit axisSubSegmentCountChanged(QAbstractAxis::AxisOrientationX, count); - } else if (sender == m_axisY) { + else if (sender == m_axisY) m_changeTracker.axisYSubSegmentCountChanged = true; - emit axisSubSegmentCountChanged(QAbstractAxis::AxisOrientationY, count); - } else if (sender == m_axisZ) { + else if (sender == m_axisZ) m_changeTracker.axisZSubSegmentCountChanged = true; - emit axisSubSegmentCountChanged(QAbstractAxis::AxisOrientationZ, count); - } else { + else qWarning() << __FUNCTION__ << "invoked for invalid axis"; - } } void Abstract3DController::handleAxisAutoAdjustRangeChanged(bool autoAdjust) @@ -649,26 +634,20 @@ void Abstract3DController::setAxisHelper(QAbstractAxis::AxisOrientation orientat axis->setParent(0); // Assume ownership axis->d_ptr->setOrientation(orientation); - QObject::connect(axis, &QAbstractAxis::titleChanged, this, &Abstract3DController::handleAxisTitleChanged); QObject::connect(axis, &QAbstractAxis::labelsChanged, this, &Abstract3DController::handleAxisLabelsChanged); - if (orientation == QAbstractAxis::AxisOrientationX) m_changeTracker.axisXTypeChanged = true; else if (orientation == QAbstractAxis::AxisOrientationY) m_changeTracker.axisYTypeChanged = true; else if (orientation == QAbstractAxis::AxisOrientationZ) m_changeTracker.axisZTypeChanged = true; - emit axisTypeChanged(orientation, axis->type()); - - handleAxisTitleChangedBySender(axis, axis->title()); - emit axisTitleChanged(orientation, axis->title()); + handleAxisTitleChangedBySender(axis); handleAxisLabelsChangedBySender(axis); - emit axisLabelsChanged(orientation, axis->labels()); if (axis->type() & QAbstractAxis::AxisTypeValue) { QValueAxis *valueAxis = static_cast<QValueAxis *>(axis); @@ -681,15 +660,9 @@ void Abstract3DController::setAxisHelper(QAbstractAxis::AxisOrientation orientat QObject::connect(valueAxis, &QValueAxis::autoAdjustRangeChanged, this, &Abstract3DController::handleAxisAutoAdjustRangeChanged); - handleAxisRangeChangedBySender(valueAxis, valueAxis->min(), valueAxis->max()); - emit axisRangeChanged(orientation, valueAxis->min(), valueAxis->max()); - - handleAxisSegmentCountChangedBySender(valueAxis, valueAxis->segmentCount()); - emit axisSegmentCountChanged(orientation, valueAxis->segmentCount()); - - handleAxisSubSegmentCountChangedBySender(valueAxis, valueAxis->subSegmentCount()); - emit axisSubSegmentCountChanged(orientation, valueAxis->subSegmentCount()); - + handleAxisRangeChangedBySender(valueAxis); + handleAxisSegmentCountChangedBySender(valueAxis); + handleAxisSubSegmentCountChangedBySender(valueAxis); handleAxisAutoAdjustRangeChangedInOrientation(valueAxis->orientation(), valueAxis->isAutoAdjustRange()); } diff --git a/src/datavis3d/engine/abstract3dcontroller_p.h b/src/datavis3d/engine/abstract3dcontroller_p.h index 8f21c97f..7fc90a93 100644 --- a/src/datavis3d/engine/abstract3dcontroller_p.h +++ b/src/datavis3d/engine/abstract3dcontroller_p.h @@ -248,11 +248,11 @@ public: virtual void setMeshFileName(const QString &fileName); virtual QString meshFileName(); - virtual void handleAxisTitleChangedBySender(QObject *sender, const QString &title); + virtual void handleAxisTitleChangedBySender(QObject *sender); virtual void handleAxisLabelsChangedBySender(QObject *sender); - virtual void handleAxisRangeChangedBySender(QObject *sender, qreal min, qreal max); - virtual void handleAxisSegmentCountChangedBySender(QObject *sender, int count); - virtual void handleAxisSubSegmentCountChangedBySender(QObject *sender, int count); + virtual void handleAxisRangeChangedBySender(QObject *sender); + virtual void handleAxisSegmentCountChangedBySender(QObject *sender); + virtual void handleAxisSubSegmentCountChangedBySender(QObject *sender); virtual void handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust) = 0; public slots: @@ -272,12 +272,6 @@ signals: void fontChanged(QFont font); // TODO should be handled via axis?? What about font for selection label? void shadowQualityChanged(QDataVis::ShadowQuality quality); void labelTransparencyChanged(QDataVis::LabelTransparency transparency); - void axisTypeChanged(QAbstractAxis::AxisOrientation orientation, QAbstractAxis::AxisType type); - void axisTitleChanged(QAbstractAxis::AxisOrientation orientation, QString title); - void axisLabelsChanged(QAbstractAxis::AxisOrientation orientation, QStringList labels); - void axisRangeChanged(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); - void axisSegmentCountChanged(QAbstractAxis::AxisOrientation orientation, int count); - void axisSubSegmentCountChanged(QAbstractAxis::AxisOrientation orientation, int count); void selectionModeChanged(QDataVis::SelectionMode mode); void backgroundEnabledChanged(bool enable); void gridEnabledChanged(bool enable); // TODO: Should be handled via axes? diff --git a/src/datavis3d/utils/utils.cpp b/src/datavis3d/utils/utils.cpp index cf6b91f8..40d7ec9f 100644 --- a/src/datavis3d/utils/utils.cpp +++ b/src/datavis3d/utils/utils.cpp @@ -23,11 +23,9 @@ #include <QPainter> #include <QPoint> #include <QImage> - +#include <QRegExp> #include <qmath.h> -#include <QDebug> - QT_DATAVIS3D_BEGIN_NAMESPACE #define NUM_IN_POWER(y, x) for (;y<x;y<<=1) @@ -231,4 +229,57 @@ QVector3D Utils::getSelection(QPoint mousepos, int height) return selectedColor; } +Utils::ParamType Utils::mapFormatCharToParamType(const QChar &formatChar) +{ + ParamType retVal = ParamTypeUnknown; + if (formatChar == QLatin1Char('d') + || formatChar == QLatin1Char('i') + || formatChar == QLatin1Char('c')) { + retVal = ParamTypeInt; + } else if (formatChar == QLatin1Char('u') + || formatChar == QLatin1Char('o') + || formatChar == QLatin1Char('x') + || formatChar == QLatin1Char('X')) { + retVal = ParamTypeUInt; + } else if (formatChar == QLatin1Char('f') + || formatChar == QLatin1Char('F') + || formatChar == QLatin1Char('e') + || formatChar == QLatin1Char('E') + || formatChar == QLatin1Char('g') + || formatChar == QLatin1Char('G')) { + retVal = ParamTypeReal; + } + + return retVal; +} + +Utils::ParamType Utils::findFormatParamType(const QString &format) +{ + static QRegExp formatMatcher(QStringLiteral("%[\\-\\+#\\s\\d\\.lhjztL]*([dicuoxfegXFEG])")); + + if (formatMatcher.indexIn(format, 0) != -1) { + QString capStr = formatMatcher.cap(1); + if (capStr.isEmpty()) + return ParamTypeUnknown; + else + return mapFormatCharToParamType(capStr.at(0)); + } + + return ParamTypeUnknown; +} + +QString Utils::formatLabel(const QByteArray &format, ParamType paramType, qreal value) +{ + switch (paramType) { + case ParamTypeInt: + return QString().sprintf(format, (qint64)value); + case ParamTypeUInt: + return QString().sprintf(format, (quint64)value); + case ParamTypeReal: + return QString().sprintf(format, value); + default: + return QString::number(value); + } +} + QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/utils/utils_p.h b/src/datavis3d/utils/utils_p.h index fe7d6081..1d8aedfa 100644 --- a/src/datavis3d/utils/utils_p.h +++ b/src/datavis3d/utils/utils_p.h @@ -43,7 +43,14 @@ QT_DATAVIS3D_BEGIN_NAMESPACE class Utils { - public: +public: + enum ParamType { + ParamTypeUnknown = 0, + ParamTypeInt, + ParamTypeUInt, + ParamTypeReal + }; + static GLuint getNearestPowerOfTwo(GLuint value, GLuint &padding); static QVector3D vectorFromColor(const QColor &color); static void printText(QPainter *painter, const QString &text, const QSize &position, @@ -54,6 +61,12 @@ class Utils const QColor &txtColor, QDataVis::LabelTransparency transparency); static QVector3D getSelection(QPoint mousepos, int height); + + static ParamType findFormatParamType(const QString &format); + static QString formatLabel(const QByteArray &format, ParamType paramType, qreal value); + +private: + static ParamType mapFormatCharToParamType(const QChar &formatChar); }; QT_DATAVIS3D_END_NAMESPACE |