diff options
-rw-r--r-- | src/datavisualization/axis/axis.pri | 7 | ||||
-rw-r--r-- | src/datavisualization/axis/qlogvalue3daxisformatter.cpp | 398 | ||||
-rw-r--r-- | src/datavisualization/axis/qlogvalue3daxisformatter.h | 75 | ||||
-rw-r--r-- | src/datavisualization/axis/qlogvalue3daxisformatter_p.h | 73 | ||||
-rw-r--r-- | src/datavisualization/axis/qvalue3daxis.cpp | 8 | ||||
-rw-r--r-- | src/datavisualization/axis/qvalue3daxis_p.h | 3 | ||||
-rw-r--r-- | src/datavisualization/axis/qvalue3daxisformatter.cpp | 133 | ||||
-rw-r--r-- | src/datavisualization/axis/qvalue3daxisformatter.h | 5 | ||||
-rw-r--r-- | src/datavisualization/axis/qvalue3daxisformatter_p.h | 5 | ||||
-rw-r--r-- | src/datavisualization/engine/abstract3dcontroller.cpp | 50 | ||||
-rw-r--r-- | src/datavisualization/engine/abstract3drenderer.cpp | 1 | ||||
-rw-r--r-- | src/datavisualization/engine/axisrendercache_p.h | 8 | ||||
-rw-r--r-- | src/datavisualization/engine/surface3drenderer.cpp | 1 | ||||
-rw-r--r-- | tests/barstest/chart.cpp | 113 | ||||
-rw-r--r-- | tests/barstest/chart.h | 3 | ||||
-rw-r--r-- | tests/barstest/main.cpp | 18 |
16 files changed, 813 insertions, 88 deletions
diff --git a/src/datavisualization/axis/axis.pri b/src/datavisualization/axis/axis.pri index 24463d1e..0173b597 100644 --- a/src/datavisualization/axis/axis.pri +++ b/src/datavisualization/axis/axis.pri @@ -6,10 +6,13 @@ HEADERS += \ $$PWD/qcategory3daxis.h \ $$PWD/qcategory3daxis_p.h \ $$PWD/qvalue3daxisformatter.h \ - $$PWD/qvalue3daxisformatter_p.h + $$PWD/qvalue3daxisformatter_p.h \ + $$PWD/qlogvalue3daxisformatter.h \ + $$PWD/qlogvalue3daxisformatter_p.h SOURCES += \ $$PWD/qabstract3daxis.cpp \ $$PWD/qvalue3daxis.cpp \ $$PWD/qcategory3daxis.cpp \ - $$PWD/qvalue3daxisformatter.cpp + $$PWD/qvalue3daxisformatter.cpp \ + $$PWD/qlogvalue3daxisformatter.cpp diff --git a/src/datavisualization/axis/qlogvalue3daxisformatter.cpp b/src/datavisualization/axis/qlogvalue3daxisformatter.cpp new file mode 100644 index 00000000..36f27c02 --- /dev/null +++ b/src/datavisualization/axis/qlogvalue3daxisformatter.cpp @@ -0,0 +1,398 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "qlogvalue3daxisformatter_p.h" +#include "qvalue3daxis_p.h" +#include <QtCore/qmath.h> + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +/*! + * \class QLogValue3DAxisFormatter + * \inmodule QtDataVisualization + * \brief QLogValue3DAxisFormatter implements logarithmic value axis formatter. + * \since Qt Data Visualization 1.1 + * + * This class provides formatting rules for a logarithmic QValue3DAxis. + * + * When a QLogValue3DAxisFormatter is attached to a QValue3DAxis, the axis range + * cannot include negative values or the zero. + * + * \sa QValue3DAxisFormatter + */ + +/*! + * \qmltype LogValueAxis3DFormatter + * \inqmlmodule QtDataVisualization + * \since QtDataVisualization 1.1 + * \ingroup datavisualization_qml + * \instantiates QLogValue3DAxisFormatter + * \brief LogValueAxis3DFormatter implements logarithmic value axis formatter. + * + * This type provides formatting rules for a logarithmic ValueAxis3D. + * When a LogValueAxis3DFormatter is attached to a ValueAxis3D, the axis range + * cannot include negative values or the zero. + */ + +/*! + * \qmlproperty real LogValueAxis3DFormatter::base + * + * The \a base of the logarithm used to map axis values. If the base is non-zero, the parent axis + * segment count will be automatically adjusted whenever the axis formatter is recalculated. + * If you want the range to be divided into equal segments like normal value axis, set this + * property value to zero. + * + * The \a base has to be zero or positive value and not equal to one. + * Defaults to ten. + * + * \sa ValueAxis3D::segmentCount + */ + +/*! + * \qmlproperty bool LogValueAxis3DFormatter::autoSubGrid + * + * If this property value is set to \c true, the parent axis sub-segment count is adjusted + * automatically according to the base property value. The number of subsegments is set to + * base value minus one, rounded down. + * Defaults to \c true. + * + * \sa base, ValueAxis3D::subSegmentCount + */ + +/*! + * \qmlproperty bool LogValueAxis3DFormatter::showMaxLabel + * + * When the base property is non-zero, the segments that get automatically generated and depending + * on the range, the last segment is often smaller than the other segments. In extreme cases this + * can lead to overlapping labels on the last two grid lines. By setting this property to \c false, + * you can suppress showing the max label for the axis in cases where the segments do not exactly + * fit the axis. + * Defaults to \c true. + * + * \sa base, AbstractAxis3D::labels + */ + +/*! + * \internal + */ +QLogValue3DAxisFormatter::QLogValue3DAxisFormatter(QLogValue3DAxisFormatterPrivate *d, + QObject *parent) : + QValue3DAxisFormatter(d, parent) +{ +} + +/*! + * Constructs a new QLogValue3DAxisFormatter instance with optional \a parent. + */ +QLogValue3DAxisFormatter::QLogValue3DAxisFormatter(QObject *parent) : + QValue3DAxisFormatter(new QLogValue3DAxisFormatterPrivate(this), parent) +{ +} + +/*! + * Destroys QLogValue3DAxisFormatter. + */ +QLogValue3DAxisFormatter::~QLogValue3DAxisFormatter() +{ +} + +/*! + * \property QLogValue3DAxisFormatter::base + * + * The \a base of the logarithm used to map axis values. If the base is non-zero, the parent axis + * segment count will be automatically adjusted whenever the axis formatter is recalculated. + * If you want the range to be divided into equal segments like normal value axis, set this + * property value to zero. + * + * The \a base has to be zero or positive value and not equal to one. + * Defaults to ten. + * + * \sa QValue3DAxis::segmentCount + */ +void QLogValue3DAxisFormatter::setBase(qreal base) +{ + if (base < 0.0f || base == 1.0f) { + qWarning() << "Warning: The logarithm base must be greater than 0 and not equal to 1," + << "attempted:" << base; + return; + } + if (dptr()->m_base != base) { + dptr()->m_base = base; + markDirty(true); + emit baseChanged(base); + } +} + +qreal QLogValue3DAxisFormatter::base() const +{ + return dptrc()->m_base; +} + +/*! + * \property QLogValue3DAxisFormatter::autoSubGrid + * + * If this property value is set to \c true, the parent axis sub-segment count is adjusted + * automatically according to the base property value. The number of subsegments is set to + * base value minus one, rounded up. + * Defaults to \c true. + * + * \sa base, QValue3DAxis::subSegmentCount + */ +void QLogValue3DAxisFormatter::setAutoSubGrid(bool enabled) +{ + if (dptr()->m_autoSubGrid != enabled) { + dptr()->m_autoSubGrid = enabled; + markDirty(false); + emit autoSubGridChanged(enabled); + } +} + +bool QLogValue3DAxisFormatter::autoSubGrid() const +{ + return dptrc()->m_autoSubGrid; +} + +/*! + * \property QLogValue3DAxisFormatter::showMaxLabel + * + * When the base property is non-zero, the segments get automatically generated, and depending + * on the range, the last segment is often smaller than the other segments. In extreme cases this + * can lead to overlapping labels on the last two grid lines. By setting this property to \c false, + * you can suppress showing the max label for the axis in cases where the segments do not exactly + * fit the axis. + * Defaults to \c true. + * + * \sa base, QAbstract3DAxis::labels + */ +void QLogValue3DAxisFormatter::setShowMaxLabel(bool enabled) +{ + if (dptr()->m_showMaxLabel != enabled) { + dptr()->m_showMaxLabel = enabled; + markDirty(true); + emit showMaxLabelChanged(enabled); + } +} + +bool QLogValue3DAxisFormatter::showMaxLabel() const +{ + return dptrc()->m_showMaxLabel; +} + +/*! + * \internal + */ +bool QLogValue3DAxisFormatter::allowNegatives() const +{ + return false; +} + +/*! + * \internal + */ +bool QLogValue3DAxisFormatter::allowZero() const +{ + return false; +} + +/*! + * \internal + */ +QValue3DAxisFormatter *QLogValue3DAxisFormatter::createNewInstance() const +{ + return new QLogValue3DAxisFormatter(); +} + +/*! + * \internal + */ +void QLogValue3DAxisFormatter::recalculate() +{ + dptr()->recalculate(); +} + +/*! + * \internal + */ +float QLogValue3DAxisFormatter::positionAt(float value) const +{ + return dptrc()->positionAt(value); +} + +/*! + * \internal + */ +float QLogValue3DAxisFormatter::valueAt(float position) const +{ + return dptrc()->valueAt(position); +} + +/*! + * \internal + */ +void QLogValue3DAxisFormatter::populateCopy(QValue3DAxisFormatter ©) const +{ + QValue3DAxisFormatter::populateCopy(copy); + dptrc()->populateCopy(copy); +} + +/*! + * \internal + */ +QString QLogValue3DAxisFormatter::labelForIndex(int index) const +{ + return dptrc()->labelForIndex(index); +} + +/*! + * \internal + */ +QLogValue3DAxisFormatterPrivate *QLogValue3DAxisFormatter::dptr() +{ + return static_cast<QLogValue3DAxisFormatterPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QLogValue3DAxisFormatterPrivate *QLogValue3DAxisFormatter::dptrc() const +{ + return static_cast<const QLogValue3DAxisFormatterPrivate *>(d_ptr.data()); +} + +// QLogValue3DAxisFormatterPrivate +QLogValue3DAxisFormatterPrivate::QLogValue3DAxisFormatterPrivate(QLogValue3DAxisFormatter *q) + : QValue3DAxisFormatterPrivate(q), + m_base(10.0f), + m_logMin(0.0f), + m_logMax(0.0f), + m_logRangeNormalizer(0.0f), + m_autoSubGrid(true), + m_showMaxLabel(true), + m_evenSegments(true) +{ +} + +QLogValue3DAxisFormatterPrivate::~QLogValue3DAxisFormatterPrivate() +{ +} + +void QLogValue3DAxisFormatterPrivate::recalculate() +{ + if (m_base > 0.0) { + // Update parent axis segment counts + qreal logMin = qLn(qreal(m_min)) / qLn(m_base); + qreal logMax = qLn(qreal(m_max)) / qLn(m_base); + qreal logRangeNormalizer = logMax - logMin; + + int segmentCount = qCeil(logRangeNormalizer); + + m_axis->setSegmentCount(segmentCount); + if (m_autoSubGrid) { + int subSegmentCount = qCeil(m_base) - 1; + if (subSegmentCount < 1) + subSegmentCount = 1; + m_axis->setSubSegmentCount(subSegmentCount); + } + + resetPositionArrays(); + + // Calculate segment positions + for (int i = 0; i < segmentCount; i++) { + float gridValue = float(qreal(i) / logRangeNormalizer); + m_gridPositions[i] = gridValue; + m_labelPositions[i] = gridValue; + } + // Ensure max value doesn't suffer from any rounding errors + m_gridPositions[segmentCount] = 1.0f; + m_labelPositions[segmentCount] = 1.0f; + float lastDiff = 1.0f - m_labelPositions.at(segmentCount - 1); + float firstDiff = m_labelPositions.at(1) - m_labelPositions.at(0); + m_evenSegments = qFuzzyCompare(lastDiff, firstDiff); + } else { + // Grid lines and label positions are the same as the parent class, so call parent impl + // first to populate those + QValue3DAxisFormatterPrivate::doRecalculate(); + m_evenSegments = true; + } + + // When doing position/value mappings, base doesn't matter, so just use natural logarithm + m_logMin = qLn(qreal(m_min)); + m_logMax = qLn(qreal(m_max)); + m_logRangeNormalizer = m_logMax - m_logMin; + + // Subgrid line positions are logarithmically spaced + int subGridCount = m_axis->subSegmentCount() - 1; + if (subGridCount > 0) { + float firstSegmentRange = valueAt(m_gridPositions.at(1)) - m_min; + float subSegmentStep = firstSegmentRange / float(subGridCount + 1); + + // Since the logarithm has the same curvature across whole axis range, we can just calculate + // subgrid positions for the first segment and replicate them to other segments. + QVector<float> actualSubSegmentSteps(subGridCount); + + for (int i = 0; i < subGridCount; i++) { + float currentSubPosition = positionAt(m_min + ((i + 1) * subSegmentStep)); + actualSubSegmentSteps[i] = currentSubPosition; + } + + int segmentCount = m_axis->segmentCount(); + for (int i = 0; i < segmentCount; i++) { + for (int j = 0; j < subGridCount; j++) { + float position = m_gridPositions.at(i) + actualSubSegmentSteps.at(j); + if (position > 1.0f) + position = 1.0f; + m_subGridPositions[i][j] = position; + } + } + } +} + +void QLogValue3DAxisFormatterPrivate::populateCopy(QValue3DAxisFormatter ©) const +{ + QLogValue3DAxisFormatter *logFormatter = static_cast<QLogValue3DAxisFormatter *>(©); + QLogValue3DAxisFormatterPrivate *priv = logFormatter->dptr(); + + priv->m_base = m_base; + priv->m_logMin = m_logMin; + priv->m_logMax = m_logMax; + priv->m_logRangeNormalizer = m_logRangeNormalizer; +} + +float QLogValue3DAxisFormatterPrivate::positionAt(float value) const +{ + qreal logValue = qLn(qreal(value)); + float retval = float((logValue - m_logMin) / m_logRangeNormalizer); + + return retval; +} + +float QLogValue3DAxisFormatterPrivate::valueAt(float position) const +{ + qreal logValue = (qreal(position) * m_logRangeNormalizer) + m_logMin; + return float(qExp(logValue)); +} + +QString QLogValue3DAxisFormatterPrivate::labelForIndex(int index) const +{ + if (index == m_gridPositions.size() - 1 && !m_evenSegments && !m_showMaxLabel) + return QString(); + else + return QValue3DAxisFormatterPrivate::labelForIndex(index); +} + +QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/axis/qlogvalue3daxisformatter.h b/src/datavisualization/axis/qlogvalue3daxisformatter.h new file mode 100644 index 00000000..33466492 --- /dev/null +++ b/src/datavisualization/axis/qlogvalue3daxisformatter.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef QLOGVALUE3DAXISFORMATTER_H +#define QLOGVALUE3DAXISFORMATTER_H + +#include <QtDataVisualization/qvalue3daxisformatter.h> + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +class QLogValue3DAxisFormatterPrivate; + +class QT_DATAVISUALIZATION_EXPORT QLogValue3DAxisFormatter : public QValue3DAxisFormatter +{ + Q_OBJECT + + Q_PROPERTY(qreal base READ base WRITE setBase NOTIFY baseChanged) + Q_PROPERTY(bool autoSubGrid READ autoSubGrid WRITE setAutoSubGrid NOTIFY autoSubGridChanged) + Q_PROPERTY(bool showMaxLabel READ showMaxLabel WRITE setShowMaxLabel NOTIFY showMaxLabelChanged) + +protected: + explicit QLogValue3DAxisFormatter(QLogValue3DAxisFormatterPrivate *d, QObject *parent = 0); +public: + explicit QLogValue3DAxisFormatter(QObject *parent = 0); + virtual ~QLogValue3DAxisFormatter(); + + void setBase(qreal base); + qreal base() const; + void setAutoSubGrid(bool enabled); + bool autoSubGrid() const; + void setShowMaxLabel(bool enabled); + bool showMaxLabel() const; + +signals: + void baseChanged(qreal base); + void autoSubGridChanged(bool enabled); + void showMaxLabelChanged(bool enabled); + +protected: + virtual bool allowNegatives() const; + virtual bool allowZero() const; + virtual QValue3DAxisFormatter *createNewInstance() const; + virtual void recalculate(); + virtual float positionAt(float value) const; + virtual float valueAt(float position) const; + virtual void populateCopy(QValue3DAxisFormatter ©) const; + virtual QString labelForIndex(int index) const; + + QLogValue3DAxisFormatterPrivate *dptr(); + const QLogValue3DAxisFormatterPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QLogValue3DAxisFormatter) + + friend class QLogValue3DAxisFormatterPrivate; +}; + +QT_END_NAMESPACE_DATAVISUALIZATION + +#endif diff --git a/src/datavisualization/axis/qlogvalue3daxisformatter_p.h b/src/datavisualization/axis/qlogvalue3daxisformatter_p.h new file mode 100644 index 00000000..44b5c80c --- /dev/null +++ b/src/datavisualization/axis/qlogvalue3daxisformatter_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#include "datavisualizationglobal_p.h" +#include "qlogvalue3daxisformatter.h" +#include "qvalue3daxisformatter_p.h" + +#ifndef QLOGVALUE3DAXISFORMATTER_P_H +#define QLOGVALUE3DAXISFORMATTER_P_H + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +class QLogValue3DAxis; + +class QLogValue3DAxisFormatterPrivate : public QValue3DAxisFormatterPrivate +{ + Q_OBJECT + +public: + QLogValue3DAxisFormatterPrivate(QLogValue3DAxisFormatter *q); + virtual ~QLogValue3DAxisFormatterPrivate(); + + void recalculate(); + void populateCopy(QValue3DAxisFormatter ©) const; + + float positionAt(float value) const; + float valueAt(float position) const; + QString labelForIndex(int index) const; + +protected: + QLogValue3DAxisFormatter *qptr(); + + qreal m_base; + qreal m_logMin; + qreal m_logMax; + qreal m_logRangeNormalizer; + bool m_autoSubGrid; + bool m_showMaxLabel; + +private: + bool m_evenSegments; + + friend class QLogValue3DAxisFormatter; +}; + +QT_END_NAMESPACE_DATAVISUALIZATION + +#endif diff --git a/src/datavisualization/axis/qvalue3daxis.cpp b/src/datavisualization/axis/qvalue3daxis.cpp index 841349dd..b0b8caa6 100644 --- a/src/datavisualization/axis/qvalue3daxis.cpp +++ b/src/datavisualization/axis/qvalue3daxis.cpp @@ -105,7 +105,7 @@ void QValue3DAxis::setSegmentCount(int count) << count << "-> 1"; count = 1; } - if (dptr()->m_segmentCount != count){ + if (dptr()->m_segmentCount != count) { dptr()->m_segmentCount = count; dptr()->emitLabelsChanged(); emit segmentCountChanged(count); @@ -270,10 +270,8 @@ void QValue3DAxisPrivate::updateLabels() newLabels.reserve(m_segmentCount + 1); m_formatter->d_ptr->recalculate(); - for (int i = 0; i <= m_segmentCount; i++) { - float value = m_formatter->valueAt(m_formatter->gridPositions().at(i)); - newLabels.append(m_formatter->stringForValue(value, m_labelFormat)); - } + for (int i = 0; i <= m_segmentCount; i++) + newLabels.append(m_formatter->labelForIndex(i)); if (m_labels != newLabels) m_labels = newLabels; diff --git a/src/datavisualization/axis/qvalue3daxis_p.h b/src/datavisualization/axis/qvalue3daxis_p.h index ff281f0c..b49447af 100644 --- a/src/datavisualization/axis/qvalue3daxis_p.h +++ b/src/datavisualization/axis/qvalue3daxis_p.h @@ -46,11 +46,12 @@ public: virtual void setMin(float min); virtual void setMax (float max); + void emitLabelsChanged(); + signals: void formatterDirty(); protected: - void emitLabelsChanged(); virtual void updateLabels(); virtual bool allowZero(); diff --git a/src/datavisualization/axis/qvalue3daxisformatter.cpp b/src/datavisualization/axis/qvalue3daxisformatter.cpp index c8e0a662..b1183023 100644 --- a/src/datavisualization/axis/qvalue3daxisformatter.cpp +++ b/src/datavisualization/axis/qvalue3daxisformatter.cpp @@ -33,7 +33,7 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION * The base class has no public API beyond constructors and destructors. It is meant to be only * used internally. However, subclasses may implement public properties as needed. * - * \sa QLog3DAxisFormatter + * \sa QLogValue3DAxisFormatter */ /*! @@ -108,12 +108,15 @@ QValue3DAxisFormatter *QValue3DAxisFormatter::createNewInstance() const * any values needed for mapping between value and position. It is allowed to access * the parent axis from inside this function. * - * This method must be reimplemented in a subclass. + * This method must be reimplemented in a subclass. The resetPositionArrays() method must be called + * in the subclass implementation before the position arrays are recalculated. If the subclass + * implementation changes any parent axis values, these changes must be done before + * the resetPositionArrays() call. * * See gridPositions(), subGridPositions(), and labelPositions() documentation about the arrays * that need to be populated. * - * \sa gridPositions(), subGridPositions(), labelPositions(), axis() + * \sa gridPositions(), subGridPositions(), labelPositions(), axis(), resetPositionArrays() */ void QValue3DAxisFormatter::recalculate() { @@ -121,12 +124,26 @@ void QValue3DAxisFormatter::recalculate() } /*! + * The parent axis uses this method to request axis label strings for label \a index. + * Reimplement this method if default labeling is not sufficient. + * If an empty string is returned, the label is not shown. + * + * \return A string formatted using axis label formatter. + * + * \sa stringForValue() + */ +QString QValue3DAxisFormatter::labelForIndex(int index) const +{ + return d_ptr->labelForIndex(index); +} + +/*! * Reimplement this method in a subclass to resolve the formatted string for a given \a value * if the default formatting provided by QValue3DAxis::labelFormat property is not sufficient. * * \return the formatted label string using \a value and \a format. * - * \sa recalculate(), stringForValue(), QValue3DAxis::labelFormat + * \sa recalculate(), labelForIndex(), QValue3DAxis::labelFormat */ QString QValue3DAxisFormatter::stringForValue(float value, const QString &format) const { @@ -141,7 +158,7 @@ QString QValue3DAxisFormatter::stringForValue(float value, const QString &format * The returned value should be between 0.0 (for minimum value) and 1.0 (for maximum value), * inclusive, if the value is within the parent axis range. * - * \sa doRecalculate(), positionAt() + * \sa recalculate(), valueAt() */ float QValue3DAxisFormatter::positionAt(float value) const { @@ -156,7 +173,7 @@ float QValue3DAxisFormatter::positionAt(float value) const * The \a position value should be between 0.0 (for minimum value) and 1.0 (for maximum value), * inclusive to obtain values within the parent axis range. * - * \sa doRecalculate(), positionAt() + * \sa recalculate(), positionAt() */ float QValue3DAxisFormatter::valueAt(float position) const { @@ -176,13 +193,26 @@ void QValue3DAxisFormatter::populateCopy(QValue3DAxisFormatter ©) const } /*! + * Resets the position arrays based on values read from the parent axis. + * This must be called in recalculate method before the arrays are accessed in subclasses, + * but after any changes to the values of the parent axis. + * + * \sa gridPositions(), subGridPositions(), labelPositions(), axis(), recalculate() + */ +void QValue3DAxisFormatter::resetPositionArrays() +{ + d_ptr->resetPositionArrays(); +} + +/*! * Marks this formatter dirty, prompting the renderer to make a new copy of its cache on the next * renderer synchronization. This method should be called by a subclass whenever the formatter - * is changed in a way that affects the resolved values. + * is changed in a way that affects the resolved values. Specify \c true for \a labelsChange + * parameter if the change was such that it requires regenerating the parent axis label strings. */ -void QValue3DAxisFormatter::markDirty() +void QValue3DAxisFormatter::markDirty(bool labelsChange) { - d_ptr->markDirty(); + d_ptr->markDirty(labelsChange); } /*! @@ -197,10 +227,12 @@ QValue3DAxis *QValue3DAxisFormatter::axis() const } /*! - * \return Returns a reference to the array of normalized grid positions. + * \return a reference to the array of normalized grid positions. * The array size is equal to the segment count of the parent axis plus one. * The values should be between 0.0 (for minimum value) and 1.0 (for maximum value), inclusive. * The grid line at the index zero corresponds to the minimum value of the axis. + * + * \sa QValue3DAxis::segmentCount */ QVector<float> &QValue3DAxisFormatter::gridPositions() const { @@ -208,10 +240,12 @@ QVector<float> &QValue3DAxisFormatter::gridPositions() const } /*! - * \return Returns a reference to the array of normalized subgrid positions. - * The array size is equal to segment count of tha parent axis times subsegment count of the parent + * \return a reference to the array of normalized subgrid positions. + * The array size is equal to segment count of the parent axis times sub-segment count of the parent * axis minus one. * The values should be between 0.0 (for minimum value) and 1.0 (for maximum value), inclusive. + * + * \sa QValue3DAxis::segmentCount, QValue3DAxis::subSegmentCount */ QVector<QVector<float> > &QValue3DAxisFormatter::subGridPositions() const { @@ -219,10 +253,12 @@ QVector<QVector<float> > &QValue3DAxisFormatter::subGridPositions() const } /*! - * \return Returns a reference to the array of normalized label positions. + * \return a reference to the array of normalized label positions. * The array size is equal to the segment count of the parent axis plus one. * The values should be between 0.0 (for minimum value) and 1.0 (for maximum value), inclusive. * The label at the index zero corresponds to the minimum value of the axis. + * + * \sa QValue3DAxis::segmentCount, QAbstract3DAxis::labels */ QVector<float> &QValue3DAxisFormatter::labelPositions() const { @@ -250,40 +286,29 @@ void QValue3DAxisFormatterPrivate::recalculate() { // Only recalculate if we need to and have m_axis pointer. If we do not have // m_axis, either we are not attached to an axis or this is a renderer cache. - if (m_axis && m_needsRecalculate) + if (m_axis && m_needsRecalculate) { + m_min = m_axis->min(); + m_max = m_axis->max(); + m_rangeNormalizer = (m_max - m_min); + q_ptr->recalculate(); + m_needsRecalculate = false; + } } void QValue3DAxisFormatterPrivate::doRecalculate() { - m_needsRecalculate = false; - - m_gridPositions.clear(); - m_subGridPositions.clear(); - m_labelPositions.clear(); + resetPositionArrays(); int segmentCount = m_axis->segmentCount(); int subGridCount = m_axis->subSegmentCount() - 1; - m_min = m_axis->min(); - m_max = m_axis->max(); - m_rangeNormalizer = (m_max - m_min); - - m_gridPositions.resize(segmentCount + 1); float segmentStep = 1.0f / float(segmentCount); float subSegmentStep = 0; - - if (subGridCount > 0) { - subSegmentStep = segmentStep / (subGridCount + 1); - m_subGridPositions.resize(segmentCount); - for (int i = 0; i < segmentCount; i++) - m_subGridPositions[i].resize(subGridCount); - } - - m_labelPositions.resize(segmentCount + 1); + if (subGridCount > 0) + subSegmentStep = segmentStep / float(subGridCount + 1); // Calculate positions - for (int i = 0; i < segmentCount; i++) { float gridValue = segmentStep * i; m_gridPositions[i] = gridValue; @@ -316,6 +341,11 @@ void QValue3DAxisFormatterPrivate::doPopulateCopy(QValue3DAxisFormatterPrivate & copy.m_subGridPositions = m_subGridPositions; } +QString QValue3DAxisFormatterPrivate::labelForIndex(int index) const +{ + return q_ptr->stringForValue(q_ptr->valueAt(m_gridPositions.at(index)), m_axis->labelFormat()); +} + QString QValue3DAxisFormatterPrivate::stringForValue(float value, const QString &format) { if (m_previousLabelFormat.compare(format)) { @@ -343,20 +373,47 @@ void QValue3DAxisFormatterPrivate::setAxis(QValue3DAxis *axis) Q_ASSERT(axis); connect(axis, &QValue3DAxis::segmentCountChanged, - this, &QValue3DAxisFormatterPrivate::markDirty); + this, &QValue3DAxisFormatterPrivate::markDirtyNoLabelChange); connect(axis, &QValue3DAxis::subSegmentCountChanged, - this, &QValue3DAxisFormatterPrivate::markDirty); + this, &QValue3DAxisFormatterPrivate::markDirtyNoLabelChange); connect(axis, &QAbstract3DAxis::rangeChanged, - this, &QValue3DAxisFormatterPrivate::markDirty); + this, &QValue3DAxisFormatterPrivate::markDirtyNoLabelChange); m_axis = axis; } -void QValue3DAxisFormatterPrivate::markDirty() +void QValue3DAxisFormatterPrivate::resetPositionArrays() +{ + m_gridPositions.clear(); + m_subGridPositions.clear(); + m_labelPositions.clear(); + + int segmentCount = m_axis->segmentCount(); + int subGridCount = m_axis->subSegmentCount() - 1; + + m_gridPositions.resize(segmentCount + 1); + + if (subGridCount > 0) { + m_subGridPositions.resize(segmentCount); + for (int i = 0; i < segmentCount; i++) + m_subGridPositions[i].resize(subGridCount); + } + + m_labelPositions.resize(segmentCount + 1); +} + +void QValue3DAxisFormatterPrivate::markDirty(bool labelsChange) { m_needsRecalculate = true; + if (labelsChange) + m_axis->dptr()->emitLabelsChanged(); if (m_axis && m_axis->orientation() != QAbstract3DAxis::AxisOrientationNone) emit m_axis->dptr()->formatterDirty(); } +void QValue3DAxisFormatterPrivate::markDirtyNoLabelChange() +{ + markDirty(false); +} + QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/axis/qvalue3daxisformatter.h b/src/datavisualization/axis/qvalue3daxisformatter.h index 14ecdc15..6e0e873a 100644 --- a/src/datavisualization/axis/qvalue3daxisformatter.h +++ b/src/datavisualization/axis/qvalue3daxisformatter.h @@ -43,12 +43,14 @@ protected: virtual bool allowZero() const; virtual QValue3DAxisFormatter *createNewInstance() const; virtual void recalculate(); + virtual QString labelForIndex(int index) const; virtual QString stringForValue(float value, const QString &format) const; virtual float positionAt(float value) const; virtual float valueAt(float position) const; virtual void populateCopy(QValue3DAxisFormatter ©) const; - void markDirty(); + void resetPositionArrays(); + void markDirty(bool labelsChange = false); QValue3DAxis *axis() const; QVector<float> &gridPositions() const; @@ -67,6 +69,7 @@ private: friend class Surface3DRenderer; friend class SurfaceObject; friend class QValue3DAxisFormatterPrivate; + friend class QLogValue3DAxisFormatter; friend class QValue3DAxis; friend class QValue3DAxisPrivate; friend class AxisRenderCache; diff --git a/src/datavisualization/axis/qvalue3daxisformatter_p.h b/src/datavisualization/axis/qvalue3daxisformatter_p.h index d9f90934..74b6f20f 100644 --- a/src/datavisualization/axis/qvalue3daxisformatter_p.h +++ b/src/datavisualization/axis/qvalue3daxisformatter_p.h @@ -51,14 +51,17 @@ public: void populateCopy(QValue3DAxisFormatter ©); void doPopulateCopy(QValue3DAxisFormatterPrivate ©); + QString labelForIndex(int index) const; QString stringForValue(float value, const QString &format); float positionAt(float value) const; float valueAt(float position) const; void setAxis(QValue3DAxis *axis); + void resetPositionArrays(); + void markDirty(bool labelsChange); public slots: - void markDirty(); + void markDirtyNoLabelChange(); protected: QValue3DAxisFormatter *q_ptr; diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp index a6c086aa..7f905243 100644 --- a/src/datavisualization/engine/abstract3dcontroller.cpp +++ b/src/datavisualization/engine/abstract3dcontroller.cpp @@ -183,6 +183,31 @@ void Abstract3DController::synchDataToRenderer() m_changeTracker.selectionModeChanged = false; } + if (m_changeTracker.axisXFormatterChanged) { + m_changeTracker.axisXFormatterChanged = false; + if (m_axisX->type() & QAbstract3DAxis::AxisTypeValue) { + QValue3DAxis *valueAxisX = static_cast<QValue3DAxis *>(m_axisX); + m_renderer->updateAxisFormatter(QAbstract3DAxis::AxisOrientationX, + valueAxisX->formatter()); + } + } + if (m_changeTracker.axisYFormatterChanged) { + m_changeTracker.axisYFormatterChanged = false; + if (m_axisY->type() & QAbstract3DAxis::AxisTypeValue) { + QValue3DAxis *valueAxisY = static_cast<QValue3DAxis *>(m_axisY); + m_renderer->updateAxisFormatter(QAbstract3DAxis::AxisOrientationY, + valueAxisY->formatter()); + } + } + if (m_changeTracker.axisZFormatterChanged) { + m_changeTracker.axisZFormatterChanged = false; + if (m_axisZ->type() & QAbstract3DAxis::AxisTypeValue) { + QValue3DAxis *valueAxisZ = static_cast<QValue3DAxis *>(m_axisZ); + m_renderer->updateAxisFormatter(QAbstract3DAxis::AxisOrientationZ, + valueAxisZ->formatter()); + } + } + if (m_changeTracker.axisXTypeChanged) { m_renderer->updateAxisType(QAbstract3DAxis::AxisOrientationX, m_axisX->type()); m_changeTracker.axisXTypeChanged = false; @@ -326,31 +351,6 @@ void Abstract3DController::synchDataToRenderer() } } - if (m_changeTracker.axisXFormatterChanged) { - m_changeTracker.axisXFormatterChanged = false; - if (m_axisX->type() & QAbstract3DAxis::AxisTypeValue) { - QValue3DAxis *valueAxisX = static_cast<QValue3DAxis *>(m_axisX); - m_renderer->updateAxisFormatter(QAbstract3DAxis::AxisOrientationX, - valueAxisX->formatter()); - } - } - if (m_changeTracker.axisYFormatterChanged) { - m_changeTracker.axisYFormatterChanged = false; - if (m_axisY->type() & QAbstract3DAxis::AxisTypeValue) { - QValue3DAxis *valueAxisY = static_cast<QValue3DAxis *>(m_axisY); - m_renderer->updateAxisFormatter(QAbstract3DAxis::AxisOrientationY, - valueAxisY->formatter()); - } - } - if (m_changeTracker.axisZFormatterChanged) { - m_changeTracker.axisZFormatterChanged = false; - if (m_axisZ->type() & QAbstract3DAxis::AxisTypeValue) { - QValue3DAxis *valueAxisZ = static_cast<QValue3DAxis *>(m_axisZ); - m_renderer->updateAxisFormatter(QAbstract3DAxis::AxisOrientationZ, - valueAxisZ->formatter()); - } - } - if (m_isSeriesVisibilityDirty || m_isSeriesVisualsDirty) { m_renderer->updateSeries(m_seriesList, m_isSeriesVisibilityDirty); m_isSeriesVisibilityDirty = false; diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp index c5e265aa..f0aec0cc 100644 --- a/src/datavisualization/engine/abstract3drenderer.cpp +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -345,6 +345,7 @@ void Abstract3DRenderer::updateAxisFormatter(QAbstract3DAxis::AxisOrientation or cache.setCtrlFormatter(formatter); } formatter->d_ptr->populateCopy(*(cache.formatter())); + cache.markPositionsDirty(); } void Abstract3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh) diff --git a/src/datavisualization/engine/axisrendercache_p.h b/src/datavisualization/engine/axisrendercache_p.h index eede9917..f37857d9 100644 --- a/src/datavisualization/engine/axisrendercache_p.h +++ b/src/datavisualization/engine/axisrendercache_p.h @@ -33,6 +33,7 @@ #include "labelitem_p.h" #include "qabstract3daxis_p.h" #include "drawer_p.h" +#include <QtCore/QPointer> QT_BEGIN_NAMESPACE_DATAVISUALIZATION @@ -66,11 +67,11 @@ public: m_formatter = formatter; m_positionsDirty = true; } inline QValue3DAxisFormatter *formatter() const { return m_formatter; } - inline void setCtrlFormatter(const QValue3DAxisFormatter *formatter) + inline void setCtrlFormatter(QValue3DAxisFormatter *formatter) { m_ctrlFormatter = formatter; } - inline const QValue3DAxisFormatter *ctrlFormatter() const { return m_ctrlFormatter; } + inline QValue3DAxisFormatter *ctrlFormatter() const { return m_ctrlFormatter; } inline LabelItem &titleItem() { return m_titleItem; } inline QList<LabelItem *> &labelItems() { return m_labelItems; } @@ -80,6 +81,7 @@ public: inline int labelCount() { return m_adjustedLabelPositions.size(); } void updateAllPositions(); inline bool positionsDirty() const { return m_positionsDirty; } + inline void markPositionsDirty() { m_positionsDirty = true; } inline void setTranslate(float translate) { m_translate = translate; m_positionsDirty = true; } inline float translate() { return m_translate; } inline void setScale(float scale) { m_scale = scale; m_positionsDirty = true; } @@ -106,7 +108,7 @@ private: QString m_labelFormat; QFont m_font; QValue3DAxisFormatter *m_formatter; - const QValue3DAxisFormatter *m_ctrlFormatter; + QPointer<QValue3DAxisFormatter> m_ctrlFormatter; // Renderer items Drawer *m_drawer; // Not owned diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index ed99e49e..9ce80081 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -900,6 +900,7 @@ void Surface3DRenderer::drawSlicedScene() // Vertical lines QVector3D gridLineScaleY(gridLineWidth, backgroundMargin, gridLineWidth); + gridLineCount = sliceCache.gridLineCount(); for (int line = 0; line < gridLineCount; line++) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; diff --git a/tests/barstest/chart.cpp b/tests/barstest/chart.cpp index cf044a45..c6c7678d 100644 --- a/tests/barstest/chart.cpp +++ b/tests/barstest/chart.cpp @@ -20,13 +20,14 @@ #include "custominputhandler.h" #include <QtDataVisualization/qcategory3daxis.h> #include <QtDataVisualization/qvalue3daxis.h> -#include <QtDataVisualization/qvalue3daxisformatter.h> +#include <QtDataVisualization/qlogvalue3daxisformatter.h> #include <QtDataVisualization/qbardataproxy.h> #include <QtDataVisualization/q3dscene.h> #include <QtDataVisualization/q3dcamera.h> #include <QtDataVisualization/q3dtheme.h> #include <QtDataVisualization/q3dinputhandler.h> -#include <QTime> +#include <QtCore/QTime> +#include <QtCore/qmath.h> using namespace QtDataVisualization; @@ -43,7 +44,7 @@ GraphModifier::GraphModifier(Q3DBars *barchart, QColorDialog *colorDialog) m_barSpacingX(0.1f), m_barSpacingZ(0.1f), m_fontSize(20), - m_segments(4), + m_segments(10), m_subSegments(3), m_minval(-16.0f), m_maxval(20.0f), @@ -222,6 +223,8 @@ GraphModifier::GraphModifier(Q3DBars *barchart, QColorDialog *colorDialog) &GraphModifier::handleValueAxisChanged); QObject::connect(m_graph, &Q3DBars::primarySeriesChanged, this, &GraphModifier::handlePrimarySeriesChanged); + QObject::connect(m_temperatureAxis, &QAbstract3DAxis::labelsChanged, this, + &GraphModifier::handleValueAxisLabelsChanged); QObject::connect(&m_insertRemoveTimer, &QTimer::timeout, this, &GraphModifier::insertRemoveTimerTimeout); @@ -1047,15 +1050,85 @@ void GraphModifier::toggleRotation() void GraphModifier::useLogAxis() { - // TODO proper log axis test + static int counter = -1; + static QLogValue3DAxisFormatter *logFormatter = new QLogValue3DAxisFormatter; + + counter++; + + switch (counter) { + case 0: { + qDebug() << "Case" << counter << ": Default log axis"; + logFormatter = new QLogValue3DAxisFormatter; + m_graph->valueAxis()->setFormatter(logFormatter); + m_graph->valueAxis()->setRange(1.0f, 1200.0f); + m_graph->valueAxis()->setLabelFormat(QStringLiteral("%.3f")); + break; + } + case 1: { + qDebug() << "Case" << counter << ": Hide max label"; + logFormatter->setShowMaxLabel(false); + break; + } + case 2: { + qDebug() << "Case" << counter << ": Try to hide subgrid unsuccessfully"; + m_graph->valueAxis()->setSubSegmentCount(1); + break; + } + case 3: { + qDebug() << "Case" << counter << ": Hide subgrid property"; + logFormatter->setAutoSubGrid(false); + m_graph->valueAxis()->setSubSegmentCount(1); + break; + } + case 4: { + qDebug() << "Case" << counter << ": Different base: 2"; + logFormatter->setBase(2.0f); + logFormatter->setAutoSubGrid(true); + break; + } + case 5: { + qDebug() << "Case" << counter << ": Different base: 16"; + logFormatter->setBase(16.0f); + break; + } + case 6: { + qDebug() << "Case" << counter << ": Invalid bases"; + logFormatter->setBase(-1.0f); + logFormatter->setBase(1.0f); + break; + } + case 7: { + qDebug() << "Case" << counter << ": Zero base"; + logFormatter->setBase(0.0f); + break; + } + case 8: { + qDebug() << "Case" << counter << ": Explicit ranges and segments"; + int segmentCount = 6; + int base = 4; + m_graph->valueAxis()->setSegmentCount(segmentCount); + m_graph->valueAxis()->setSubSegmentCount(base - 1); + m_graph->valueAxis()->setRange(1.0f / float(base * base), qPow(base, segmentCount - 2)); + break; + } + case 9: { + qDebug() << "Case" << counter << ": Negative range"; + m_graph->valueAxis()->setRange(-20.0f, 50.0f); + break; + } + case 10: { + qDebug() << "Case" << counter << ": Non-integer base"; + logFormatter->setBase(3.3f); + logFormatter->setAutoSubGrid(true); + break; + } + default: + qDebug() << "Resetting logaxis test"; + counter = -1; + break; + } -// // Change y-axis to log axis -// QValue3DAxis *logAxis = new QValue3DAxis; -// logAxis->formatter()->setBase(10); -// logAxis->setSegmentCount(5); -// logAxis->setRange(1, 100000); - // m_graph->setValueAxis(logAxis); } void GraphModifier::changeValueAxisFormat(const QString & text) @@ -1063,6 +1136,21 @@ void GraphModifier::changeValueAxisFormat(const QString & text) m_graph->valueAxis()->setLabelFormat(text); } +void GraphModifier::changeLogBase(const QString &text) +{ + QLogValue3DAxisFormatter *formatter = + qobject_cast<QLogValue3DAxisFormatter *>(m_graph->valueAxis()->formatter()); + if (formatter) + formatter->setBase(qreal(text.toDouble())); +} + +void GraphModifier::changeValueAxisSegments(int value) +{ + qDebug() << __FUNCTION__ << value; + m_segments = value; + m_graph->valueAxis()->setSegmentCount(m_segments); +} + void GraphModifier::insertRemoveTimerTimeout() { if (m_insertRemoveStep < 32) { @@ -1119,6 +1207,11 @@ void GraphModifier::triggerRotation() } } +void GraphModifier::handleValueAxisLabelsChanged() +{ + qDebug() << __FUNCTION__; +} + void GraphModifier::setBackgroundEnabled(int enabled) { m_graph->activeTheme()->setBackgroundEnabled(bool(enabled)); diff --git a/tests/barstest/chart.h b/tests/barstest/chart.h index 304103cd..52c46a8c 100644 --- a/tests/barstest/chart.h +++ b/tests/barstest/chart.h @@ -87,6 +87,7 @@ public: void toggleRotation(); void useLogAxis(); void changeValueAxisFormat(const QString & text); + void changeLogBase(const QString & text); public slots: void flipViews(); @@ -96,6 +97,7 @@ public slots: void shadowQualityUpdatedByVisual(QAbstract3DGraph::ShadowQuality shadowQuality); void handleSelectionChange(const QPoint &position); void setUseNullInputHandler(bool useNull); + void changeValueAxisSegments(int value); void handleRowAxisChanged(QCategory3DAxis *axis); void handleColumnAxisChanged(QCategory3DAxis *axis); @@ -105,6 +107,7 @@ public slots: void insertRemoveTimerTimeout(); void triggerSelection(); void triggerRotation(); + void handleValueAxisLabelsChanged(); signals: void shadowQualityChanged(int quality); diff --git a/tests/barstest/main.cpp b/tests/barstest/main.cpp index edf61e2e..f4cd02f7 100644 --- a/tests/barstest/main.cpp +++ b/tests/barstest/main.cpp @@ -33,6 +33,7 @@ #include <QPainter> #include <QColorDialog> #include <QLineEdit> +#include <QSpinBox> int main(int argc, char **argv) { @@ -292,6 +293,11 @@ int main(int argc, char **argv) shadowQuality->setCurrentIndex(5); QLineEdit *valueAxisFormatEdit = new QLineEdit(widget); + QLineEdit *logBaseEdit = new QLineEdit(widget); + QSpinBox *valueAxisSegmentsSpin = new QSpinBox(widget); + valueAxisSegmentsSpin->setMinimum(1); + valueAxisSegmentsSpin->setMaximum(100); + valueAxisSegmentsSpin->setValue(10); vLayout->addWidget(addDataButton, 0, Qt::AlignTop); vLayout->addWidget(addMultiDataButton, 0, Qt::AlignTop); @@ -320,7 +326,6 @@ int main(int argc, char **argv) vLayout->addWidget(ownThemeButton, 0, Qt::AlignTop); vLayout->addWidget(primarySeriesTestsButton, 0, Qt::AlignTop); vLayout->addWidget(toggleRotationButton, 0, Qt::AlignTop); - vLayout->addWidget(logAxisButton, 0, Qt::AlignTop); vLayout->addWidget(gradientBtoYPB, 1, Qt::AlignTop); vLayout2->addWidget(staticCheckBox, 0, Qt::AlignTop); @@ -349,7 +354,12 @@ int main(int argc, char **argv) vLayout2->addWidget(new QLabel(QStringLiteral("Adjust font size")), 0, Qt::AlignTop); vLayout2->addWidget(fontSizeSlider, 0, Qt::AlignTop); vLayout2->addWidget(new QLabel(QStringLiteral("Value axis format")), 0, Qt::AlignTop); - vLayout2->addWidget(valueAxisFormatEdit, 1, Qt::AlignTop); + vLayout2->addWidget(valueAxisFormatEdit, 0, Qt::AlignTop); + vLayout2->addWidget(new QLabel(QStringLiteral("Log axis base")), 0, Qt::AlignTop); + vLayout2->addWidget(logBaseEdit, 0, Qt::AlignTop); + vLayout2->addWidget(new QLabel(QStringLiteral("Value axis segments")), 0, Qt::AlignTop); + vLayout2->addWidget(valueAxisSegmentsSpin, 0, Qt::AlignTop); + vLayout->addWidget(logAxisButton, 1, Qt::AlignTop); // TODO: Add example for setMeshFileName widget->show(); @@ -387,6 +397,10 @@ int main(int argc, char **argv) &GraphModifier::changeFontSize); QObject::connect(valueAxisFormatEdit, &QLineEdit::textEdited, modifier, &GraphModifier::changeValueAxisFormat); + QObject::connect(logBaseEdit, &QLineEdit::textEdited, modifier, + &GraphModifier::changeLogBase); + QObject::connect(valueAxisSegmentsSpin, SIGNAL(valueChanged(int)), modifier, + SLOT(changeValueAxisSegments(int))); QObject::connect(multiScaleButton, &QPushButton::clicked, modifier, &GraphModifier::toggleMultiseriesScaling); |